Quantizer.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. #include "stdafx.h"
  2. #include "Quantizer.h"
  3. #include <MATH.H>
  4. /////////////////////////////////////////////////////////////////////////////
  5. CQuantizer::CQuantizer(UINT nMaxColors, UINT nColorBits)
  6. {
  7. m_nColorBits = nColorBits < 8 ? nColorBits : 8;
  8. m_pTree = NULL;
  9. m_nLeafCount = 0;
  10. for (int i = 0; i <= (int)m_nColorBits; i++)
  11. m_pReducibleNodes[i] = NULL;
  12. m_nMaxColors = nMaxColors;
  13. }
  14. /////////////////////////////////////////////////////////////////////////////
  15. CQuantizer::~CQuantizer()
  16. {
  17. if (m_pTree != NULL)
  18. DeleteTree(&m_pTree);
  19. }
  20. /////////////////////////////////////////////////////////////////////////////
  21. BOOL CQuantizer::ProcessImage(HANDLE hImage)
  22. {
  23. BYTE r, g, b;
  24. int i, j;
  25. BITMAPINFOHEADER ds;
  26. memcpy(&ds, hImage, sizeof(ds));
  27. int effwdt = ((((ds.biBitCount * ds.biWidth) + 31) / 32) * 4);
  28. int nPad = effwdt - (((ds.biWidth * ds.biBitCount) + 7) / 8);
  29. BYTE* pbBits = (BYTE*)hImage + *(LPDWORD)hImage;
  30. switch (ds.biBitCount) {
  31. case 1: // 1-bit DIB
  32. case 4: // 4-bit DIB
  33. case 8: // 8-bit DIB
  34. for (i = 0; i < ds.biHeight; i++) {
  35. for (j = 0; j < ds.biWidth; j++) {
  36. BYTE idx = GetPixelIndex(j, i, ds.biBitCount, effwdt, pbBits);
  37. BYTE* pal = (BYTE*)(hImage)+sizeof(BITMAPINFOHEADER);
  38. long ldx = idx * sizeof(RGBQUAD);
  39. b = pal[ldx++];
  40. g = pal[ldx++];
  41. r = pal[ldx];
  42. AddColor(&m_pTree, r, g, b, m_nColorBits, 0, &m_nLeafCount,
  43. m_pReducibleNodes);
  44. while (m_nLeafCount > m_nMaxColors)
  45. ReduceTree(m_nColorBits, &m_nLeafCount,
  46. m_pReducibleNodes);
  47. }
  48. }
  49. break;
  50. case 15:
  51. case 16://16bit
  52. for (i = 0; i < ds.biHeight; i++)
  53. {
  54. for (j = 0; j < ds.biWidth; j++)
  55. {
  56. b = (*pbBits) & 0x1F;
  57. g = (*pbBits++) >> 5;
  58. g |= ((*pbBits) & 0x03) << 3;
  59. r = ((*pbBits++) >> 2) & 0x1F;
  60. r *= 8;
  61. b *= 8;
  62. g *= 8;
  63. AddColor(&m_pTree, r, g, b, m_nColorBits, 0, &m_nLeafCount,
  64. m_pReducibleNodes);
  65. while (m_nLeafCount > m_nMaxColors)
  66. ReduceTree(m_nColorBits, &m_nLeafCount, m_pReducibleNodes);
  67. }
  68. pbBits += nPad;
  69. }
  70. break;
  71. case 24: // 24-bit DIB
  72. for (i = 0; i < ds.biHeight; i++) {
  73. for (j = 0; j < ds.biWidth; j++) {
  74. b = *pbBits++;
  75. g = *pbBits++;
  76. r = *pbBits++;
  77. AddColor(&m_pTree, r, g, b, m_nColorBits, 0, &m_nLeafCount,
  78. m_pReducibleNodes);
  79. while (m_nLeafCount > m_nMaxColors)
  80. ReduceTree(m_nColorBits, &m_nLeafCount, m_pReducibleNodes);
  81. }
  82. pbBits += nPad;
  83. }
  84. break;
  85. case 32: // 32-bit DIB
  86. for (i = 0; i < ds.biHeight; i++) {
  87. for (j = 0; j < ds.biWidth; j++) {
  88. b = *pbBits++;
  89. g = *pbBits++;
  90. r = *pbBits++;
  91. pbBits++;
  92. AddColor(&m_pTree, r, g, b, m_nColorBits, 0, &m_nLeafCount,
  93. m_pReducibleNodes);
  94. while (m_nLeafCount > m_nMaxColors)
  95. ReduceTree(m_nColorBits, &m_nLeafCount, m_pReducibleNodes);
  96. }
  97. pbBits += nPad;
  98. }
  99. break;
  100. default: // Unrecognized color format
  101. return FALSE;
  102. }
  103. return TRUE;
  104. }
  105. /////////////////////////////////////////////////////////////////////////////
  106. void CQuantizer::AddColor(NODE** ppNode, BYTE r, BYTE g, BYTE b,
  107. UINT nColorBits, UINT nLevel, UINT* pLeafCount, NODE** pReducibleNodes)
  108. {
  109. static BYTE mask[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
  110. // If the node doesn't exist, create it.
  111. if (*ppNode == NULL)
  112. *ppNode = (NODE*)CreateNode(nLevel, nColorBits, pLeafCount, pReducibleNodes);
  113. // Update color information if it's a leaf node.
  114. if ((*ppNode)->bIsLeaf)
  115. {
  116. (*ppNode)->nPixelCount++;
  117. (*ppNode)->nRedSum += r;
  118. (*ppNode)->nGreenSum += g;
  119. (*ppNode)->nBlueSum += b;
  120. }
  121. else
  122. { // Recurse a level deeper if the node is not a leaf.
  123. int shift = 7 - nLevel;
  124. int nIndex = (((r & mask[nLevel]) >> shift) << 2) |
  125. (((g & mask[nLevel]) >> shift) << 1) |
  126. ((b & mask[nLevel]) >> shift);
  127. AddColor(&((*ppNode)->pChild[nIndex]), r, g, b, nColorBits,
  128. nLevel + 1, pLeafCount, pReducibleNodes);
  129. }
  130. }
  131. /////////////////////////////////////////////////////////////////////////////
  132. void* CQuantizer::CreateNode(UINT nLevel, UINT nColorBits, UINT* pLeafCount,
  133. NODE** pReducibleNodes)
  134. {
  135. NODE* pNode = (NODE*)calloc(1, sizeof(NODE));
  136. if (pNode == NULL) return NULL;
  137. pNode->bIsLeaf = (nLevel == nColorBits) ? TRUE : FALSE;
  138. if (pNode->bIsLeaf) (*pLeafCount)++;
  139. else {
  140. pNode->pNext = pReducibleNodes[nLevel];
  141. pReducibleNodes[nLevel] = pNode;
  142. }
  143. return pNode;
  144. }
  145. /////////////////////////////////////////////////////////////////////////////
  146. void CQuantizer::ReduceTree(UINT nColorBits, UINT* pLeafCount,
  147. NODE** pReducibleNodes)
  148. {
  149. int i;
  150. // Find the deepest level containing at least one reducible node.
  151. for (i = nColorBits - 1; (i > 0) && (pReducibleNodes[i] == NULL); i--);
  152. // Reduce the node most recently added to the list at level i.
  153. NODE* pNode = pReducibleNodes[i];
  154. pReducibleNodes[i] = pNode->pNext;
  155. NODE* pNodeTmp = pNode;
  156. NODE* pNeedReduceNode = NULL, * pPreNode = NULL, * pPreNodeTmp = NULL;
  157. long nMinPixelCount = 0;
  158. while (pNodeTmp)
  159. {
  160. long nPixelCount = 0;
  161. for (int m = 0; m < 8; m++)
  162. {
  163. if (pNodeTmp->pChild[m] != NULL)
  164. {
  165. nPixelCount += pNodeTmp->pChild[m]->nPixelCount;
  166. }
  167. }
  168. if (nMinPixelCount == 0)
  169. {
  170. nMinPixelCount = nPixelCount;
  171. pNeedReduceNode = pNodeTmp;
  172. }
  173. else if (nPixelCount < nMinPixelCount)
  174. {
  175. nMinPixelCount = nPixelCount;
  176. pNeedReduceNode = pNodeTmp;
  177. pPreNode = pPreNodeTmp;
  178. }
  179. pPreNodeTmp = pNodeTmp;
  180. pNodeTmp = pNodeTmp->pNext;
  181. }
  182. if (pPreNode)
  183. {
  184. pPreNode->pNext = pNeedReduceNode->pNext;
  185. pReducibleNodes[i] = pNode;
  186. }
  187. pNode = pNeedReduceNode;
  188. UINT nRedSum = 0;
  189. UINT nGreenSum = 0;
  190. UINT nBlueSum = 0;
  191. UINT nChildren = 0;
  192. for (i = 0; i < 8; i++)
  193. {
  194. if (pNode->pChild[i] != NULL)
  195. {
  196. nRedSum += pNode->pChild[i]->nRedSum;
  197. nGreenSum += pNode->pChild[i]->nGreenSum;
  198. nBlueSum += pNode->pChild[i]->nBlueSum;
  199. pNode->nPixelCount += pNode->pChild[i]->nPixelCount;
  200. free(pNode->pChild[i]);
  201. pNode->pChild[i] = NULL;
  202. nChildren++;
  203. }
  204. }
  205. pNode->bIsLeaf = TRUE;
  206. pNode->nRedSum = nRedSum;
  207. pNode->nGreenSum = nGreenSum;
  208. pNode->nBlueSum = nBlueSum;
  209. *pLeafCount -= (nChildren - 1);
  210. }
  211. /////////////////////////////////////////////////////////////////////////////
  212. void CQuantizer::DeleteTree(NODE** ppNode)
  213. {
  214. for (int i = 0; i < 8; i++) {
  215. if ((*ppNode)->pChild[i] != NULL) DeleteTree(&((*ppNode)->pChild[i]));
  216. }
  217. free(*ppNode);
  218. *ppNode = NULL;
  219. }
  220. BOOL CQuantizer::FindColorIndex(NODE* pNode, BYTE r, BYTE g, BYTE b, int nLevel, UINT* pColorIndex)
  221. {
  222. static BYTE mask[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
  223. // If the node doesn't exist, create it.
  224. if (pNode == NULL)
  225. {
  226. return FALSE;
  227. }
  228. // Update color information if it's a leaf node.
  229. if (pNode->bIsLeaf)
  230. {
  231. *pColorIndex = pNode->nColorIndex;
  232. return TRUE;
  233. }
  234. // Recurse a level deeper if the node is not a leaf.
  235. int shift = 7 - nLevel;
  236. int nIndex = (((r & mask[nLevel]) >> shift) << 2) |
  237. (((g & mask[nLevel]) >> shift) << 1) |
  238. ((b & mask[nLevel]) >> shift);
  239. return FindColorIndex(pNode->pChild[nIndex], r, g, b, nLevel + 1, pColorIndex);
  240. }
  241. BOOL CQuantizer::GetColorIndex(BYTE r, BYTE g, BYTE b, UINT* pColorIndex)
  242. {
  243. return FindColorIndex(m_pTree, r, g, b, 0, pColorIndex);
  244. }
  245. /////////////////////////////////////////////////////////////////////////////
  246. void CQuantizer::GetPaletteColors(NODE* pTree, RGBQUAD* prgb, UINT* pIndex)
  247. {
  248. if (pTree) {
  249. if (pTree->bIsLeaf) {
  250. prgb[*pIndex].rgbRed = (BYTE)((pTree->nRedSum) / (pTree->nPixelCount));
  251. prgb[*pIndex].rgbGreen = (BYTE)((pTree->nGreenSum) / (pTree->nPixelCount));
  252. prgb[*pIndex].rgbBlue = (BYTE)((pTree->nBlueSum) / (pTree->nPixelCount));
  253. prgb[*pIndex].rgbReserved = 0;
  254. pTree->nColorIndex = *pIndex;
  255. (*pIndex)++;
  256. }
  257. else {
  258. for (int i = 0; i < 8; i++) {
  259. if (pTree->pChild[i] != NULL)
  260. GetPaletteColors(pTree->pChild[i], prgb, pIndex);
  261. }
  262. }
  263. }
  264. }
  265. /////////////////////////////////////////////////////////////////////////////
  266. UINT CQuantizer::GetColorCount()
  267. {
  268. return m_nLeafCount;
  269. }
  270. /////////////////////////////////////////////////////////////////////////////
  271. void CQuantizer::SetColorTable(RGBQUAD* prgb)
  272. {
  273. UINT nIndex = 0;
  274. GetPaletteColors(m_pTree, prgb, &nIndex);
  275. }
  276. /////////////////////////////////////////////////////////////////////////////
  277. BYTE CQuantizer::GetPixelIndex(long x, long y, int nbit, long effwdt, BYTE* pimage)
  278. {
  279. if (nbit == 8)
  280. {
  281. return pimage[y * effwdt + x];
  282. }
  283. else
  284. {
  285. BYTE pos;
  286. BYTE iDst = pimage[y * effwdt + (x * nbit >> 3)];
  287. if (nbit == 4)
  288. {
  289. pos = 4 * (1 - x % 2);
  290. iDst &= (0x0F << pos);
  291. return iDst >> pos;
  292. }
  293. else if (nbit == 1)
  294. {
  295. pos = 7 - x % 8;
  296. iDst &= (0x01 << pos);
  297. return iDst >> pos;
  298. }
  299. }
  300. return 0;
  301. }
  302. CRGBQuantizer::CRGBQuantizer(UINT nMaxColors, UINT nColorBits)
  303. :CQuantizer(nMaxColors, nColorBits)
  304. {
  305. }
  306. BOOL CRGBQuantizer::ProcessImageRGB(BYTE* pRGBData, UINT nWidth, UINT nHeight)
  307. {
  308. BYTE r, g, b;
  309. for (int i = 0; i < nHeight; i++)
  310. {
  311. for (int j = 0; j < nWidth; j++)
  312. {
  313. r = *pRGBData++;
  314. g = *pRGBData++;
  315. b = *pRGBData++;
  316. AddColor(&m_pTree, r, g, b, m_nColorBits, 0, &m_nLeafCount,
  317. m_pReducibleNodes);
  318. while (m_nLeafCount > m_nMaxColors)
  319. ReduceTree(m_nColorBits, &m_nLeafCount, m_pReducibleNodes);
  320. }
  321. }
  322. return TRUE;
  323. }
  324. CBitmapQuantizer::CBitmapQuantizer(UINT nMaxColors, UINT nColorBits)
  325. :CQuantizer(nMaxColors, nColorBits)
  326. {
  327. }
  328. BOOL CBitmapQuantizer::ProcessImageBitmap(HBITMAP hBmp)
  329. {
  330. BITMAP bm;
  331. PBITMAPINFO bmpInf;
  332. if (GetObject(hBmp, sizeof(bm), &bm) == 0)
  333. return FALSE;
  334. int nPaletteSize = 0;
  335. if (bm.bmBitsPixel < 16)
  336. nPaletteSize = (int)pow(2.0, bm.bmBitsPixel);
  337. bmpInf = (PBITMAPINFO)LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER) +
  338. sizeof(RGBQUAD) * nPaletteSize +
  339. (bm.bmWidth + 7) / 8 * bm.bmHeight * bm.bmBitsPixel);
  340. BYTE* buf = ((BYTE*)bmpInf) +
  341. sizeof(BITMAPINFOHEADER) +
  342. sizeof(RGBQUAD) * nPaletteSize;
  343. //-----------------------------------------------
  344. bmpInf->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  345. bmpInf->bmiHeader.biWidth = bm.bmWidth;
  346. bmpInf->bmiHeader.biHeight = bm.bmHeight;
  347. bmpInf->bmiHeader.biPlanes = bm.bmPlanes;
  348. bmpInf->bmiHeader.biBitCount = bm.bmBitsPixel;
  349. bmpInf->bmiHeader.biCompression = BI_RGB;
  350. bmpInf->bmiHeader.biSizeImage = (bm.bmWidth + 7) / 8 * bm.bmHeight * bm.bmBitsPixel;
  351. bmpInf->bmiHeader.biXPelsPerMeter = 0;
  352. bmpInf->bmiHeader.biYPelsPerMeter = 0;
  353. bmpInf->bmiHeader.biClrUsed = 0;
  354. bmpInf->bmiHeader.biClrImportant = 0;
  355. //-----------------------------------------------
  356. HDC hDC = ::GetWindowDC(NULL);
  357. if (!::GetDIBits(hDC, hBmp, 0, (UINT)bm.bmHeight, buf, bmpInf, DIB_RGB_COLORS))
  358. {
  359. ::ReleaseDC(NULL, hDC);
  360. LocalFree(bmpInf);
  361. return FALSE;
  362. }
  363. ::ReleaseDC(NULL, hDC);
  364. bmpInf->bmiHeader.biSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * nPaletteSize;
  365. BOOL bRet = ProcessImage(bmpInf);
  366. LocalFree(bmpInf);
  367. return bRet;
  368. }