xref: /MusicPlayer2/MusicPlayer2/GaussBlur.cpp (revision 877f5f92b251a01591a4960c885129aa589a8135)
1 #include "stdafx.h"
2 #include "GaussBlur.h"
3 
4 
CGaussBlur()5 CGaussBlur::CGaussBlur()
6 {
7 }
8 
9 
~CGaussBlur()10 CGaussBlur::~CGaussBlur()
11 {
12 	if (m_pTempl != NULL)
13 		free(m_pTempl);
14 }
15 
SetSigma(double sigma)16 void CGaussBlur::SetSigma(double sigma)
17 {
18 	int i;
19 	m_sigma = sigma;
20 	m_r = (int)(m_sigma * 3 + 0.5);
21 	if (m_r <= 0) m_r = 1;
22 
23 	//分配模板
24 	LPVOID pOldTempl = m_pTempl;
25 	m_pTempl = (double*)realloc(m_pTempl, sizeof(double) * (m_r + 1));
26 
27 	//分配失败?
28 	if (m_pTempl == NULL)
29 	{
30 		if (pOldTempl != NULL)
31 			free(pOldTempl);
32 
33 		return;
34 	}
35 
36 	//计算 p[0] 灰度值为1 的模板面
37 	double k1 = (double)((-0.5) / (m_sigma * m_sigma));
38 	for (i = 0; i <= m_r; i++)
39 		m_pTempl[i] = exp(k1 * i * i);
40 
41 	//计算模板加权总和
42 	double sum = m_pTempl[0];
43 	for (i = 1; i <= m_r; i++)
44 	{
45 		sum += (m_pTempl[i] * 2);
46 	}
47 
48 	//归一化
49 	sum = (double)(1.0 / sum); //取倒数
50 	for (i = 0; i <= m_r; i++)
51 		m_pTempl[i] *= sum;
52 }
53 
Reset()54 void CGaussBlur::Reset()
55 {
56 	m_r = -1;
57 	m_sigma = (double)(-1.0);
58 	if (m_pTempl != NULL)
59 	{
60 		free(m_pTempl);
61 		m_pTempl = NULL;
62 	}
63 }
64 
DoGaussBlur(const CImage & image_src,CImage & image_dest)65 void CGaussBlur::DoGaussBlur(const CImage & image_src, CImage & image_dest)
66 {
67 	if (image_src.IsNull())
68 		return;
69 	int width = image_src.GetWidth();
70 	int height = image_src.GetHeight();
71 	int bpp = image_src.GetBPP();
72 	if (!image_dest.IsNull())
73 		image_dest.Destroy();
74 	image_dest.Create(width, height, bpp);
75 	Filter(image_src.GetPixelAddress(0, height - 1), image_dest.GetPixelAddress(0, height - 1), width, height, bpp);
76 }
77 
Filter(LPCVOID pSrc,LPVOID pDest,int width,int height,int bpp)78 bool CGaussBlur::Filter(LPCVOID pSrc, LPVOID pDest, int width, int height, int bpp)
79 {
80 	if (pSrc == NULL || pDest == NULL)
81 		return false;
82 
83 	//只能处理 8, 24, 32 bpp
84 	if (bpp != 24 && bpp != 8 && bpp != 32)
85 		return false;
86 
87 	if (m_r < 0 || m_pTempl == NULL)
88 		return false;
89 
90 	int absHeight = (height >= 0) ? height : (-height);
91 	int stride = (width * bpp + 31) / 32 * 4;
92 	int pixelSize = bpp / 8;
93 
94 	//申请缓冲区,存储中间结果
95 	LPVOID pTemp = malloc(stride * absHeight);
96 	if (pTemp == NULL)
97 		return false;
98 
99 	CGaussBlurThreadParams params;
100 
101 	params.pSrc = (LPBYTE)pSrc;
102 	params.pDest = (LPBYTE)pTemp;
103 	params.width = width;
104 	params.height = absHeight;
105 	params.stride = stride;
106 	params.pixelSize = pixelSize;
107 	params.r = m_r;
108 	params.pTempl = m_pTempl;
109 	params.rowBegin = 0;
110 	params.rowEnd = absHeight;
111 	params.bHorz = true;
112 
113 	if (bpp == 8)
114 		GaussBlurThreadProc8(&params);
115 	else
116 		GaussBlurThreadProc24(&params);
117 
118 
119 	params.pSrc = (LPBYTE)pTemp;
120 	params.pDest = (LPBYTE)pDest;
121 	params.bHorz = false;
122 
123 	if (bpp == 8)
124 		GaussBlurThreadProc8(&params);
125 	else
126 		GaussBlurThreadProc24(&params);
127 
128 	free(pTemp);
129 	return true;
130 }
131 
GaussBlurThreadProc8(LPVOID lpParameters)132 DWORD CGaussBlur::GaussBlurThreadProc8(LPVOID lpParameters)
133 {
134 	CGaussBlurThreadParams *pInfo = (CGaussBlurThreadParams*)lpParameters;
135 
136 	double result;
137 	int row, col, subRow, subCol, MaxVal, x, x1;
138 	LPINT pSubVal, pRefVal;
139 
140 	if (pInfo->bHorz)
141 	{
142 		//水平方向
143 		pSubVal = &subCol;
144 		pRefVal = &col;
145 		MaxVal = pInfo->width - 1;
146 	}
147 	else
148 	{
149 		//垂直方向
150 		pSubVal = &subRow;
151 		pRefVal = &row;
152 		MaxVal = pInfo->height - 1;
153 	}
154 
155 	LPBYTE pSrcPixel = NULL;
156 	LPBYTE pDestPixel = NULL;
157 
158 	for (row = pInfo->rowBegin; row < pInfo->rowEnd; ++row)
159 	{
160 		for (col = 0; col < pInfo->width; ++col)
161 		{
162 			pDestPixel = pInfo->pDest + pInfo->stride * row + col;
163 
164 			result = 0;
165 
166 			subRow = row;
167 			subCol = col;
168 
169 			for (x = -pInfo->r; x <= pInfo->r; x++)
170 			{
171 				//边界处理
172 				x1 = (x >= 0) ? x : (-x);
173 				*pSubVal = *pRefVal + x;
174 				if (*pSubVal < 0) *pSubVal = 0;
175 				else if (*pSubVal > MaxVal) *pSubVal = MaxVal;
176 
177 				pSrcPixel = pInfo->pSrc + pInfo->stride * subRow + subCol;
178 
179 				result += *pSrcPixel * pInfo->pTempl[x1];
180 			}
181 			*pDestPixel = (BYTE)result;
182 		}
183 	}
184 	return 0;
185 }
186 
GaussBlurThreadProc24(LPVOID lpParameters)187 DWORD CGaussBlur::GaussBlurThreadProc24(LPVOID lpParameters)
188 {
189 	CGaussBlurThreadParams *pInfo = (CGaussBlurThreadParams*)lpParameters;
190 
191 	double result[3];
192 	int row, col, subRow, subCol, MaxVal, x, x1;
193 	LPINT pSubVal, pRefVal;
194 
195 	if (pInfo->bHorz)
196 	{
197 		//水平方向
198 		pSubVal = &subCol;
199 		pRefVal = &col;
200 		MaxVal = pInfo->width - 1;
201 	}
202 	else
203 	{
204 		//垂直方向
205 		pSubVal = &subRow;
206 		pRefVal = &row;
207 		MaxVal = pInfo->height - 1;
208 	}
209 
210 	LPBYTE pSrcPixel = NULL;
211 	LPBYTE pDestPixel = NULL;
212 
213 	for (row = pInfo->rowBegin; row < pInfo->rowEnd; ++row)
214 	{
215 		for (col = 0; col < pInfo->width; ++col)
216 		{
217 			pDestPixel = pInfo->pDest + pInfo->stride * row + pInfo->pixelSize * col;
218 
219 			result[0] = 0;
220 			result[1] = 0;
221 			result[2] = 0;
222 
223 			subRow = row;
224 			subCol = col;
225 
226 			for (x = -pInfo->r; x <= pInfo->r; x++)
227 			{
228 				x1 = (x >= 0) ? x : (-x);
229 				*pSubVal = *pRefVal + x;
230 
231 				//边界处理:Photoshop 采用的是方法1。
232 				//方法1:取边缘像素(图像边缘像素向内部扩散!)
233 				if (*pSubVal < 0) *pSubVal = 0;
234 				else if (*pSubVal > MaxVal) *pSubVal = MaxVal;
235 
236 				//方法2:取当前像素(使得越靠近图像边缘的地方越清晰)
237 				/*
238 				if(*pSubVal < 0 || *pSubVal > MaxVal)
239 				*pSubVal = *pRefVal;
240 				*/
241 
242 				pSrcPixel = pInfo->pSrc + pInfo->stride * subRow + pInfo->pixelSize * subCol;
243 
244 				result[0] += pSrcPixel[0] * pInfo->pTempl[x1];
245 				result[1] += pSrcPixel[1] * pInfo->pTempl[x1];
246 				result[2] += pSrcPixel[2] * pInfo->pTempl[x1];
247 			}
248 			pDestPixel[0] = (BYTE)result[0];
249 			pDestPixel[1] = (BYTE)result[1];
250 			pDestPixel[2] = (BYTE)result[2];
251 		}
252 	}
253 	return 0;
254 }
255