#include "imageblur.h" #include #include //边缘算法 //i: 偏移 //x: 当前位置 //w: 范围(位置范围是0 -> w) //返回: x周边第i个的位置 template T ImageBlurUtility::Edge(T i, T x, T w) { //x周边第i个的位置 T i_k = x + i; if (i_k < 0) i_k = -x; else if (i_k >= w) i_k = w - 1 - x; else i_k = i; return i_k; } //归一化 void ImageBlurUtility::Normalization(std::vector &kernels) { double sum = std::accumulate(kernels.begin(), kernels.end(), 0.0); if(qFuzzyCompare(sum, 0)) return; if(qFuzzyCompare(sum, 1.0)) return; std::transform(kernels.begin(), kernels.end(), kernels.begin(), [sum](double x){ return x/sum; }); } //得到高斯核(把radius带入高斯公式求解) std::vector GaussBlur::GetKernels(int radius) { static const double SQRT2PI = qSqrt(2.0 * 3.14159265358979323); double sigma = (double)radius / 3.0; double sigma2 = 2.0 * sigma * sigma; double sigmap = sigma * SQRT2PI; std::vector kernels; for(int i = -radius; i <= radius; ++i) { kernels.push_back(qExp(-(double)(i * i) / sigma2) / sigmap); } return kernels; } void GaussBlur::Blur(QImage &image, int radius) { std::vector kernels = GetKernels(radius); ImageBlurUtility::Normalization(kernels); typedef ImageBlurUtility::pixel_t pixel; typedef ImageBlurUtility::buff_t buff; pixel *pData = (pixel*)image.bits(); //栈的空间小, 所以这里buffer分配到堆 const int size = image.width() * image.height(); buff *pBuffer = new buff[size]; for(int inx = 0, y = 0; y < image.height(); ++y) { for(int x = 0; x < image.width(); ++x, ++inx) { for(int n = 0, i = -radius; i <= radius; ++i, ++n) { long i_k = ImageBlurUtility::Edge(i, x, image.width()); long inx_k = inx + i_k; pBuffer[inx].r += pData[inx_k].r() * kernels[n]; pBuffer[inx].g += pData[inx_k].g() * kernels[n]; pBuffer[inx].b += pData[inx_k].b() * kernels[n]; pBuffer[inx].a += pData[inx_k].a() * kernels[n]; } } } for(int inx = 0, x = 0; x < image.width(); ++x) { for(int y = 0; y < image.height(); ++y) { inx = y * image.width() + x; buff buffer; for(int n = 0, i = -radius; i <= radius; ++i, ++n) { int i_k = ImageBlurUtility::Edge(i, y, image.height()); int inx_k = inx + i_k * image.width(); buffer.r += pBuffer[inx_k].r * kernels[n]; buffer.g += pBuffer[inx_k].g * kernels[n]; buffer.b += pBuffer[inx_k].b * kernels[n]; buffer.a += pBuffer[inx_k].a * kernels[n]; } pData[inx].Set(buffer.Red(), buffer.Green(), buffer.Blue(), buffer.Alpha()); //pData[inx].Set(Clamp(r), Clamp(g), Clamp(b), Clamp(a)); } } delete[] pBuffer; }