2#include "helper/SDIBHelper.h"
4#define RGB2GRAY(r, g, b) (((b)*117 + (g)*601 + (r)*306) >> 10)
18template <
class Mode,
class Param>
19bool ColorTransform(DIBINFO *pDib, Mode mode,
const Param ¶m)
21 if (NULL == pDib || NULL == pDib->pBits)
26 SMap<DWORD, DWORD> cache;
27 int nPixels = pDib->nWid * pDib->nHei;
28 LPBYTE pBit = pDib->pBits;
29 for (
int i = 0; i < nPixels; i++, pBit += 4)
31 DWORD crFrom = *(DWORD *)pBit;
32 SMap<DWORD, DWORD>::CPair *p = cache.Lookup(crFrom);
35 memcpy(pBit, &p->m_value, 4);
40 cache[crFrom] = *(DWORD *)pBit;
48static void GrayMode(BYTE *pColor,
const int &)
50 pColor[0] = pColor[1] = pColor[2] = RGB2GRAY(pColor[0], pColor[1], pColor[2]);
61static void FillColorizeParam(COLORIZEPARAM ¶m, BYTE hue, BYTE sat,
float fBlend)
65 SASSERT(fBlend >= 0.0f && fBlend <= 1.0f);
66 param.a0 = (int)(fBlend * 256);
67 param.a1 = 256 - param.a0;
78#define HSLUNDEFINED (HSLMAX * 2 / 3)
80static RGBQUAD RGBtoHSL(RGBQUAD lRGBColor)
85 WORD Rdelta, Gdelta, Bdelta;
88 G = lRGBColor.rgbGreen;
89 B = lRGBColor.rgbBlue;
91 cMax = smax(smax(R, G), B);
92 cMin = smin(smin(R, G), B);
93 L = (BYTE)((((cMax + cMin) * HSLMAX) + RGBMAX) / (2 * RGBMAX));
102 if (L <= (HSLMAX / 2))
103 S = (BYTE)((((cMax - cMin) * HSLMAX) + ((cMax + cMin) / 2)) / (cMax + cMin));
105 S = (BYTE)((((cMax - cMin) * HSLMAX) + ((2 * RGBMAX - cMax - cMin) / 2)) / (2 * RGBMAX - cMax - cMin));
107 Rdelta = (WORD)((((cMax - R) * (HSLMAX / 6)) + ((cMax - cMin) / 2)) / (cMax - cMin));
108 Gdelta = (WORD)((((cMax - G) * (HSLMAX / 6)) + ((cMax - cMin) / 2)) / (cMax - cMin));
109 Bdelta = (WORD)((((cMax - B) * (HSLMAX / 6)) + ((cMax - cMin) / 2)) / (cMax - cMin));
112 H = (BYTE)(Bdelta - Gdelta);
114 H = (BYTE)((HSLMAX / 3) + Rdelta - Bdelta);
116 H = (BYTE)(((2 * HSLMAX) / 3) + Gdelta - Rdelta);
122 RGBQUAD hsl = { L, S, H, 0 };
127static RGBQUAD RGBtoRGBQUAD(COLORREF cr)
130 c.rgbRed = GetRValue(cr);
131 c.rgbGreen = GetGValue(cr);
132 c.rgbBlue = GetBValue(cr);
133 c.rgbReserved = GetAValue(cr);
137static COLORREF RGBQUADtoRGB(RGBQUAD c)
139 return RGBA(c.rgbRed, c.rgbGreen, c.rgbBlue, c.rgbReserved);
143static float HueToRGB(
float n1,
float n2,
float hue)
154 rValue = n1 + (n2 - n1) * hue / 60.0f;
158 rValue = n1 + (n2 - n1) * (240 - hue) / 60;
166static RGBQUAD HSLtoRGB(RGBQUAD lHSLColor)
173 h = (float)lHSLColor.rgbRed * 360.0f / 255.0f;
174 s = (float)lHSLColor.rgbGreen / 255.0f;
175 l = (float)lHSLColor.rgbBlue / 255.0f;
186 r = g = b = (BYTE)(l * 255.0f);
190 r = (BYTE)(HueToRGB(m1, m2, h + 120) * 255.0f);
191 g = (BYTE)(HueToRGB(m1, m2, h) * 255.0f);
192 b = (BYTE)(HueToRGB(m1, m2, h - 120) * 255.0f);
195 RGBQUAD rgb = { b, g, r, 0 };
199static void ColorizeMode(BYTE *pArgb,
const COLORIZEPARAM ¶m)
201 BYTE blue = pArgb[0], green = pArgb[1], red = pArgb[2], alpha = pArgb[3];
207 red = (red * 255) / alpha;
208 green = (green * 255) / alpha;
209 blue = (blue * 255) / alpha;
211 RGBQUAD pixel = { blue, green, red };
215 RGBQUAD color = RGBtoHSL(pixel);
216 color.rgbRed = param.hue;
217 color.rgbGreen = param.sat;
218 pixel = HSLtoRGB(color);
220 green = pixel.rgbGreen;
221 blue = pixel.rgbBlue;
225 RGBQUAD color = pixel;
227 hsl.rgbRed = param.hue;
228 hsl.rgbGreen = param.sat;
229 hsl.rgbBlue = (BYTE)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);
231 red = (BYTE)((hsl.rgbRed * param.a0 + color.rgbRed * param.a1) >> 8);
232 blue = (BYTE)((hsl.rgbBlue * param.a0 + color.rgbBlue * param.a1) >> 8);
233 green = (BYTE)((hsl.rgbGreen * param.a0 + color.rgbGreen * param.a1) >> 8);
237 red = (red * alpha) / 255;
238 green = (green * alpha) / 255;
239 blue = (blue * alpha) / 255;
248 RGBQUAD color = RGBtoRGBQUAD(crRef);
249 RGBQUAD hsl = RGBtoHSL(color);
252 BYTE byAlpha = GetAValue(crRef);
254 fBlend = byAlpha * 1.0f / 255;
256 FillColorizeParam(param, hsl.rgbRed, hsl.rgbGreen, fBlend);
260 bool bRet = ColorTransform(&di, ColorizeMode, param);
268 RGBQUAD color = RGBtoRGBQUAD(crRef);
269 RGBQUAD hsl = RGBtoHSL(color);
273 BYTE byAlpha = GetAValue(crRef);
275 fBlend = byAlpha * 1.0f / 255;
277 FillColorizeParam(param, hsl.rgbRed, hsl.rgbGreen, fBlend);
279 RGBQUAD argbTarget = RGBtoRGBQUAD(crTarget);
280 ColorizeMode((BYTE *)&argbTarget, param);
281 crTarget = RGBQUADtoRGB(argbTarget);
288 bool bRet = ColorTransform(&di, GrayMode, 0);
293static COLORREF CalcAvarageRectColor(
const DIBINFO &di, RECT rc)
295 LPBYTE pLine = di.pBits + di.nWid * rc.top * 4;
296 if (rc.right > (
int)di.nWid)
298 if (rc.bottom > (
int)di.nHei)
300 int nWid = rc.right - rc.left;
301 int nHei = rc.bottom - rc.top;
303 int r = 0, g = 0, b = 0;
304 for (
int y = 0; y < nHei; y++)
306 LPBYTE p = pLine + rc.left * 4;
307 for (
int x = 0; x < nWid; x++)
314 pLine += di.nWid * 4;
316 int nPixels = (nWid * nHei);
323static int RgbCmp(
const void *p1,
const void *p2)
325 const BYTE *cr1 = (
const BYTE *)p1;
326 const BYTE *cr2 = (
const BYTE *)p2;
327 int deltaR = ((int)cr2[0] - (int)cr1[0]);
328 int deltaG = ((int)cr2[1] - (int)cr1[1]);
329 int deltaB = ((int)cr2[2] - (int)cr1[2]);
330 return deltaR + deltaG + deltaB;
337 int xBlocks = (di.nWid + nBlockSize - 1) / nBlockSize;
338 int yBlocks = (di.nHei + nBlockSize - 1) / nBlockSize;
340 int nBlocks = xBlocks * yBlocks;
341 COLORREF *pAvgColors =
new COLORREF[nBlocks];
343 CRect rcBlock(0, 0, nBlockSize, nBlockSize);
345 for (
int y = 0; y < yBlocks; y++)
347 for (
int x = 0; x < xBlocks; x++)
349 pAvgColors[iBlock++] = CalcAvarageRectColor(di, rcBlock);
350 rcBlock.OffsetRect(nBlockSize, 0);
353 rcBlock.OffsetRect(0, nBlockSize);
356 qsort(pAvgColors, nBlocks,
sizeof(COLORREF), RgbCmp);
358 int nThrows = nBlocks * (100 - nPercent) / 200;
359 int iBegin = nThrows;
360 int iEnd = nBlocks - nThrows;
362 int r = 0, g = 0, b = 0;
363 for (
int i = iBegin; i < iEnd; i++)
365 BYTE *p = (BYTE *)(pAvgColors + i);
371 r /= (iEnd - iBegin);
372 g /= (iEnd - iBegin);
373 b /= (iEnd - iBegin);
static bool GrayImage(IBitmapS *pBmp)
将位图转换为灰度图像
static bool Colorize(IBitmapS *pBmp, COLORREF crRef)
对位图进行着色处理
static COLORREF CalcAvarageColor(IBitmapS *pBmp, int nPercent=90, int nBlockSize=5)
计算图片的平均颜色
UINT Height() SCONST PURE
Retrieves the height of the bitmap.
UINT Width() SCONST PURE
Retrieves the width of the bitmap.
LPVOID LockPixelBits() PURE
Locks the pixel bits of the bitmap for writing.
void UnlockPixelBits(LPVOID pBuf) PURE
Unlocks the pixel bits of the bitmap.