1 #include "stdafx.h" 2 #include "GaussBlur.h" 3 4 5 CGaussBlur::CGaussBlur() 6 { 7 } 8 9 10 CGaussBlur::~CGaussBlur() 11 { 12 if (m_pTempl != NULL) 13 free(m_pTempl); 14 } 15 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 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 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 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(¶ms); 115 else 116 GaussBlurThreadProc24(¶ms); 117 118 119 params.pSrc = (LPBYTE)pTemp; 120 params.pDest = (LPBYTE)pDest; 121 params.bHorz = false; 122 123 if (bpp == 8) 124 GaussBlurThreadProc8(¶ms); 125 else 126 GaussBlurThreadProc24(¶ms); 127 128 free(pTemp); 129 return true; 130 } 131 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 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