xref: /MusicPlayer2/MusicPlayer2/GaussBlur.cpp (revision 877f5f92b251a01591a4960c885129aa589a8135)
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(&params);
1156f7f8ab0SZhong Yang 	else
1166f7f8ab0SZhong Yang 		GaussBlurThreadProc24(&params);
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(&params);
1256f7f8ab0SZhong Yang 	else
1266f7f8ab0SZhong Yang 		GaussBlurThreadProc24(&params);
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