| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 | #include "imageblur.h"#include <QtMath>#include <QDebug>//边缘算法//i: 偏移//x: 当前位置//w: 范围(位置范围是0 -> w)//返回: x周边第i个的位置template <typename T>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<double> &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<double> 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<double> 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<double> 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<int>(r), Clamp<int>(g), Clamp<int>(b), Clamp<int>(a));        }    }    delete[] pBuffer;}
 |