DIBMAP.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:22k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /**************************************************************************
  2.  *
  3.  *  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4.  *  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5.  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6.  *  PURPOSE.
  7.  *
  8.  *  Copyright (C) 1992 - 1997 Microsoft Corporation.  All Rights Reserved.
  9.  *
  10.  **************************************************************************/
  11. #include <windows.h>
  12. #include <windowsx.h>
  13. #include "dibmap.h"
  14. extern NEAR PASCAL MemCopy(LPVOID,LPVOID,DWORD);
  15. extern NEAR PASCAL MemFill(LPVOID,DWORD,BYTE);
  16. void Histogram24(BYTE *pb, int dx, int dy, WORD WidthBytes, LPHISTOGRAM lpHistogram);
  17. void Histogram16(BYTE *pb, int dx, int dy, WORD WidthBytes, LPHISTOGRAM lpHistogram);
  18. void Histogram8(BYTE *pb, int dx, int dy, WORD WidthBytes, LPHISTOGRAM lpHistogram, LPWORD lpColors);
  19. void Histogram4(BYTE *pb, int dx, int dy, WORD WidthBytes, LPHISTOGRAM lpHistogram, LPWORD lpColors);
  20. void Histogram1(BYTE *pb, int dx, int dy, WORD WidthBytes, LPHISTOGRAM lpHistogram, LPWORD lpColors);
  21. void Reduce24(BYTE *pbIn, int dx, int dy, WORD cbIn, BYTE *pbOut, WORD cbOut, LPBYTE lp16to8);
  22. void Reduce16(BYTE *pbIn, int dx, int dy, WORD cbIn, BYTE *pbOut, WORD cbOut, LPBYTE lp16to8);
  23. void Reduce8(BYTE *pbIn, int dx, int dy, WORD cbIn, BYTE *pbOut, WORD cbOut, LPBYTE lp8to8);
  24. void Reduce4(BYTE *pbIn, int dx, int dy, WORD cbIn, BYTE *pbOut, WORD cbOut, LPBYTE lp8to8);
  25. void Reduce1(BYTE *pbIn, int dx, int dy, WORD cbIn, BYTE *pbOut, WORD cbOut, LPBYTE lp8to8);
  26. LPHISTOGRAM lpHistogram;
  27. //
  28. // InitHistogram
  29. //
  30. // create a zero'ed histogram table, or initialize a existing table
  31. // to all zeros.
  32. //
  33. LPHISTOGRAM InitHistogram(
  34. LPHISTOGRAM lpHistogram)
  35. {
  36. if (lpHistogram == NULL)
  37. lpHistogram = (LPVOID)GlobalAllocPtr(GHND, 32768L * sizeof(DWORD));
  38. return lpHistogram;
  39. }
  40. //
  41. // FreeHistogram
  42. //
  43. // free a histogram table
  44. //
  45. void FreeHistogram(
  46. LPHISTOGRAM lpHistogram)
  47. {
  48. GlobalFreePtr(lpHistogram);
  49. }
  50. //
  51. // DibHistogram
  52. //
  53. // take all colors in a dib and increment its entry in the Histogram table
  54. //
  55. // supports the following DIB formats: 1,4,8,16,24
  56. //
  57. BOOL DibHistogram(
  58. LPBITMAPINFOHEADER lpbi,
  59. LPBYTE lpBits,
  60. int x,
  61. int y,
  62. int dx,
  63. int dy,
  64. LPHISTOGRAM lpHistogram)
  65. {
  66. int i;
  67. WORD WidthBytes;
  68. RGBQUAD FAR * prgbq;
  69. WORD argb16[256];
  70. if (lpbi == NULL || lpHistogram == NULL)
  71. return FALSE;
  72. if (lpbi->biClrUsed == 0 && lpbi->biBitCount <= 8)
  73. lpbi->biClrUsed = (1 << (int)lpbi->biBitCount);
  74. if (lpBits == NULL)
  75. lpBits = (LPBYTE)lpbi + (int)lpbi->biSize
  76. + (int)lpbi->biClrUsed*sizeof(RGBQUAD);
  77. WidthBytes = (WORD)(((LONG)lpbi->biBitCount * lpbi->biWidth + 7) / 8 + 3) & ~3;
  78. ((BYTE *)lpBits) += (DWORD)y*WidthBytes + ((x*(int)lpbi->biBitCount)/8);
  79. if (dx < 0 || dx > (int)lpbi->biWidth)
  80. dx = (int)lpbi->biWidth;
  81. if (dy < 0 || dy > (int)lpbi->biHeight)
  82. dy = (int)lpbi->biHeight;
  83. if ((int)lpbi->biBitCount <= 8)
  84. {
  85. prgbq = (LPVOID)((LPBYTE)lpbi + lpbi->biSize);
  86. for (i=0; i<(int)lpbi->biClrUsed; i++)
  87. {
  88. argb16[i] = (WORD) RGB16(prgbq[i].rgbRed,prgbq[i].rgbGreen,prgbq[i].rgbBlue);
  89. }
  90. for (i=(int)lpbi->biClrUsed; i<256; i++)
  91. {
  92. argb16[i] = 0x0000; // just in case!
  93. }
  94. }
  95. switch ((int)lpbi->biBitCount)
  96. {
  97. case 24:
  98. Histogram24(lpBits, dx, dy, WidthBytes, lpHistogram);
  99. break;
  100. case 16:
  101. Histogram16(lpBits, dx, dy, WidthBytes, lpHistogram);
  102. break;
  103. case 8:
  104. Histogram8(lpBits, dx, dy, WidthBytes, lpHistogram, argb16);
  105. break;
  106. case 4:
  107. Histogram4(lpBits, dx, dy, WidthBytes, lpHistogram, argb16);
  108. break;
  109. case 1:
  110. Histogram1(lpBits, dx, dy, WidthBytes, lpHistogram, argb16);
  111. break;
  112. }
  113. }
  114. //
  115. // will convert the given DIB to a 8bit DIB with the specifed palette
  116. //
  117. LPBITMAPINFOHEADER DibReduce(
  118. LPBITMAPINFOHEADER lpbiIn,
  119. LPBYTE pbIn,
  120. HPALETTE hpal,
  121. LPBYTE lp16to8)
  122. {
  123. LPBITMAPINFOHEADER lpdib;
  124. WORD nPalColors;  // NOTE win32 GetObject ONLY returns
  125.                                              // 2 bytes for HPALs
  126. int nDibColors;
  127. WORD cbOut;
  128. WORD cbIn;
  129. BYTE xlat[256];
  130. BYTE * pbOut;
  131. RGBQUAD FAR * prgb;
  132. DWORD dwSize;
  133. int i;
  134. int dx;
  135. int dy;
  136. PALETTEENTRY pe;
  137. dx = (int)lpbiIn->biWidth;
  138. dy = (int)lpbiIn->biHeight;
  139. cbIn = (WORD)((((UINT)lpbiIn->biBitCount*dx+7)/8+3)&~3);
  140. cbOut = (WORD)((dx+3)&~3);
  141. GetObject(hpal, sizeof(WORD), (LPVOID)&nPalColors);
  142. nDibColors = (int)lpbiIn->biClrUsed;
  143. if (nDibColors == 0 && lpbiIn->biBitCount <= 8)
  144. nDibColors = (1 << (int)lpbiIn->biBitCount);
  145. if (pbIn == NULL)
  146. pbIn = (LPBYTE)lpbiIn + (int)lpbiIn->biSize + nDibColors*sizeof(RGBQUAD);
  147. dwSize = (DWORD)cbOut * dy;
  148. lpdib = GlobalAllocPtr(GMEM_MOVEABLE,sizeof(BITMAPINFOHEADER)
  149. + nPalColors*sizeof(RGBQUAD) + dwSize);
  150. if (!lpdib)
  151. return NULL;
  152. lpdib->biSize = sizeof(BITMAPINFOHEADER);
  153. lpdib->biWidth = lpbiIn->biWidth;
  154. lpdib->biHeight = lpbiIn->biHeight;
  155. lpdib->biPlanes = 1;
  156. lpdib->biBitCount = 8;
  157. lpdib->biCompression = BI_RGB;
  158. lpdib->biSizeImage = dwSize;
  159. lpdib->biXPelsPerMeter = 0;
  160. lpdib->biYPelsPerMeter = 0;
  161. lpdib->biClrUsed = (DWORD)nPalColors;
  162. lpdib->biClrImportant = 0;
  163. pbOut = (LPBYTE)lpdib + (int)lpdib->biSize + nPalColors*sizeof(RGBQUAD);
  164. prgb = (LPVOID)((LPBYTE)lpdib + (int)lpdib->biSize);
  165. for (i=0; i<(int)nPalColors; i++)
  166. {
  167. GetPaletteEntries(hpal, i, 1, &pe);
  168. prgb[i].rgbRed = pe.peRed;
  169. prgb[i].rgbGreen = pe.peGreen;
  170. prgb[i].rgbBlue = pe.peBlue;
  171. prgb[i].rgbReserved = 0;
  172. }
  173. if ((int)lpbiIn->biBitCount <= 8)
  174. {
  175. prgb = (LPVOID)((LPBYTE)lpbiIn + lpbiIn->biSize);
  176. for (i=0; i<nDibColors; i++)
  177. xlat[i] = lp16to8[RGB16(prgb[i].rgbRed,prgb[i].rgbGreen,prgb[i].rgbBlue)];
  178. for (; i<256; i++)
  179. xlat[i] = 0;
  180. }
  181. switch ((int)lpbiIn->biBitCount)
  182. {
  183. case 24:
  184. Reduce24(pbIn, dx, dy, cbIn, pbOut, cbOut, lp16to8);
  185. break;
  186. case 16:
  187. Reduce16(pbIn, dx, dy, cbIn, pbOut, cbOut, lp16to8);
  188. break;
  189. case 8:
  190. Reduce8(pbIn, dx, dy, cbIn, pbOut, cbOut, xlat);
  191. break;
  192. case 4:
  193. Reduce4(pbIn, dx, dy, cbIn, pbOut, cbOut, xlat);
  194. break;
  195. case 1:
  196. Reduce1(pbIn, dx, dy, cbIn, pbOut, cbOut, xlat);
  197. break;
  198. }
  199. return lpdib;
  200. }
  201. ///////////////////////////////////////////////////////////////////////////////
  202. // cluster.c
  203. ///////////////////////////////////////////////////////////////////////////////
  204. #define IN_DEPTH 5 // # bits/component kept from input
  205. #define IN_SIZE (1 << IN_DEPTH) // max value of a color component
  206. typedef enum { red, green, blue } color;
  207. typedef struct tagCut
  208. {
  209. long lvariance; // for int version
  210. int cutpoint;
  211. unsigned long rem; // for experimental fixed point
  212. color cutaxis;
  213. long w1, w2;
  214. double variance;
  215. } Cut;
  216. typedef struct tagColorBox // from cluster.c
  217. {
  218. struct tagColorBox *next; /* pointer to next box */
  219. int rmin, rmax, gmin, gmax, bmin, bmax; /* bounding box */
  220. long variance, wt; /* weighted variance */
  221. long sum[3]; /* sum of values */
  222. } ColorBox;
  223. static int InitBoxes(int nBoxes);
  224. static void DeleteBoxes(void);
  225. static int SplitBoxAxis(ColorBox *box, Cut cutaxis);
  226. static void ShrinkBox(ColorBox *box);
  227. static int ComputePalette(LPHISTOGRAM lpHistogram, LPBYTE lp16to8, LPPALETTEENTRY palette);
  228. static COLORREF DetermineRepresentative(ColorBox *box, int palIndex);
  229. static Cut FindSplitAxis(ColorBox *box);
  230. static void SplitBox(ColorBox *box);
  231. static void SortBoxes(void);
  232. HANDLE hBoxes;
  233. ColorBox *UsedBoxes;
  234. ColorBox *FreeBoxes;
  235. LPBYTE glp16to8;
  236. //#define hist(r,g,b) ((DWORD *)glpHistogram)[(WORD)(b) | ((WORD)(g)<<IN_DEPTH) | ((WORD)(r)<<(IN_DEPTH*2))]
  237. #define hist(r,g,b) GetHistogram((BYTE)(r),(BYTE)(g),(BYTE)(b))
  238. #pragma optimize ("", off)
  239. //
  240. // set FS == lpHistogram.sel, so we can get at it quickly!
  241. //
  242. void NEAR PASCAL UseHistogram(
  243. LPHISTOGRAM lpHistogramToSet)
  244. {
  245.         lpHistogram = lpHistogramToSet;
  246. }
  247. //
  248. // get the DOWRD histogram count of a RGB
  249. //
  250. DWORD near _fastcall GetHistogram(
  251. BYTE r,
  252. BYTE g,
  253. BYTE b)
  254. {
  255.         return lpHistogram[((UINT)r << 10 ) + ((UINT)g << 5) + (UINT)b];
  256. }
  257. //
  258. // increment the histogram count of a RGB16
  259. //
  260. //
  261. // #define IncHistogram(w) if (lpHistogram[(WORD)(w)] < 0xFFFFFFFF)
  262. // lpHistogram[(WORD)(w)]++;
  263. //
  264. void near _fastcall IncHistogram(WORD rgb16)
  265. {
  266.     if (lpHistogram[rgb16] != (DWORD)-1)
  267.         lpHistogram[rgb16]++;
  268. }
  269. #pragma optimize ("", on)
  270. // !!! C8 generates a Jump into the middle of a 2 byte instruction
  271. // !!! Stupid C8!
  272. #pragma optimize ("", off)
  273. //
  274. // HistogramPalette
  275. //
  276. // given a histogram, will reduce it to 'nColors' number of colors.
  277. // returns a optimal palette.  if specifed lp16to8 will contain the
  278. // translate table from RGB16 to the palette index.
  279. //
  280. // you can specify lpHistogram as lp16to8
  281. //
  282. HPALETTE HistogramPalette(
  283. LPHISTOGRAM lpHistogram,
  284. LPBYTE lp16to8,
  285. int nColors)
  286. {
  287. struct {
  288. WORD palVersion;
  289. WORD palNumEntries;
  290. PALETTEENTRY palPalEntry[256];
  291. } pal;
  292. WORD w;
  293. DWORD dwMax;
  294. COLORREF rgb;
  295. ColorBox *box;
  296. int i;
  297. //
  298. // the 'C' code cant handle >64k histogram counts.
  299. // !!!fix this
  300. //
  301. for (dwMax=0,w=0; w<0x8000; w++)
  302. dwMax = max(dwMax,lpHistogram[w]);
  303. while (dwMax > 0xFFFFl)
  304. {
  305. for (w=0; w<0x8000; w++)
  306. lpHistogram[w] /= 2;
  307. dwMax /= 2;
  308. }
  309. if (!InitBoxes(min(nColors, 236)))
  310. return NULL;
  311. UseHistogram(lpHistogram);
  312. glp16to8 = lp16to8;
  313. /* while there are free boxes left, split the largest */
  314. i = 0;
  315. do {
  316. i++;
  317. SplitBox(UsedBoxes);
  318. }
  319. while (FreeBoxes && UsedBoxes->variance);
  320. SortBoxes();
  321. i=0;
  322. //
  323. // add some standard colors to the histogram
  324. //
  325. if (nColors > 236)
  326. {
  327. HDC hdc;
  328. hdc = GetDC(NULL);
  329. if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
  330. {
  331. GetSystemPaletteEntries(hdc, 0,
  332. 10, &pal.palPalEntry[0]);
  333. GetSystemPaletteEntries(hdc, 246,
  334. 10, &pal.palPalEntry[246]);
  335. i = 10;
  336. }
  337. ReleaseDC(NULL, hdc);
  338. }
  339. /* Generate the representitives and the associated Palette mapping */
  340. /* NOTE:  Might loop less than nColors times.                      */
  341. for (box = UsedBoxes; box; box = box->next, i++)
  342. {
  343. rgb = DetermineRepresentative(box, i);
  344. pal.palPalEntry[i].peRed = GetRValue(rgb);
  345. pal.palPalEntry[i].peGreen = GetGValue(rgb);
  346. pal.palPalEntry[i].peBlue = GetBValue(rgb);
  347. pal.palPalEntry[i].peFlags = 0;
  348. }
  349. DeleteBoxes();
  350. if (nColors > 236)
  351. {
  352. for (; i<246; i++)
  353. {
  354. pal.palPalEntry[i].peRed = 0;
  355. pal.palPalEntry[i].peGreen = 0;
  356. pal.palPalEntry[i].peBlue = 0;
  357. pal.palPalEntry[i].peFlags = 0;
  358. }
  359. i = 256;
  360. }
  361. glp16to8 = NULL;
  362. pal.palVersion = 0x300;
  363. pal.palNumEntries = (WORD)i;
  364. return CreatePalette((LPLOGPALETTE)&pal);
  365. }
  366. #pragma optimize ("", on)
  367. static void SortBoxes(void)
  368. {
  369. ColorBox *box;
  370. ColorBox *newList;
  371. ColorBox *insBox;
  372. ColorBox *nextBox;
  373. newList = UsedBoxes;
  374. nextBox = newList->next;
  375. newList->next = NULL;
  376. for (box = nextBox; box; box = nextBox) { // just an insertion sort...
  377. nextBox = box->next;
  378. if (box->wt > newList->wt) {
  379. box->next = newList;
  380. newList = box;
  381. } else {
  382. for (insBox = newList;
  383. insBox->next && (box->wt < insBox->next->wt);
  384. insBox = insBox->next) ;
  385. box->next = insBox->next;
  386. insBox->next = box;
  387. }
  388. }
  389. UsedBoxes = newList;
  390. }
  391. /*
  392. allocate space for nBoxes boxes, set up links.  On exit UsedBoxes
  393. points to one box, FreeBoxes points to remaining (nBoxes-1) boxes.
  394. return 0 if successful.
  395. */
  396. static BOOL InitBoxes(
  397. int nBoxes)
  398. {
  399. int i;
  400. hBoxes = LocalAlloc(LHND, nBoxes*sizeof(ColorBox));
  401. if (!hBoxes)
  402. return FALSE;
  403. UsedBoxes = (ColorBox*)LocalLock(hBoxes);
  404. FreeBoxes = UsedBoxes + 1;
  405. UsedBoxes->next = NULL;
  406. for (i = 0; i < nBoxes - 1; ++i)
  407. {
  408. FreeBoxes[i].next = FreeBoxes + i + 1;
  409. }
  410. FreeBoxes[nBoxes-2].next = NULL;
  411. /* save the bounding box */
  412. UsedBoxes->rmin = UsedBoxes->gmin = UsedBoxes->bmin = 0;
  413. UsedBoxes->rmax = UsedBoxes->gmax = UsedBoxes->bmax = IN_SIZE - 1;
  414. UsedBoxes->variance = 9999999; /* arbitrary large # */
  415. return TRUE;
  416. }
  417. static void DeleteBoxes(void)
  418. {
  419. LocalUnlock(hBoxes);
  420. LocalFree(hBoxes);
  421. hBoxes = NULL;
  422. }
  423. static void SplitBox(
  424. ColorBox *box)
  425. {
  426. /*
  427. split box into two roughly equal halves and update the data structures
  428. appropriately.
  429. */
  430. Cut cutaxis;
  431. ColorBox *temp, *temp2, *prev;
  432. cutaxis = FindSplitAxis(box);
  433. /* split the box along that axis.  If rc != 0 then the box contains
  434. one color, and should not be split
  435. */
  436. if (SplitBoxAxis(box, cutaxis))
  437. return;
  438. /* shrink each of the boxes to fit the points they enclose */
  439. ShrinkBox(box);
  440. ShrinkBox(FreeBoxes);
  441. /* move old box down in list, if necessary */
  442. if (box->next && box->variance < box->next->variance)
  443. {
  444. UsedBoxes = box->next;
  445. temp = box;
  446. do {
  447. prev = temp;
  448. temp = temp->next;
  449. } while (temp && temp->variance > box->variance);
  450. box->next = temp;
  451. prev->next = box;
  452. }
  453. /* insert the new box in sorted order (descending), removing it
  454. from the free list.
  455. */
  456. if (FreeBoxes->variance >= UsedBoxes->variance)
  457. {
  458. temp = FreeBoxes;
  459. FreeBoxes = FreeBoxes->next;
  460. temp->next = UsedBoxes;
  461. UsedBoxes = temp;
  462. }
  463. else
  464. {
  465. temp = UsedBoxes;
  466. do {
  467. prev = temp;
  468. temp = temp->next;
  469. } while (temp && temp->variance > FreeBoxes->variance);
  470. temp2 = FreeBoxes->next;
  471. FreeBoxes->next = temp;
  472. prev->next = FreeBoxes;
  473. FreeBoxes = temp2;
  474. }
  475. }
  476. static Cut FindSplitAxis(
  477. ColorBox *box)
  478. {
  479. unsigned long proj_r[IN_SIZE],proj_g[IN_SIZE],proj_b[IN_SIZE];
  480. unsigned long f;
  481. double currentMax,mean;
  482. unsigned long w,w1,m,m1;
  483. int r,g,b;
  484. int bestCut;
  485. color bestAxis;
  486. Cut cutRet;
  487. double temp1,temp2;
  488. for (r = 0; r < IN_SIZE; r++) {
  489. proj_r[r] = proj_g[r] = proj_b[r] = 0;
  490. }
  491. w = 0;
  492. // Project contents of box down onto axes
  493. for (r = box->rmin; r <= box->rmax; r++) {
  494. for (g = box->gmin; g <= box->gmax; ++g) {
  495. for (b = box->bmin; b <= box->bmax; ++b) {
  496. f = hist(r,g,b);
  497. proj_r[r] += f;
  498. proj_g[g] += f;
  499. proj_b[b] += f;
  500. }
  501. }
  502. w += proj_r[r];
  503. }
  504. currentMax = 0.0f;
  505. #define Check_Axis(l,color)
  506. m = 0;
  507. for (l = box->l##min; l <= box->l##max; (l)++) {
  508. m += l * proj_##l[l];
  509. }
  510. mean = ((double) m) / ((double) w);
  511. w1 = 0;
  512. m1 = 0;
  513. for (l = box->l##min; l <= box->l##max; l++) {
  514. w1 += proj_##l[l];
  515. if (w1 == 0)
  516. continue;
  517. if (w1 == w)
  518. break;
  519. m1 += l * proj_##l[l];
  520. temp1 = mean - (((double) m1) / ((double) w1));
  521. temp2 = (((double) w1) / ((double) (w-w1))) * temp1 * temp1; 
  522. if (temp2 > currentMax) {
  523. bestCut = l;
  524. bestAxis = color;
  525. currentMax = temp2;
  526. }
  527. }
  528. Check_Axis(r,red);
  529. Check_Axis(g,green);
  530. Check_Axis(b,blue);
  531. cutRet.cutaxis = bestAxis;
  532. cutRet.cutpoint = bestCut;
  533. return cutRet;
  534. }
  535. static int SplitBoxAxis(
  536. ColorBox *box,
  537. Cut cutaxis)
  538. {
  539. /*
  540. Split box along splitaxis into two boxes, one of which is placed
  541. back in box, the other going in the first free box (FreeBoxes)
  542. If the box only contains one color, return non-zero, else return 0.
  543. */
  544. ColorBox *next;
  545. if ( box->variance == 0)
  546. return 1;
  547. /* copy all non-link information to new box */
  548. next = FreeBoxes->next;
  549. *FreeBoxes = *box;
  550. FreeBoxes->next = next;
  551. switch (cutaxis.cutaxis)
  552. {
  553. case red:
  554. box->rmax = cutaxis.cutpoint;
  555. FreeBoxes->rmin = cutaxis.cutpoint+1;
  556. break;
  557. case green:
  558. box->gmax = cutaxis.cutpoint;
  559. FreeBoxes->gmin = cutaxis.cutpoint+1;
  560. break;
  561. case blue:
  562. box->bmax = cutaxis.cutpoint;
  563. FreeBoxes->bmin = cutaxis.cutpoint+1;
  564. break;
  565. }
  566. return 0;
  567. }
  568. static void ShrinkBox(
  569. ColorBox *box)
  570. {
  571. unsigned long n, sxx, sx2, var, quotient, remainder;
  572. int r,g,b;
  573. unsigned long f;
  574. unsigned long proj_r[IN_SIZE],proj_g[IN_SIZE],proj_b[IN_SIZE];
  575. n = 0;
  576. for (r = 0; r < IN_SIZE; r++) {
  577. proj_r[r] = proj_g[r] = proj_b[r] = 0;
  578. }
  579. // Project contents of box down onto axes
  580. for (r = box->rmin; r <= box->rmax; r++) {
  581. for (g = box->gmin; g <= box->gmax; ++g) {
  582. for (b = box->bmin; b <= box->bmax; ++b) {
  583. f = hist(r,g,b);
  584. proj_r[r] += f;
  585. proj_g[g] += f;
  586. proj_b[b] += f;
  587. }
  588. }
  589. n += proj_r[r];
  590. }
  591. box->wt = n;
  592. var = 0;
  593. #define AddAxisVariance(c)
  594. sxx = 0; sx2 = 0;
  595. for (c = box->c##min; c <= box->c##max; c++) {
  596. sxx += proj_##c[c] * c * c;
  597. sx2 += proj_##c[c] * c;
  598. }
  599. quotient = sx2 / n; /* This stuff avoids overflow */
  600. remainder = sx2 % n;
  601. var += sxx - quotient * sx2 - ((remainder * sx2)/n);
  602. AddAxisVariance(r);
  603. AddAxisVariance(g);
  604. AddAxisVariance(b);
  605. box->variance = var;
  606. }
  607. static COLORREF DetermineRepresentative(
  608. ColorBox *box,
  609. int palIndex)
  610. {
  611. /*
  612. determines the rgb value to represent the pixels contained in
  613. box.  nbits is the # bits/component we're allowed to return.
  614. */
  615. long f;
  616. long Rval, Gval, Bval;
  617. unsigned long total;
  618. int r, g, b;
  619. int i;
  620. /* compute the weighted sum of the elements in the box */
  621. Rval = Gval = Bval = total = 0;
  622. for (r = box->rmin; r <= box->rmax; ++r)
  623. {
  624. for (g = box->gmin; g <= box->gmax; ++g)
  625. {
  626. for (b = box->bmin; b <= box->bmax; ++b)
  627. {
  628. if (glp16to8)
  629. {
  630. i = (b) | (g << IN_DEPTH)
  631. | (r << (IN_DEPTH*2));
  632. glp16to8[i] = (BYTE)palIndex;
  633. }
  634. f = hist(r,g,b);
  635. if (f == 0L)
  636. continue;
  637. Rval += f * (long) r;
  638. Gval += f * (long) g;
  639. Bval += f * (long) b;
  640. total += f;
  641. }
  642. }
  643. }
  644. /* Bias the sum so that we round up at .5 */
  645. Rval += total / 2;
  646. Gval += total / 2;
  647. Bval += total / 2;
  648. return RGB(Rval*255/total/IN_SIZE, Gval*255/total/IN_SIZE, Bval*255/total/IN_SIZE);
  649. }
  650. ///////////////////////////////////////////////////////////////////////////////
  651. //
  652. ///////////////////////////////////////////////////////////////////////////////
  653. ///////////////////////////////////////////////////////////////////////////////
  654. //
  655. //  write this stuff in ASM!
  656. //
  657. ///////////////////////////////////////////////////////////////////////////////
  658. void Histogram24(
  659. BYTE *pb,
  660. int dx,
  661. int dy,
  662. WORD WidthBytes,
  663. LPHISTOGRAM lpHistogram)
  664. {
  665. int x,y;
  666. BYTE r,g,b;
  667. WORD w;
  668. UseHistogram(lpHistogram);
  669. WidthBytes -= (WORD) (dx*3);
  670. for (y=0; y<dy; y++)
  671. {
  672. for (x=0; x<dx; x++)
  673. {
  674. b = *pb++;
  675. g = *pb++;
  676. r = *pb++;
  677. w = (WORD) RGB16(r,g,b);
  678. IncHistogram(w);
  679. }
  680. pb += WidthBytes;
  681. }
  682. }
  683. void Histogram16(
  684. BYTE *pb,
  685. int dx,
  686. int dy,
  687. WORD WidthBytes,
  688. LPHISTOGRAM lpHistogram)
  689. {
  690. int x,y;
  691. WORD w;
  692. UseHistogram(lpHistogram);
  693. WidthBytes -= (WORD)(dx*2);
  694. for (y=0; y<dy; y++)
  695. {
  696. for (x=0; x<dx; x++)
  697. {
  698. w = *((WORD *)pb)++;
  699. w &= 0x7FFF;
  700. IncHistogram(w);
  701. }
  702. pb += WidthBytes;
  703. }
  704. }
  705. void Histogram8(
  706. BYTE *pb,
  707. int dx,
  708. int dy,
  709. WORD WidthBytes,
  710. LPHISTOGRAM lpHistogram,
  711. LPWORD lpColors)
  712. {
  713. int x,y;
  714. WORD w;
  715. UseHistogram(lpHistogram);
  716. WidthBytes -= (WORD)dx;
  717. for (y=0; y<dy; y++)
  718. {
  719. for (x=0; x<dx; x++)
  720. {
  721. w = lpColors[*pb++];
  722. IncHistogram(w);
  723. }
  724. pb += WidthBytes;
  725. }
  726. }
  727. void Histogram4(
  728. BYTE *pb,
  729. int dx,
  730. int dy,
  731. WORD WidthBytes,
  732. LPHISTOGRAM lpHistogram,
  733. LPWORD lpColors)
  734. {
  735. int x,y;
  736. BYTE b;
  737. WORD w;
  738. UseHistogram(lpHistogram);
  739. WidthBytes -= (WORD)((dx+1)/2);
  740. for (y=0; y<dy; y++)
  741. {
  742. for (x=0; x<(dx+1)/2; x++)
  743. {
  744. b = *pb++;
  745. w = lpColors[b>>4];
  746. IncHistogram(w);
  747. w = lpColors[b&0x0F];
  748. IncHistogram(w);
  749. }
  750. pb += WidthBytes;
  751. }
  752. }
  753. void Histogram1(
  754. BYTE *pb,
  755. int dx,
  756. int dy,
  757. WORD WidthBytes,
  758. LPHISTOGRAM lpHistogram,
  759. LPWORD lpColors)
  760. {
  761. int x,y,i;
  762. BYTE b;
  763. WORD w;
  764. UseHistogram(lpHistogram);
  765. WidthBytes -= (WORD)((dx+7)/8);
  766. for (y=0; y<dy; y++)
  767. {
  768. for (x=0; x<(dx+7)/8; x++)
  769. {
  770. b = *pb++;
  771. for (i=0; i<8; i++)
  772. {
  773. w = lpColors[b>>7];
  774. IncHistogram(w);
  775. b<<=1;
  776. }
  777. }
  778. pb += WidthBytes;
  779. }
  780. }
  781. ///////////////////////////////////////////////////////////////////////////////
  782. //
  783. //  write this stuff in ASM! too
  784. //
  785. ///////////////////////////////////////////////////////////////////////////////
  786. void Reduce24(
  787. BYTE *pbIn,
  788. int dx,
  789. int dy,
  790. WORD cbIn,
  791. BYTE *pbOut,
  792. WORD cbOut,
  793. LPBYTE lp16to8)
  794. {
  795. int x,y;
  796. BYTE r,g,b;
  797. cbOut -= (WORD)dx;
  798. cbIn -= (WORD)(dx*3);
  799. for (y=0; y<dy; y++)
  800. {
  801. for (x=0; x<dx; x++)
  802. {
  803. b = *pbIn++;
  804. g = *pbIn++;
  805. r = *pbIn++;
  806. *pbOut++ = lp16to8[RGB16(r,g,b)];
  807. }
  808. pbIn += cbIn;
  809. pbOut+= cbOut;
  810. }
  811. }
  812. void Reduce16(
  813. BYTE *pbIn,
  814. int dx,
  815. int dy,
  816. WORD cbIn,
  817. BYTE *pbOut,
  818. WORD cbOut,
  819. LPBYTE lp16to8)
  820. {
  821. int x,y;
  822. WORD w;
  823. cbOut -= (WORD)dx;
  824. cbIn -= (WORD)(dx*2);
  825. for (y=0; y<dy; y++)
  826. {
  827. for (x=0; x<dx; x++)
  828. {
  829. w = *((WORD *)pbIn)++;
  830. *pbOut++ = lp16to8[w&0x7FFF];
  831. }
  832. pbIn += cbIn;
  833. pbOut+= cbOut;
  834. }
  835. }
  836. void Reduce8(
  837. BYTE *pbIn,
  838. int dx,
  839. int dy,
  840. WORD cbIn,
  841. BYTE *pbOut,
  842. WORD cbOut,
  843. LPBYTE lp8to8)
  844. {
  845. int x,y;
  846. cbIn -= (WORD)dx;
  847. cbOut -= (WORD)dx;
  848. for (y=0; y<dy; y++)
  849. {
  850. for (x=0; x<dx; x++)
  851. {
  852. *pbOut++ = lp8to8[*pbIn++];
  853. }
  854. pbIn += cbIn;
  855. pbOut += cbOut;
  856. }
  857. }
  858. void Reduce4(
  859. BYTE *pbIn,
  860. int dx,
  861. int dy,
  862. WORD cbIn,
  863. BYTE *pbOut,
  864. WORD cbOut,
  865. LPBYTE lp8to8)
  866. {
  867. int x,y;
  868. BYTE b;
  869. cbIn -= (WORD)((dx+1)/2);
  870. cbOut -= (WORD)((dx+1)&~1);
  871. for (y=0; y<dy; y++)
  872. {
  873. for (x=0; x<(dx+1)/2; x++)
  874. {
  875. b = *pbIn++;
  876. *pbOut++ = lp8to8[b>>4];
  877. *pbOut++ = lp8to8[b&0x0F];
  878. }
  879. pbIn += cbIn;
  880. pbOut += cbOut;
  881. }
  882. }
  883. void Reduce1(
  884. BYTE *pbIn,
  885. int dx,
  886. int dy,
  887. WORD cbIn,
  888. BYTE *pbOut,
  889. WORD cbOut,
  890. LPBYTE lp8to8)
  891. {
  892. int x,y;
  893. BYTE b;
  894. cbIn -= (WORD)((dx+7)/8);
  895. cbOut -= (WORD)dx;
  896. for (y=0; y<dy; y++)
  897. {
  898. for (x=0; x<dx; x++)
  899. {
  900. if (x%8 == 0)
  901. b = *pbIn++;
  902. *pbOut++ = lp8to8[b>>7];
  903. b<<=1;
  904. }
  905. pbIn += cbIn;
  906. pbOut += cbOut;
  907. }
  908. }