graphics.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. #include "./main.h"
  2. #include "./graphics.h"
  3. #include <math.h>
  4. #include <strsafe.h>
  5. INT GetColorDistance(COLORREF rgb1, COLORREF rgb2)
  6. {
  7. return (1000 * ((GetRValue(rgb1) - GetRValue(rgb2)) +
  8. (GetGValue(rgb1) - GetGValue(rgb2)) +
  9. (GetBValue(rgb1) - GetBValue(rgb2))))/ (3 * 255);
  10. }
  11. COLORREF GetDarkerColor(COLORREF rgb1, COLORREF rgb2)
  12. {
  13. INT g1 = (GetRValue(rgb1)*299 + GetGValue(rgb1)*587 + GetBValue(rgb1)*114);
  14. INT g2 = (GetRValue(rgb2)*299 + GetGValue(rgb2)*587 + GetBValue(rgb2)*114);
  15. return (g1 < g2) ? rgb1 : rgb2;
  16. }
  17. COLORREF BlendColors(COLORREF rgbTop, COLORREF rgbBottom, INT alpha)
  18. {
  19. if (alpha > 254) return rgbTop;
  20. if (alpha < 0) return rgbBottom;
  21. WORD k = (((255 - alpha)*255 + 127)/255);
  22. return RGB( (GetRValue(rgbTop)*alpha + k*GetRValue(rgbBottom) + 127)/255,
  23. (GetGValue(rgbTop)*alpha + k*GetGValue(rgbBottom) + 127)/255,
  24. (GetBValue(rgbTop)*alpha + k*GetBValue(rgbBottom) + 127)/255);
  25. }
  26. BOOL Image_Colorize(BYTE *pPixels, LONG cx, LONG cy, WORD bpp, COLORREF rgbBk, COLORREF rgbFg, BOOL removeAlpha)
  27. {
  28. LONG pitch, x;
  29. INT step;
  30. BYTE rFg, gFg, bFg;
  31. LPBYTE cursor, line;
  32. if (bpp < 24) return FALSE;
  33. step = (bpp>>3);
  34. pitch = cx*step;
  35. while (pitch%4) pitch++;
  36. rFg = GetRValue(rgbFg); gFg = GetGValue(rgbFg); bFg = GetBValue(rgbFg);
  37. INT bK = (bFg - GetBValue(rgbBk));
  38. INT gK = (gFg - GetGValue(rgbBk));
  39. INT rK = (rFg - GetRValue(rgbBk));
  40. if (24 == bpp)
  41. {
  42. for (line = pPixels; cy-- != 0; line += pitch )
  43. {
  44. for (x = cx, cursor = line; x-- != 0; cursor += 3)
  45. {
  46. cursor[0] = bFg - (bK*(255 - cursor[0])>>8);
  47. cursor[1] = gFg - (gK*(255 - cursor[1])>>8);
  48. cursor[2] = rFg - (rK*(255 - cursor[2])>>8);
  49. }
  50. }
  51. }
  52. else if (32 == bpp)
  53. {
  54. if (removeAlpha)
  55. {
  56. BYTE rBk, gBk, bBk;
  57. rBk = GetRValue(rgbBk); gBk = GetGValue(rgbBk); bBk = GetBValue(rgbBk);
  58. for (line = pPixels; cy-- != 0; line += pitch )
  59. {
  60. for (x = cx, cursor = line; x-- != 0; cursor += 4)
  61. {
  62. if (0x00 == cursor[3])
  63. {
  64. cursor[0] = bBk;
  65. cursor[1] = gBk;
  66. cursor[2] = rBk;
  67. cursor[3] = 0xFF;
  68. }
  69. else if (0xFF == cursor[3])
  70. {
  71. cursor[0] = bFg - (bK*(255 - cursor[0])>>8);
  72. cursor[1] = gFg - (gK*(255 - cursor[1])>>8);
  73. cursor[2] = rFg - (rK*(255 - cursor[2])>>8);
  74. }
  75. else
  76. {
  77. cursor[0] = ((bFg - (bK*(255 - cursor[0])>>8))*cursor[3] + (((255 - cursor[3])*255 + 127)/255)*bBk + 127)/255;
  78. cursor[1] = ((gFg - (gK*(255 - cursor[1])>>8))*cursor[3] + (((255 - cursor[3])*255 + 127)/255)*gBk + 127)/255;
  79. cursor[2] = ((rFg - (rK*(255 - cursor[2])>>8))*cursor[3] + (((255 - cursor[3])*255 + 127)/255)*rBk + 127)/255;
  80. cursor[3] = 0xFF;
  81. }
  82. }
  83. }
  84. }
  85. else
  86. {
  87. for (line = pPixels; cy-- != 0; line += pitch )
  88. {
  89. for (x = cx, cursor = line; x-- != 0; cursor += 4)
  90. {
  91. cursor[0] = bFg - (bK*(255 - cursor[0])>>8);
  92. cursor[1] = gFg - (gK*(255 - cursor[1])>>8);
  93. cursor[2] = rFg - (rK*(255 - cursor[2])>>8);
  94. }
  95. }
  96. }
  97. }
  98. return TRUE;
  99. }
  100. BOOL Image_BlendOnColorEx(BYTE *pPixels, INT bitmapCX, INT bitmapCY, LONG x, LONG y, LONG cx, LONG cy, WORD bpp, BOOL premult, COLORREF rgb)
  101. {
  102. LONG pitch;
  103. WORD r, g, b;
  104. INT step = (bpp>>3);
  105. LPBYTE line, cursor;
  106. pitch = bitmapCX * step;
  107. while (pitch%4) pitch++;
  108. if (bpp != 32)
  109. return TRUE;
  110. if (cy < 0) cy -= cy;
  111. r = GetRValue(rgb); g = GetGValue(rgb); b = GetBValue(rgb);
  112. INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
  113. line = pPixels + pitch * ofs + x*step;
  114. if (premult)
  115. {
  116. for (; cy-- != 0; line += pitch)
  117. {
  118. for (x = cx, cursor = line; x-- != 0; cursor += 4)
  119. {
  120. if (0x00 == cursor[3])
  121. {
  122. cursor[0] = (BYTE)b;
  123. cursor[1] = (BYTE)g;
  124. cursor[2] = (BYTE)r;
  125. cursor[3] = 0xFF;
  126. }
  127. else if (cursor[3] != 0xFF)
  128. {
  129. WORD a = 255 - cursor[3];
  130. WORD destB = (cursor[0] * 255 + a * b + 127) / 255;
  131. WORD destG = (cursor[1] * 255 + a * g + 127) / 255;
  132. WORD destR = (cursor[2] * 255 + a * r + 127) / 255;
  133. cursor[0] = (destB > 0xFF) ? 0xFF : destB;
  134. cursor[1] = (destG > 0xFF) ? 0xFF : destG;
  135. cursor[2] = (destR > 0xFF) ? 0xFF : destR;
  136. cursor[3] = 0xFF;
  137. }
  138. }
  139. }
  140. }
  141. else
  142. {
  143. for (; cy-- != 0; line += pitch)
  144. {
  145. for (x = cx, cursor = line; x-- != 0; cursor += 4)
  146. {
  147. if (0x00 == cursor[3])
  148. {
  149. cursor[0] = (BYTE)b;
  150. cursor[1] = (BYTE)g;
  151. cursor[2] = (BYTE)r;
  152. cursor[3] = 0xFF;
  153. }
  154. else if (cursor[3] != 0xFF)
  155. {
  156. WORD a = (((255 - cursor[3])*255 + 127)/255);
  157. cursor[0] = (cursor[0]*cursor[3] + a*b + 127)/255;
  158. cursor[1] = (cursor[1]*cursor[3] + a*g + 127)/255;
  159. cursor[2] = (cursor[2]*cursor[3] + a*r + 127)/255;
  160. cursor[3] = 0xFF;
  161. }
  162. }
  163. }
  164. }
  165. return TRUE;
  166. }
  167. BOOL Image_BlendOnColor(HBITMAP hbmp, RECT *prcPart, BOOL premult, COLORREF rgb)
  168. {
  169. DIBSECTION dibsec;
  170. if (!hbmp || sizeof(DIBSECTION) != GetObject(hbmp, sizeof(DIBSECTION), &dibsec) ||
  171. BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || dibsec.dsBm.bmBitsPixel != 32)
  172. return FALSE;
  173. return Image_BlendOnColorEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
  174. prcPart->left, prcPart->top,
  175. prcPart->right - prcPart->left, prcPart->bottom - prcPart->top,
  176. dibsec.dsBm.bmBitsPixel, premult, rgb);
  177. }
  178. HBITMAP Image_AnimateRotation(HDC hdc, HBITMAP bitmapFrame, INT frameCount, COLORREF rgbBk, BOOL fKeepSize)
  179. {
  180. if (NULL == bitmapFrame)
  181. return NULL;
  182. BITMAP bm;
  183. if (sizeof(BITMAP) != GetObject(bitmapFrame, sizeof(BITMAP), &bm))
  184. return NULL;
  185. if (bm.bmHeight < 0) bm.bmHeight = -bm.bmHeight;
  186. HBITMAP hbmp = NULL;
  187. HDC hdcDst = CreateCompatibleDC(hdc);
  188. HDC hdcSrc = CreateCompatibleDC(hdc);
  189. if (NULL != hdcDst && NULL != hdcSrc)
  190. {
  191. INT side;
  192. if (FALSE == fKeepSize)
  193. side = (INT)ceil(_hypot(bm.bmWidth, bm.bmHeight));
  194. else
  195. {
  196. side = bm.bmWidth;
  197. if (bm.bmHeight > side)
  198. side = bm.bmHeight;
  199. }
  200. hbmp = CreateCompatibleBitmap(hdc, side, side * frameCount);
  201. if (NULL != hbmp)
  202. {
  203. LONG centerX, centerY;
  204. centerX = side/2;
  205. centerY = side/2;
  206. XFORM xForm;
  207. ZeroMemory(&xForm, sizeof(XFORM));
  208. HBITMAP hbmpFrameOld = (HBITMAP)SelectObject(hdcSrc, bitmapFrame);
  209. HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcDst, hbmp);
  210. RECT rcFill;
  211. SetRect(&rcFill, 0, 0, side, side * frameCount);
  212. SetBkColor(hdcDst, rgbBk);
  213. ExtTextOut(hdcDst, 0, 0, ETO_OPAQUE, &rcFill, NULL, 0, NULL);
  214. INT graphicsMode = SetGraphicsMode(hdcDst, GM_ADVANCED);
  215. INT top = (side - bm.bmHeight)/2;
  216. INT left = (side - bm.bmWidth)/2;
  217. for (INT i = 0; i < frameCount; i++)
  218. {
  219. double fangle = (double)(360/frameCount * i)/180. * 3.1415926;
  220. xForm.eM11 = (float)cos(fangle);
  221. xForm.eM12 = (float)sin(fangle);
  222. xForm.eM21 = (float)-sin(fangle);
  223. xForm.eM22 = (float)cos(fangle);
  224. xForm.eDx = (float)(centerX - cos(fangle)*centerX + sin(fangle)*centerY);
  225. xForm.eDy = (float)(centerY - cos(fangle)*centerY - sin(fangle)*centerX);
  226. SetWorldTransform(hdcDst, &xForm);
  227. BitBlt(hdcDst, left, top, bm.bmWidth, bm.bmHeight, hdcSrc, 0, 0, SRCCOPY);
  228. centerY += side;
  229. top += side;
  230. }
  231. SetGraphicsMode(hdcDst, graphicsMode);
  232. ModifyWorldTransform(hdcDst, NULL, MWT_IDENTITY);
  233. SelectObject(hdcSrc, hbmpFrameOld);
  234. SelectObject(hdcDst, hbmpOld);
  235. }
  236. }
  237. if (NULL != hdcDst) DeleteDC(hdcDst);
  238. if (NULL != hdcSrc) DeleteDC(hdcSrc);
  239. return hbmp;
  240. }
  241. BOOL Image_Premultiply(BYTE *pPixels, LONG cx, LONG cy)
  242. {
  243. LONG pitch, x;
  244. pitch = cx* 4;
  245. LPBYTE cursor, line;
  246. for (line = pPixels; cy-- != 0; line += pitch )
  247. {
  248. for (x = cx, cursor = line; x-- != 0; cursor += 4)
  249. {
  250. if (0x00 == cursor[3])
  251. {
  252. cursor[0] = 0x00;
  253. cursor[1] = 0x00;
  254. cursor[2] = 0x00;
  255. }
  256. else if (0xFF != cursor[3])
  257. {
  258. cursor[0] = (cursor[0] * cursor[3]) >> 8;
  259. cursor[1] = (cursor[1] * cursor[3]) >> 8;
  260. cursor[2] = (cursor[2] * cursor[3]) >> 8;
  261. }
  262. }
  263. }
  264. return TRUE;
  265. }
  266. BOOL Image_AlphaBlend(HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, BLENDFUNCTION blendFunction)
  267. {
  268. return AlphaBlend(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, blendFunction);
  269. }