1*877f5f92SZhongYang #include "stdafx.h"
26f7f8ab0SZhong Yang #include "GaussBlur.h"
36f7f8ab0SZhong Yang
46f7f8ab0SZhong Yang
CGaussBlur()56f7f8ab0SZhong Yang CGaussBlur::CGaussBlur()
66f7f8ab0SZhong Yang {
76f7f8ab0SZhong Yang }
86f7f8ab0SZhong Yang
96f7f8ab0SZhong Yang
~CGaussBlur()106f7f8ab0SZhong Yang CGaussBlur::~CGaussBlur()
116f7f8ab0SZhong Yang {
126f7f8ab0SZhong Yang if (m_pTempl != NULL)
136f7f8ab0SZhong Yang free(m_pTempl);
146f7f8ab0SZhong Yang }
156f7f8ab0SZhong Yang
SetSigma(double sigma)166f7f8ab0SZhong Yang void CGaussBlur::SetSigma(double sigma)
176f7f8ab0SZhong Yang {
186f7f8ab0SZhong Yang int i;
196f7f8ab0SZhong Yang m_sigma = sigma;
206f7f8ab0SZhong Yang m_r = (int)(m_sigma * 3 + 0.5);
216f7f8ab0SZhong Yang if (m_r <= 0) m_r = 1;
226f7f8ab0SZhong Yang
23*877f5f92SZhongYang //分配模板
246f7f8ab0SZhong Yang LPVOID pOldTempl = m_pTempl;
256f7f8ab0SZhong Yang m_pTempl = (double*)realloc(m_pTempl, sizeof(double) * (m_r + 1));
266f7f8ab0SZhong Yang
27*877f5f92SZhongYang //分配失败?
286f7f8ab0SZhong Yang if (m_pTempl == NULL)
296f7f8ab0SZhong Yang {
306f7f8ab0SZhong Yang if (pOldTempl != NULL)
316f7f8ab0SZhong Yang free(pOldTempl);
326f7f8ab0SZhong Yang
336f7f8ab0SZhong Yang return;
346f7f8ab0SZhong Yang }
356f7f8ab0SZhong Yang
36*877f5f92SZhongYang //计算 p[0] 灰度值为1 的模板面
376f7f8ab0SZhong Yang double k1 = (double)((-0.5) / (m_sigma * m_sigma));
386f7f8ab0SZhong Yang for (i = 0; i <= m_r; i++)
396f7f8ab0SZhong Yang m_pTempl[i] = exp(k1 * i * i);
406f7f8ab0SZhong Yang
41*877f5f92SZhongYang //计算模板加权总和
426f7f8ab0SZhong Yang double sum = m_pTempl[0];
436f7f8ab0SZhong Yang for (i = 1; i <= m_r; i++)
446f7f8ab0SZhong Yang {
456f7f8ab0SZhong Yang sum += (m_pTempl[i] * 2);
466f7f8ab0SZhong Yang }
476f7f8ab0SZhong Yang
48*877f5f92SZhongYang //归一化
49*877f5f92SZhongYang sum = (double)(1.0 / sum); //取倒数
506f7f8ab0SZhong Yang for (i = 0; i <= m_r; i++)
516f7f8ab0SZhong Yang m_pTempl[i] *= sum;
526f7f8ab0SZhong Yang }
536f7f8ab0SZhong Yang
Reset()546f7f8ab0SZhong Yang void CGaussBlur::Reset()
556f7f8ab0SZhong Yang {
566f7f8ab0SZhong Yang m_r = -1;
576f7f8ab0SZhong Yang m_sigma = (double)(-1.0);
586f7f8ab0SZhong Yang if (m_pTempl != NULL)
596f7f8ab0SZhong Yang {
606f7f8ab0SZhong Yang free(m_pTempl);
616f7f8ab0SZhong Yang m_pTempl = NULL;
626f7f8ab0SZhong Yang }
636f7f8ab0SZhong Yang }
646f7f8ab0SZhong Yang
DoGaussBlur(const CImage & image_src,CImage & image_dest)656f7f8ab0SZhong Yang void CGaussBlur::DoGaussBlur(const CImage & image_src, CImage & image_dest)
666f7f8ab0SZhong Yang {
676f7f8ab0SZhong Yang if (image_src.IsNull())
686f7f8ab0SZhong Yang return;
696f7f8ab0SZhong Yang int width = image_src.GetWidth();
706f7f8ab0SZhong Yang int height = image_src.GetHeight();
716f7f8ab0SZhong Yang int bpp = image_src.GetBPP();
726f7f8ab0SZhong Yang if (!image_dest.IsNull())
736f7f8ab0SZhong Yang image_dest.Destroy();
746f7f8ab0SZhong Yang image_dest.Create(width, height, bpp);
756f7f8ab0SZhong Yang Filter(image_src.GetPixelAddress(0, height - 1), image_dest.GetPixelAddress(0, height - 1), width, height, bpp);
766f7f8ab0SZhong Yang }
776f7f8ab0SZhong Yang
Filter(LPCVOID pSrc,LPVOID pDest,int width,int height,int bpp)786f7f8ab0SZhong Yang bool CGaussBlur::Filter(LPCVOID pSrc, LPVOID pDest, int width, int height, int bpp)
796f7f8ab0SZhong Yang {
806f7f8ab0SZhong Yang if (pSrc == NULL || pDest == NULL)
816f7f8ab0SZhong Yang return false;
826f7f8ab0SZhong Yang
83*877f5f92SZhongYang //只能处理 8, 24, 32 bpp
846f7f8ab0SZhong Yang if (bpp != 24 && bpp != 8 && bpp != 32)
856f7f8ab0SZhong Yang return false;
866f7f8ab0SZhong Yang
876f7f8ab0SZhong Yang if (m_r < 0 || m_pTempl == NULL)
886f7f8ab0SZhong Yang return false;
896f7f8ab0SZhong Yang
906f7f8ab0SZhong Yang int absHeight = (height >= 0) ? height : (-height);
916f7f8ab0SZhong Yang int stride = (width * bpp + 31) / 32 * 4;
926f7f8ab0SZhong Yang int pixelSize = bpp / 8;
936f7f8ab0SZhong Yang
94*877f5f92SZhongYang //申请缓冲区,存储中间结果
956f7f8ab0SZhong Yang LPVOID pTemp = malloc(stride * absHeight);
966f7f8ab0SZhong Yang if (pTemp == NULL)
976f7f8ab0SZhong Yang return false;
986f7f8ab0SZhong Yang
996f7f8ab0SZhong Yang CGaussBlurThreadParams params;
1006f7f8ab0SZhong Yang
1016f7f8ab0SZhong Yang params.pSrc = (LPBYTE)pSrc;
1026f7f8ab0SZhong Yang params.pDest = (LPBYTE)pTemp;
1036f7f8ab0SZhong Yang params.width = width;
1046f7f8ab0SZhong Yang params.height = absHeight;
1056f7f8ab0SZhong Yang params.stride = stride;
1066f7f8ab0SZhong Yang params.pixelSize = pixelSize;
1076f7f8ab0SZhong Yang params.r = m_r;
1086f7f8ab0SZhong Yang params.pTempl = m_pTempl;
1096f7f8ab0SZhong Yang params.rowBegin = 0;
1106f7f8ab0SZhong Yang params.rowEnd = absHeight;
1116f7f8ab0SZhong Yang params.bHorz = true;
1126f7f8ab0SZhong Yang
1136f7f8ab0SZhong Yang if (bpp == 8)
1146f7f8ab0SZhong Yang GaussBlurThreadProc8(¶ms);
1156f7f8ab0SZhong Yang else
1166f7f8ab0SZhong Yang GaussBlurThreadProc24(¶ms);
1176f7f8ab0SZhong Yang
1186f7f8ab0SZhong Yang
1196f7f8ab0SZhong Yang params.pSrc = (LPBYTE)pTemp;
1206f7f8ab0SZhong Yang params.pDest = (LPBYTE)pDest;
1216f7f8ab0SZhong Yang params.bHorz = false;
1226f7f8ab0SZhong Yang
1236f7f8ab0SZhong Yang if (bpp == 8)
1246f7f8ab0SZhong Yang GaussBlurThreadProc8(¶ms);
1256f7f8ab0SZhong Yang else
1266f7f8ab0SZhong Yang GaussBlurThreadProc24(¶ms);
1276f7f8ab0SZhong Yang
1286f7f8ab0SZhong Yang free(pTemp);
1296f7f8ab0SZhong Yang return true;
1306f7f8ab0SZhong Yang }
1316f7f8ab0SZhong Yang
GaussBlurThreadProc8(LPVOID lpParameters)1326f7f8ab0SZhong Yang DWORD CGaussBlur::GaussBlurThreadProc8(LPVOID lpParameters)
1336f7f8ab0SZhong Yang {
1346f7f8ab0SZhong Yang CGaussBlurThreadParams *pInfo = (CGaussBlurThreadParams*)lpParameters;
1356f7f8ab0SZhong Yang
1366f7f8ab0SZhong Yang double result;
1376f7f8ab0SZhong Yang int row, col, subRow, subCol, MaxVal, x, x1;
1386f7f8ab0SZhong Yang LPINT pSubVal, pRefVal;
1396f7f8ab0SZhong Yang
1406f7f8ab0SZhong Yang if (pInfo->bHorz)
1416f7f8ab0SZhong Yang {
142*877f5f92SZhongYang //水平方向
1436f7f8ab0SZhong Yang pSubVal = &subCol;
1446f7f8ab0SZhong Yang pRefVal = &col;
1456f7f8ab0SZhong Yang MaxVal = pInfo->width - 1;
1466f7f8ab0SZhong Yang }
1476f7f8ab0SZhong Yang else
1486f7f8ab0SZhong Yang {
149*877f5f92SZhongYang //垂直方向
1506f7f8ab0SZhong Yang pSubVal = &subRow;
1516f7f8ab0SZhong Yang pRefVal = &row;
1526f7f8ab0SZhong Yang MaxVal = pInfo->height - 1;
1536f7f8ab0SZhong Yang }
1546f7f8ab0SZhong Yang
1556f7f8ab0SZhong Yang LPBYTE pSrcPixel = NULL;
1566f7f8ab0SZhong Yang LPBYTE pDestPixel = NULL;
1576f7f8ab0SZhong Yang
1586f7f8ab0SZhong Yang for (row = pInfo->rowBegin; row < pInfo->rowEnd; ++row)
1596f7f8ab0SZhong Yang {
1606f7f8ab0SZhong Yang for (col = 0; col < pInfo->width; ++col)
1616f7f8ab0SZhong Yang {
1626f7f8ab0SZhong Yang pDestPixel = pInfo->pDest + pInfo->stride * row + col;
1636f7f8ab0SZhong Yang
1646f7f8ab0SZhong Yang result = 0;
1656f7f8ab0SZhong Yang
1666f7f8ab0SZhong Yang subRow = row;
1676f7f8ab0SZhong Yang subCol = col;
1686f7f8ab0SZhong Yang
1696f7f8ab0SZhong Yang for (x = -pInfo->r; x <= pInfo->r; x++)
1706f7f8ab0SZhong Yang {
171*877f5f92SZhongYang //边界处理
1726f7f8ab0SZhong Yang x1 = (x >= 0) ? x : (-x);
1736f7f8ab0SZhong Yang *pSubVal = *pRefVal + x;
1746f7f8ab0SZhong Yang if (*pSubVal < 0) *pSubVal = 0;
1756f7f8ab0SZhong Yang else if (*pSubVal > MaxVal) *pSubVal = MaxVal;
1766f7f8ab0SZhong Yang
1776f7f8ab0SZhong Yang pSrcPixel = pInfo->pSrc + pInfo->stride * subRow + subCol;
1786f7f8ab0SZhong Yang
1796f7f8ab0SZhong Yang result += *pSrcPixel * pInfo->pTempl[x1];
1806f7f8ab0SZhong Yang }
1816f7f8ab0SZhong Yang *pDestPixel = (BYTE)result;
1826f7f8ab0SZhong Yang }
1836f7f8ab0SZhong Yang }
1846f7f8ab0SZhong Yang return 0;
1856f7f8ab0SZhong Yang }
1866f7f8ab0SZhong Yang
GaussBlurThreadProc24(LPVOID lpParameters)1876f7f8ab0SZhong Yang DWORD CGaussBlur::GaussBlurThreadProc24(LPVOID lpParameters)
1886f7f8ab0SZhong Yang {
1896f7f8ab0SZhong Yang CGaussBlurThreadParams *pInfo = (CGaussBlurThreadParams*)lpParameters;
1906f7f8ab0SZhong Yang
1916f7f8ab0SZhong Yang double result[3];
1926f7f8ab0SZhong Yang int row, col, subRow, subCol, MaxVal, x, x1;
1936f7f8ab0SZhong Yang LPINT pSubVal, pRefVal;
1946f7f8ab0SZhong Yang
1956f7f8ab0SZhong Yang if (pInfo->bHorz)
1966f7f8ab0SZhong Yang {
197*877f5f92SZhongYang //水平方向
1986f7f8ab0SZhong Yang pSubVal = &subCol;
1996f7f8ab0SZhong Yang pRefVal = &col;
2006f7f8ab0SZhong Yang MaxVal = pInfo->width - 1;
2016f7f8ab0SZhong Yang }
2026f7f8ab0SZhong Yang else
2036f7f8ab0SZhong Yang {
204*877f5f92SZhongYang //垂直方向
2056f7f8ab0SZhong Yang pSubVal = &subRow;
2066f7f8ab0SZhong Yang pRefVal = &row;
2076f7f8ab0SZhong Yang MaxVal = pInfo->height - 1;
2086f7f8ab0SZhong Yang }
2096f7f8ab0SZhong Yang
2106f7f8ab0SZhong Yang LPBYTE pSrcPixel = NULL;
2116f7f8ab0SZhong Yang LPBYTE pDestPixel = NULL;
2126f7f8ab0SZhong Yang
2136f7f8ab0SZhong Yang for (row = pInfo->rowBegin; row < pInfo->rowEnd; ++row)
2146f7f8ab0SZhong Yang {
2156f7f8ab0SZhong Yang for (col = 0; col < pInfo->width; ++col)
2166f7f8ab0SZhong Yang {
2176f7f8ab0SZhong Yang pDestPixel = pInfo->pDest + pInfo->stride * row + pInfo->pixelSize * col;
2186f7f8ab0SZhong Yang
2196f7f8ab0SZhong Yang result[0] = 0;
2206f7f8ab0SZhong Yang result[1] = 0;
2216f7f8ab0SZhong Yang result[2] = 0;
2226f7f8ab0SZhong Yang
2236f7f8ab0SZhong Yang subRow = row;
2246f7f8ab0SZhong Yang subCol = col;
2256f7f8ab0SZhong Yang
2266f7f8ab0SZhong Yang for (x = -pInfo->r; x <= pInfo->r; x++)
2276f7f8ab0SZhong Yang {
2286f7f8ab0SZhong Yang x1 = (x >= 0) ? x : (-x);
2296f7f8ab0SZhong Yang *pSubVal = *pRefVal + x;
2306f7f8ab0SZhong Yang
231*877f5f92SZhongYang //边界处理:Photoshop 采用的是方法1。
232*877f5f92SZhongYang //方法1:取边缘像素(图像边缘像素向内部扩散!)
2336f7f8ab0SZhong Yang if (*pSubVal < 0) *pSubVal = 0;
2346f7f8ab0SZhong Yang else if (*pSubVal > MaxVal) *pSubVal = MaxVal;
2356f7f8ab0SZhong Yang
236*877f5f92SZhongYang //方法2:取当前像素(使得越靠近图像边缘的地方越清晰)
2376f7f8ab0SZhong Yang /*
2386f7f8ab0SZhong Yang if(*pSubVal < 0 || *pSubVal > MaxVal)
2396f7f8ab0SZhong Yang *pSubVal = *pRefVal;
2406f7f8ab0SZhong Yang */
2416f7f8ab0SZhong Yang
2426f7f8ab0SZhong Yang pSrcPixel = pInfo->pSrc + pInfo->stride * subRow + pInfo->pixelSize * subCol;
2436f7f8ab0SZhong Yang
2446f7f8ab0SZhong Yang result[0] += pSrcPixel[0] * pInfo->pTempl[x1];
2456f7f8ab0SZhong Yang result[1] += pSrcPixel[1] * pInfo->pTempl[x1];
2466f7f8ab0SZhong Yang result[2] += pSrcPixel[2] * pInfo->pTempl[x1];
2476f7f8ab0SZhong Yang }
2486f7f8ab0SZhong Yang pDestPixel[0] = (BYTE)result[0];
2496f7f8ab0SZhong Yang pDestPixel[1] = (BYTE)result[1];
2506f7f8ab0SZhong Yang pDestPixel[2] = (BYTE)result[2];
2516f7f8ab0SZhong Yang }
2526f7f8ab0SZhong Yang }
2536f7f8ab0SZhong Yang return 0;
2546f7f8ab0SZhong Yang }
255