Created
March 27, 2013 20:49
-
-
Save silvercircle/5257898 to your computer and use it in GitHub Desktop.
colorizing bitmaps
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* colorize an image item (both standalone items with their own bitmap and glyph items). | |
* | |
* @param item image item to colorize | |
* @param clr color to use (note: BGRA format required, although, alpha is ignored) | |
* @param hue hue adjustment (in degrees, -180 .. +180 | |
* @param saturation scalar value (0.0 ... 1.0) | |
* @param value scalar value (0.0 ... 1.0) | |
* | |
* note: this isn't performance critical as it only runs at skin loading time or when | |
* the user changes colorization options, never during rendering. | |
* | |
* if clr == 0, hsv transformation will be applied, otherwise it's rgb colorization. | |
*/ | |
void Gfx::colorizeGlyph(TImageItem *item, const COLORREF clr, float hue, float saturation, float value) | |
{ | |
LONG stride = 0, line, pixel; | |
HBITMAP hBitmap = 0; | |
LONG x, y, x1, y1; | |
BITMAP bmp = {0}; | |
DWORD dwLen; | |
BYTE* p, *pOrig, *pLine, alpha; | |
float v_s_u, v_s_w, r, g, b; | |
if(0 == clr) { // do hsv transformation | |
v_s_u = value * saturation * cos(hue * M_PI/180); | |
v_s_w = value * saturation * sin(hue * M_PI/180); | |
} | |
else { // rgb colorization | |
BYTE rValue = GetRValue(clr); | |
BYTE gValue = GetGValue(clr); | |
BYTE bValue = GetBValue(clr); | |
r = (float)rValue / 2.55; | |
g = (float)gValue / 2.55; | |
b = (float)bValue / 2.55; | |
} | |
if(item) { | |
/* | |
* colorize a rectangular glyph | |
*/ | |
if(item->dwFlags & IMAGE_GLYPH) { | |
hBitmap = Skin::glyphItem->hbm; | |
x = item->glyphMetrics[0]; | |
y = item->glyphMetrics[1]; | |
x1 = x + item->glyphMetrics[2] - 1; | |
y1 = y + item->glyphMetrics[3] - 1; | |
GetObject(hBitmap, sizeof(bmp), &bmp); | |
if (bmp.bmBitsPixel != 32) | |
return; | |
dwLen = bmp.bmWidth * bmp.bmHeight * 4; | |
p = (BYTE *)malloc(dwLen); | |
memset(p, 0, dwLen); | |
if (p == NULL) | |
return; | |
pOrig = p; | |
GetBitmapBits(hBitmap, dwLen, p); | |
stride = bmp.bmWidthBytes; | |
p += ((y * stride) + (4 * x)); | |
for(line = y; line <= y1; line++) { | |
pLine = p; | |
for(pixel = x; pixel <= x1; pixel++) { | |
alpha = p[3]; | |
if(alpha > 0) { | |
if(0 == clr) | |
hsvTransformPixel(p, value, v_s_u, v_s_w, alpha); | |
else | |
rgbTransformPixel(p, r, g, b, alpha); | |
} | |
p += 4; | |
} | |
p = pLine + stride; | |
} | |
SetBitmapBits(hBitmap, dwLen, pOrig); | |
free(pOrig); | |
} | |
else if (item->hbm) { | |
GetObject(item->hbm, sizeof(bmp), &bmp); | |
if (bmp.bmBitsPixel != 32) | |
return; | |
dwLen = bmp.bmWidth * bmp.bmHeight * 4; | |
p = (BYTE *)malloc(dwLen); | |
memset(p, 0, dwLen); | |
if (p == NULL) | |
return; | |
pOrig = p; | |
GetBitmapBits(item->hbm, dwLen, p); | |
for(pixel = 0; pixel < (bmp.bmWidth * bmp.bmHeight); pixel++) { | |
alpha = p[3]; | |
if(alpha > 0) { | |
if(0 == clr) | |
hsvTransformPixel(p, value, v_s_u, v_s_w, alpha); | |
else | |
rgbTransformPixel(p, r, g, b, alpha); | |
} | |
p += 4; | |
} | |
SetBitmapBits(item->hbm, dwLen, pOrig); | |
free(pOrig); | |
} | |
} | |
} | |
/** | |
* transform a single pixel from hsv into rgb color space | |
* | |
* @param *p BYTE* - pointer to a single pixel in (BGRA pixel format!) | |
* @param value const float - the v component | |
* @param v_s_u const float - precalculated h/s factor | |
* @param v_s_w const float | |
* @param alpha const BYTE - alpha value for the pixel (0..255) | |
*/ | |
inline void Gfx::hsvTransformPixel(BYTE *p, const float value, const float v_s_u, const float v_s_w, const BYTE alpha) | |
{ | |
// ain't matrices beautiful? :) | |
float r = (.299 * value +.701 * v_s_u +.168 * v_s_w) * p[2] + (.587 * value -.587 * v_s_u +.330 * v_s_w) * p[1] + (.114 * value -.114 * v_s_u -.497 * v_s_w) * p[0]; | |
float g = (.299 * value -.299 * v_s_u -.328 * v_s_w) * p[2] + (.587 * value +.413 * v_s_u +.035 * v_s_w) * p[1] + (.114 * value -.114 * v_s_u +.292 * v_s_w) * p[0]; | |
float b = (.299 * value -.3 * v_s_u +1.25 * v_s_w) * p[2]+ (.587* value -.588 * v_s_u -1.05 * v_s_w) * p[1] + (.114 * value +.886 * v_s_u -.203 * v_s_w) * p[0]; | |
/* | |
* premultiply | |
*/ | |
p[0] = (int)b * alpha/255; | |
p[1] = (int)g * alpha/255; | |
p[2] = (int)r * alpha/255; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment