ildither.c 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $XConsortium: ildither.c /main/5 1996/06/19 12:21:43 ageorge $ */
  24. /**---------------------------------------------------------------------
  25. ***
  26. *** (c)Copyright 1991 Hewlett-Packard Co.
  27. ***
  28. *** RESTRICTED RIGHTS LEGEND
  29. *** Use, duplication, or disclosure by the U.S. Government is subject to
  30. *** restrictions as set forth in sub-paragraph (c)(1)(ii) of the Rights in
  31. *** Technical Data and Computer Software clause in DFARS 252.227-7013.
  32. *** Hewlett-Packard Company
  33. *** 3000 Hanover Street
  34. *** Palo Alto, CA 94304 U.S.A.
  35. *** Rights for non-DOD U.S. Government Departments and Agencies are as set
  36. *** forth in FAR 52.227-19(c)(1,2).
  37. ***
  38. ***-------------------------------------------------------------------*/
  39. /* Contains ilConvertRGBToPalette(), called by ilConvert() to convert the RGB pipe
  40. image to a palette image. Contains dither / error diffusion code, but also
  41. code (from John Francis) for converting by finding the best "n" colors.
  42. */
  43. #include <stdlib.h>
  44. #include "ilint.h"
  45. #include "ilpipelem.h"
  46. #include "ilconvert.h"
  47. #include "ilerrors.h"
  48. /* =========================== COLOR DITHER CODE =============================== */
  49. /* Area dither: derived from software simulation of ELK hardware dither.
  50. Basically, use an 8x8 dither.
  51. For each pixel, fetch "kernel" based on position within image, mod 8.
  52. For each RGB, index into separate tables (which are index * "# levels - 1"
  53. plus a litte), add kernel, and divide by 256. Depending on the value of
  54. "kernel", this will yield a RGB value which is +/- the "color slammed" value,
  55. thus dithering. See John Beck for details (or other ELK heavy).
  56. */
  57. /* Multiply tables. Each entry "i" (0..255) gives the value of:
  58. i * (mulFactor - 1) * 256/255
  59. (truncated). Calculated by:
  60. main ()
  61. { int i, j, k;
  62. #define MULFACTOR 4
  63. i = 0;
  64. printf ("static unsigned short ilMul%d[256] = {\n", MULFACTOR);
  65. for (i = 0; i < 256; i++) {
  66. printf ("%4d", (int)((double)i * (MULFACTOR-1) * (double)256 / (double)255));
  67. if (i < 255) printf (",");
  68. if ((i % 16) == 15) printf ("\n");
  69. }
  70. printf ("};\n");
  71. }
  72. */
  73. /* Tables generated by /il/util/gendithertables.c .
  74. "ilDitherKernel" was truncated to be 8 by 8.
  75. */
  76. IL_PRIVATE const unsigned int _ilDitherKernel[64] = {
  77. 2, 194, 50, 242, 14, 206, 62, 254,
  78. 130, 66, 178, 114, 142, 78, 190, 126,
  79. 34, 226, 18, 210, 46, 238, 30, 222,
  80. 162, 98, 146, 82, 174, 110, 158, 94,
  81. 10, 202, 58, 250, 6, 198, 54, 246,
  82. 138, 74, 186, 122, 134, 70, 182, 118,
  83. 42, 234, 26, 218, 38, 230, 22, 214,
  84. 170, 106, 154, 90, 166, 102, 150, 86
  85. };
  86. IL_PRIVATE const unsigned short _ilMul8[256] = {
  87. 0, 7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 77, 84, 91, 98, 105,
  88. 112, 119, 126, 133, 140, 147, 154, 161, 168, 175, 182, 189, 196, 203, 210, 217,
  89. 224, 231, 238, 245, 252, 260, 267, 274, 281, 288, 295, 302, 309, 316, 323, 330,
  90. 337, 344, 351, 358, 365, 372, 379, 386, 393, 400, 407, 414, 421, 428, 435, 442,
  91. 449, 456, 463, 470, 477, 484, 491, 498, 505, 513, 520, 527, 534, 541, 548, 555,
  92. 562, 569, 576, 583, 590, 597, 604, 611, 618, 625, 632, 639, 646, 653, 660, 667,
  93. 674, 681, 688, 695, 702, 709, 716, 723, 730, 737, 744, 751, 758, 765, 773, 780,
  94. 787, 794, 801, 808, 815, 822, 829, 836, 843, 850, 857, 864, 871, 878, 885, 892,
  95. 899, 906, 913, 920, 927, 934, 941, 948, 955, 962, 969, 976, 983, 990, 997,1004,
  96. 1011,1018,1026,1033,1040,1047,1054,1061,1068,1075,1082,1089,1096,1103,1110,1117,
  97. 1124,1131,1138,1145,1152,1159,1166,1173,1180,1187,1194,1201,1208,1215,1222,1229,
  98. 1236,1243,1250,1257,1264,1271,1278,1286,1293,1300,1307,1314,1321,1328,1335,1342,
  99. 1349,1356,1363,1370,1377,1384,1391,1398,1405,1412,1419,1426,1433,1440,1447,1454,
  100. 1461,1468,1475,1482,1489,1496,1503,1510,1517,1524,1531,1539,1546,1553,1560,1567,
  101. 1574,1581,1588,1595,1602,1609,1616,1623,1630,1637,1644,1651,1658,1665,1672,1679,
  102. 1686,1693,1700,1707,1714,1721,1728,1735,1742,1749,1756,1763,1770,1777,1784,1792
  103. };
  104. IL_PRIVATE const unsigned short _ilMul4[256] = {
  105. 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45,
  106. 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93,
  107. 96, 99, 102, 105, 108, 111, 114, 117, 120, 123, 126, 129, 132, 135, 138, 141,
  108. 144, 147, 150, 153, 156, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 189,
  109. 192, 195, 198, 201, 204, 207, 210, 213, 216, 219, 222, 225, 228, 231, 234, 237,
  110. 240, 243, 246, 249, 252, 256, 259, 262, 265, 268, 271, 274, 277, 280, 283, 286,
  111. 289, 292, 295, 298, 301, 304, 307, 310, 313, 316, 319, 322, 325, 328, 331, 334,
  112. 337, 340, 343, 346, 349, 352, 355, 358, 361, 364, 367, 370, 373, 376, 379, 382,
  113. 385, 388, 391, 394, 397, 400, 403, 406, 409, 412, 415, 418, 421, 424, 427, 430,
  114. 433, 436, 439, 442, 445, 448, 451, 454, 457, 460, 463, 466, 469, 472, 475, 478,
  115. 481, 484, 487, 490, 493, 496, 499, 502, 505, 508, 512, 515, 518, 521, 524, 527,
  116. 530, 533, 536, 539, 542, 545, 548, 551, 554, 557, 560, 563, 566, 569, 572, 575,
  117. 578, 581, 584, 587, 590, 593, 596, 599, 602, 605, 608, 611, 614, 617, 620, 623,
  118. 626, 629, 632, 635, 638, 641, 644, 647, 650, 653, 656, 659, 662, 665, 668, 671,
  119. 674, 677, 680, 683, 686, 689, 692, 695, 698, 701, 704, 707, 710, 713, 716, 719,
  120. 722, 725, 728, 731, 734, 737, 740, 743, 746, 749, 752, 755, 758, 761, 764, 768
  121. };
  122. static const unsigned short _ilMul2[256] = {
  123. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
  124. 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
  125. 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
  126. 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
  127. 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
  128. 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
  129. 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
  130. 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
  131. 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
  132. 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
  133. 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
  134. 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
  135. 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
  136. 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
  137. 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
  138. 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 256
  139. };
  140. /* Private data for cvt to palette: first part set when element added. */
  141. typedef struct {
  142. ilBool diffusion; /* true if error diffusion; else dither */
  143. ilPtr pTranslate; /* ptr to lookup table (image) */
  144. ilByte translate [256]; /* identity image if no mapImage given */
  145. unsigned short *pPalette; /* palette to destroy or null */
  146. long *pColorTable; /* color lookup table (diffusion) or null */
  147. int shifts[3]; /* RGB right shifts for diffusion */
  148. int nColors; /* for "choose colors": nColors to fit to */
  149. const unsigned short *pMulTable[3]; /* dither other than 484 only: pMul? */
  150. /* Below data inited by Init() function. */
  151. long width; /* width of src/dst images */
  152. long srcRowBytes; /* bytes/row of src image */
  153. ilPtr pSrcPixels; /* ptr to start of src pixels */
  154. long dstRowBytes; /* bytes/row of dst image */
  155. ilPtr pDstPixels; /* ptr to start of dst pixels */
  156. long y; /* current logical line within the image */
  157. int *pErrors; /* error buffer (diffusion) or null */
  158. } ilDitherPrivRec, *ilDitherPrivPtr;
  159. /* Init() function: init the counter of "y" within private; load image pixel
  160. address and rowBytes into private for faster reference in Execute().
  161. */
  162. static ilError ilInitDitherRGB (
  163. ilDitherPrivPtr pPriv,
  164. ilImageInfo *pSrcImage,
  165. ilImageInfo *pDstImage
  166. )
  167. {
  168. pPriv->width = pSrcImage->width;
  169. pPriv->srcRowBytes = pSrcImage->plane[0].nBytesPerRow;
  170. pPriv->pSrcPixels = pSrcImage->plane[0].pPixels;
  171. pPriv->dstRowBytes = pDstImage->plane[0].nBytesPerRow;
  172. pPriv->pDstPixels = pDstImage->plane[0].pPixels;
  173. pPriv->y = 0;
  174. /* If error diffusion, create an error buffer: 3 ints (1 per R/G/B), width + 2
  175. for easy access to first / last value in line (point + 3 into it).
  176. */
  177. if (pPriv->diffusion) {
  178. pPriv->pErrors = (int *)IL_MALLOC_ZERO (sizeof (int) * 3 * (pPriv->width + 2));
  179. if (!pPriv->pErrors)
  180. return IL_ERROR_MALLOC;
  181. }
  182. return IL_OK;
  183. }
  184. /* Destroy() function: free pPriv->pPalette. */
  185. static ilError ilDestroyDitherRGB (
  186. ilDitherPrivPtr pPriv
  187. )
  188. {
  189. if (pPriv->pPalette)
  190. IL_FREE (pPriv->pPalette);
  191. if (pPriv->pColorTable)
  192. IL_FREE (pPriv->pColorTable);
  193. return IL_OK;
  194. }
  195. /* Cleanup() function: only if diffusion: free pPriv->pErrors. */
  196. static ilError ilCleanupDitherRGB (
  197. ilDitherPrivPtr pPriv
  198. )
  199. {
  200. if (pPriv->pErrors)
  201. IL_FREE (pPriv->pErrors);
  202. return IL_OK;
  203. }
  204. /* ---------------------- ilExecuteDitherRGB ------------------------ */
  205. /* Execute() function: dither (IL_DITHER) to arbitrary powers of 2, based
  206. on shift values and pointers to "mul" tables in private using an 8x8 matrix.
  207. */
  208. static ilError ilExecuteDitherRGB (
  209. ilExecuteData *pData,
  210. long dstLine,
  211. long *pNLines
  212. )
  213. {
  214. ilDitherPrivPtr pPriv;
  215. long nLinesM1;
  216. long srcRowBytes, dstRowBytes;
  217. ilPtr pSrcLine, pDstLine;
  218. long x, yMod8Times8, width;
  219. const unsigned short *pMulR, *pMulG, *pMulB;
  220. ilPtr pSrc, pDst, pTranslate;
  221. unsigned long pixel, kernel;
  222. int upShiftR, upShiftG;
  223. pPriv = (ilDitherPrivPtr)pData->pPrivate;
  224. width = pPriv->width;
  225. srcRowBytes = pPriv->srcRowBytes;
  226. pSrcLine = pPriv->pSrcPixels + pData->srcLine * srcRowBytes;
  227. dstRowBytes = pPriv->dstRowBytes;
  228. pDstLine = pPriv->pDstPixels + dstLine * dstRowBytes;
  229. yMod8Times8 = (pPriv->y & 7) << 3;
  230. nLinesM1 = *pNLines;
  231. if (nLinesM1 <= 0)
  232. return IL_OK;
  233. pPriv->y += nLinesM1;
  234. nLinesM1--;
  235. /* Do dither; see comments above for overall approach */
  236. pTranslate = pPriv->pTranslate;
  237. upShiftR = 8 - pPriv->shifts[1];
  238. upShiftG = 8 - pPriv->shifts[2];
  239. pMulR = pPriv->pMulTable[0];
  240. pMulG = pPriv->pMulTable[1];
  241. pMulB = pPriv->pMulTable[2];
  242. do {
  243. pSrc = pSrcLine;
  244. pSrcLine += srcRowBytes;
  245. pDst = pDstLine;
  246. pDstLine += dstRowBytes;
  247. x = 0;
  248. while (x < width) {
  249. kernel = _ilDitherKernel [yMod8Times8 | (x & 7)];
  250. x++;
  251. pixel = ((pMulR[*pSrc++] + kernel) >> 8) << upShiftR;
  252. pixel += (pMulG[*pSrc++] + kernel) >> 8;
  253. pixel <<= upShiftG;
  254. pixel += (pMulB[*pSrc++] + kernel) >> 8;
  255. *pDst++ = pTranslate[pixel];
  256. }
  257. yMod8Times8 += (1 << 3);
  258. if (yMod8Times8 >= (8 << 3))
  259. yMod8Times8 = 0;
  260. } while (--nLinesM1 >= 0);
  261. return IL_OK;
  262. }
  263. /* ---------------------- ilExecuteDitherRGBTo484 ------------------------ */
  264. /* Execute() function: dither to 484 and pack the given # of src lines.
  265. */
  266. static ilError ilExecuteDitherRGBTo484 (
  267. ilExecuteData *pData,
  268. long dstLine,
  269. long *pNLines
  270. )
  271. {
  272. ilDitherPrivPtr pPriv;
  273. long nLinesM1;
  274. long srcRowBytes, dstRowBytes;
  275. ilPtr pSrcLine, pDstLine;
  276. long x, yMod8Times8, width;
  277. const unsigned short *pMul8, *pMul4;
  278. ilPtr pSrc, pDst, pTranslate;
  279. unsigned long pixel, kernel;
  280. pPriv = (ilDitherPrivPtr)pData->pPrivate;
  281. width = pPriv->width;
  282. srcRowBytes = pPriv->srcRowBytes;
  283. pSrcLine = pPriv->pSrcPixels + pData->srcLine * srcRowBytes;
  284. dstRowBytes = pPriv->dstRowBytes;
  285. pDstLine = pPriv->pDstPixels + dstLine * dstRowBytes;
  286. yMod8Times8 = (pPriv->y & 7) << 3;
  287. nLinesM1 = *pNLines;
  288. if (nLinesM1 <= 0)
  289. return IL_OK;
  290. pPriv->y += nLinesM1;
  291. nLinesM1--;
  292. /* Do dither; see comments above for overall approach */
  293. pTranslate = pPriv->pTranslate;
  294. pMul4 = _ilMul4;
  295. pMul8 = _ilMul8;
  296. do {
  297. pSrc = pSrcLine;
  298. pSrcLine += srcRowBytes;
  299. pDst = pDstLine;
  300. pDstLine += dstRowBytes;
  301. x = 0;
  302. while (x < width) {
  303. kernel = _ilDitherKernel [yMod8Times8 | (x & 7)];
  304. x++;
  305. pixel = ((pMul4[*pSrc++] + kernel) >> 8) << 3;
  306. pixel += (pMul8[*pSrc++] + kernel) >> 8;
  307. pixel <<= 2;
  308. pixel += (pMul4[*pSrc++] + kernel) >> 8;
  309. *pDst++ = pTranslate[pixel];
  310. }
  311. yMod8Times8 += (1 << 3);
  312. if (yMod8Times8 >= (8 << 3))
  313. yMod8Times8 = 0;
  314. } while (--nLinesM1 >= 0);
  315. return IL_OK;
  316. }
  317. /* =========================== COLOR DIFFUSION CODE =============================== */
  318. /* ---------------------- ilExecuteDiffusionRGB ------------------------ */
  319. /* Execute() function: error diffuse and pack the given # of src lines.
  320. */
  321. static ilError ilExecuteDiffusionRGB (
  322. ilExecuteData *pData,
  323. long dstLine,
  324. long *pNLines
  325. )
  326. {
  327. ilDitherPrivPtr pPriv;
  328. long srcRowBytes, dstRowBytes;
  329. long nLinesM1, nPixelsM1, nPixelsM1Init;
  330. int red, green, blue;
  331. int redAboveError, greenAboveError, blueAboveError;
  332. int redAboveLeftError, greenAboveLeftError, blueAboveLeftError;
  333. int redAboveRightError, greenAboveRightError, blueAboveRightError;
  334. int redRShift, greenRShift, blueRShift;
  335. long pixel;
  336. int *pError;
  337. ilPtr pSrc;
  338. long *pColorTable;
  339. ilPtr pDst, pSrcLine, pDstLine;
  340. pPriv = (ilDitherPrivPtr)pData->pPrivate;
  341. srcRowBytes = pPriv->srcRowBytes;
  342. pSrcLine = pPriv->pSrcPixels + pData->srcLine * srcRowBytes;
  343. dstRowBytes = pPriv->dstRowBytes;
  344. pDstLine = pPriv->pDstPixels + dstLine * dstRowBytes;
  345. nLinesM1 = *pNLines - 1;
  346. nPixelsM1Init = pPriv->width - 1;
  347. pColorTable = pPriv->pColorTable;
  348. redRShift = pPriv->shifts[0];
  349. greenRShift = pPriv->shifts[1];
  350. blueRShift = pPriv->shifts[2];
  351. do {
  352. pSrc = pSrcLine;
  353. pSrcLine += srcRowBytes;
  354. pDst = pDstLine;
  355. pDstLine += dstRowBytes;
  356. nPixelsM1 = nPixelsM1Init;
  357. pError = pPriv->pErrors;
  358. red = redAboveError = 0;
  359. redAboveRightError = *pError;
  360. green = greenAboveError = 0;
  361. greenAboveRightError = *(pError + 1);
  362. blue = blueAboveError = 0;
  363. blueAboveRightError = *(pError + 2);
  364. /* Do Floyd-Steinberg error diffusion. For each pixel, "color slam" to
  365. pack RGB into "pixel", then use pixel as index into pColorTable to
  366. find out what actual RGB value that pseudo-color pixel represents.
  367. Subtract the actual from the original (desired) value to determine the
  368. error, and save error in red/green/blue, and in error buffer (*pError)
  369. Factor in errors from surrounding pixels using: 7/16 of left,
  370. 1/16 of above left, 5/16 of above and 3/16 of above right. Effectively
  371. multiply by each, doing successive adds, then >> 4 for / 16.
  372. */
  373. do {
  374. redAboveLeftError = redAboveError;
  375. redAboveError = redAboveRightError;
  376. redAboveRightError = *(pError + 3);
  377. pixel = red;
  378. red += redAboveError;
  379. pixel += red;
  380. red += redAboveRightError;
  381. pixel += red;
  382. red = *pSrc++ + ((pixel + pixel + red + redAboveLeftError) >> 4);
  383. if (red >> 8) goto edClipR;
  384. edClipRetR:
  385. greenAboveLeftError = greenAboveError;
  386. greenAboveError = greenAboveRightError;
  387. greenAboveRightError = *(pError + 4);
  388. pixel = green;
  389. green += greenAboveError;
  390. pixel += green;
  391. green += greenAboveRightError;
  392. pixel += green;
  393. green = *pSrc++ + ((pixel + pixel + green + greenAboveLeftError) >> 4);
  394. if (green >> 8) goto edClipG;
  395. edClipRetG:
  396. blueAboveLeftError = blueAboveError;
  397. blueAboveError = blueAboveRightError;
  398. blueAboveRightError = *(pError + 5);
  399. pixel = blue;
  400. blue += blueAboveError;
  401. pixel += blue;
  402. blue += blueAboveRightError;
  403. pixel += blue;
  404. blue = *pSrc++ + ((pixel + pixel + blue + blueAboveLeftError) >> 4);
  405. if (blue >> 8) goto edClipB;
  406. edClipRetB:
  407. /* Color slam to find 8 bit pixel to use. */
  408. pixel = (red >> redRShift);
  409. pixel <<= (8 - greenRShift);
  410. pixel |= (green >> greenRShift);
  411. pixel <<= (8 - blueRShift);
  412. pixel |= (blue >> blueRShift);
  413. pixel = pColorTable[pixel];
  414. *pDst++ = pixel;
  415. pixel >>= 8;
  416. red -= ((ilByte)pixel);
  417. *pError++ = red;
  418. pixel >>= 8;
  419. green -= ((ilByte)pixel);
  420. *pError++ = green;
  421. blue -= (ilByte)(pixel >> 8);
  422. *pError++ = blue;
  423. } while (--nPixelsM1 >= 0);
  424. } while (--nLinesM1 >= 0);
  425. return IL_OK;
  426. /* Goto points for RGB value out of range (the exceptional case); done this
  427. way for significant performance gain, due to not taking the branch.
  428. */
  429. edClipR: if (red < 0) red = 0; else red = 255;
  430. goto edClipRetR;
  431. edClipG: if (green < 0) green = 0; else green = 255;
  432. goto edClipRetG;
  433. edClipB: if (blue < 0) blue = 0; else blue = 255;
  434. goto edClipRetB;
  435. }
  436. /* ---------------------- ilExecuteDiffusion484 ------------------------ */
  437. /* Execute() function: error diffuse, specific to levels 484.
  438. */
  439. static ilError ilExecuteDiffusion484 (
  440. ilExecuteData *pData,
  441. long dstLine,
  442. long *pNLines
  443. )
  444. {
  445. ilDitherPrivPtr pPriv;
  446. long srcRowBytes, dstRowBytes;
  447. long nLinesM1, nPixelsM1, nPixelsM1Init;
  448. int red, green, blue;
  449. int redAboveError, greenAboveError, blueAboveError;
  450. int redAboveLeftError, greenAboveLeftError, blueAboveLeftError;
  451. int redAboveRightError, greenAboveRightError, blueAboveRightError;
  452. long pixel;
  453. int *pError;
  454. ilPtr pSrc;
  455. long *pColorTable;
  456. ilPtr pDst, pSrcLine, pDstLine;
  457. pPriv = (ilDitherPrivPtr)pData->pPrivate;
  458. srcRowBytes = pPriv->srcRowBytes;
  459. pSrcLine = pPriv->pSrcPixels + pData->srcLine * srcRowBytes;
  460. dstRowBytes = pPriv->dstRowBytes;
  461. pDstLine = pPriv->pDstPixels + dstLine * dstRowBytes;
  462. nLinesM1 = *pNLines - 1;
  463. nPixelsM1Init = pPriv->width - 1;
  464. pColorTable = pPriv->pColorTable;
  465. /* Error diffusion, same as general case above, but # levels of RGB = 484. */
  466. do {
  467. pSrc = pSrcLine;
  468. pSrcLine += srcRowBytes;
  469. pDst = pDstLine;
  470. pDstLine += dstRowBytes;
  471. nPixelsM1 = nPixelsM1Init;
  472. pError = pPriv->pErrors;
  473. red = redAboveError = 0;
  474. redAboveRightError = *pError;
  475. green = greenAboveError = 0;
  476. greenAboveRightError = *(pError + 1);
  477. blue = blueAboveError = 0;
  478. blueAboveRightError = *(pError + 2);
  479. do {
  480. redAboveLeftError = redAboveError;
  481. redAboveError = redAboveRightError;
  482. redAboveRightError = *(pError + 3);
  483. pixel = red;
  484. red += redAboveError;
  485. pixel += red;
  486. red += redAboveRightError;
  487. pixel += red;
  488. red = *pSrc++ + ((pixel + pixel + red + redAboveLeftError) >> 4);
  489. if (red >> 8) goto edClipR;
  490. edClipRetR:
  491. greenAboveLeftError = greenAboveError;
  492. greenAboveError = greenAboveRightError;
  493. greenAboveRightError = *(pError + 4);
  494. pixel = green;
  495. green += greenAboveError;
  496. pixel += green;
  497. green += greenAboveRightError;
  498. pixel += green;
  499. green = *pSrc++ + ((pixel + pixel + green + greenAboveLeftError) >> 4);
  500. if (green >> 8) goto edClipG;
  501. edClipRetG:
  502. blueAboveLeftError = blueAboveError;
  503. blueAboveError = blueAboveRightError;
  504. blueAboveRightError = *(pError + 5);
  505. pixel = blue;
  506. blue += blueAboveError;
  507. pixel += blue;
  508. blue += blueAboveRightError;
  509. pixel += blue;
  510. blue = *pSrc++ + ((pixel + pixel + blue + blueAboveLeftError) >> 4);
  511. if (blue >> 8) goto edClipB;
  512. edClipRetB:
  513. /* Color slam to find 8 bit pixel to use. */
  514. pixel = (red >> 6);
  515. pixel <<= 3;
  516. pixel |= (green >> 5);
  517. pixel <<= 2;
  518. pixel |= (blue >> 6);
  519. pixel = pColorTable[pixel];
  520. *pDst++ = pixel;
  521. pixel >>= 8;
  522. red -= ((ilByte)pixel);
  523. *pError++ = red;
  524. pixel >>= 8;
  525. green -= ((ilByte)pixel);
  526. *pError++ = green;
  527. blue -= (ilByte)(pixel >> 8);
  528. *pError++ = blue;
  529. } while (--nPixelsM1 >= 0);
  530. } while (--nLinesM1 >= 0);
  531. return IL_OK;
  532. /* Goto points for RGB value out of range (the exceptional case); done this
  533. way for significant performance gain, due to not taking the branch.
  534. */
  535. edClipR: if (red < 0) red = 0; else red = 255;
  536. goto edClipRetR;
  537. edClipG: if (green < 0) green = 0; else green = 255;
  538. goto edClipRetG;
  539. edClipB: if (blue < 0) blue = 0; else blue = 255;
  540. goto edClipRetB;
  541. }
  542. /* -------------------- ilExecuteQuickDiffusionRGB --------------------- */
  543. /* Execute() function for "quick" dithering
  544. */
  545. static ilError ilExecuteQuickDiffusionRGB (
  546. ilExecuteData *pData,
  547. long dstLine,
  548. long *pNLines
  549. )
  550. {
  551. ilDitherPrivPtr pPriv;
  552. long srcRowBytes, dstRowBytes;
  553. long nLinesM1, nPixelsM1, nPixelsM1Init;
  554. int red, green, blue;
  555. int redRShift, greenRShift, blueRShift;
  556. long pixel;
  557. int *pError;
  558. ilPtr pSrc;
  559. long *pColorTable;
  560. ilPtr pDst, pSrcLine, pDstLine;
  561. /* Same as regular diffusion above, except spread the errors in a simpler and
  562. quicker way: 1/2 of error from pixel to left, 1/2 from pixel above.
  563. */
  564. pPriv = (ilDitherPrivPtr)pData->pPrivate;
  565. srcRowBytes = pPriv->srcRowBytes;
  566. pSrcLine = pPriv->pSrcPixels + pData->srcLine * srcRowBytes;
  567. dstRowBytes = pPriv->dstRowBytes;
  568. pDstLine = pPriv->pDstPixels + dstLine * dstRowBytes;
  569. nLinesM1 = *pNLines - 1;
  570. nPixelsM1Init = pPriv->width - 1;
  571. pColorTable = pPriv->pColorTable;
  572. redRShift = pPriv->shifts[0];
  573. greenRShift = pPriv->shifts[1];
  574. blueRShift = pPriv->shifts[2];
  575. do {
  576. pSrc = pSrcLine;
  577. pSrcLine += srcRowBytes;
  578. pDst = pDstLine;
  579. pDstLine += dstRowBytes;
  580. nPixelsM1 = nPixelsM1Init;
  581. pError = pPriv->pErrors;
  582. red = green = blue = 0;
  583. do {
  584. red = *pSrc++ + ((red + pError[0]) >> 1);
  585. if (red >> 8) goto qdClipR;
  586. qdClipRetR:
  587. green = *pSrc++ + ((green + pError[1]) >> 1);
  588. if (green >> 8) goto qdClipG;
  589. qdClipRetG:
  590. blue = *pSrc++ + ((blue + pError[2]) >> 1);
  591. if (blue >> 8) goto qdClipB;
  592. qdClipRetB:
  593. /* Color slam to find 8 bit pixel to use. */
  594. pixel = (red >> redRShift);
  595. pixel <<= (8 - greenRShift);
  596. pixel |= (green >> greenRShift);
  597. pixel <<= (8 - blueRShift);
  598. pixel |= (blue >> blueRShift);
  599. pixel = pColorTable[pixel];
  600. *pDst++ = pixel;
  601. pixel >>= 8;
  602. red -= ((ilByte)pixel);
  603. *pError++ = red;
  604. pixel >>= 8;
  605. green -= ((ilByte)pixel);
  606. *pError++ = green;
  607. blue -= (ilByte)(pixel >> 8);
  608. *pError++ = blue;
  609. } while (--nPixelsM1 >= 0);
  610. } while (--nLinesM1 >= 0);
  611. return IL_OK;
  612. /* Goto points for RGB value out of range (the exceptional case); done this
  613. way for significant performance gain, due to not taking the branch.
  614. */
  615. qdClipR: if (red < 0) red = 0; else red = 255;
  616. goto qdClipRetR;
  617. qdClipG: if (green < 0) green = 0; else green = 255;
  618. goto qdClipRetG;
  619. qdClipB: if (blue < 0) blue = 0; else blue = 255;
  620. goto qdClipRetB;
  621. }
  622. /* =========================== CHOOSE COLORS CODE =============================== */
  623. static double weight[3] = {0.299, 0.587, 0.114};
  624. /* Private data types used by assorted ConverterExecute pipe filter private functions. */
  625. typedef struct {
  626. unsigned long number;
  627. unsigned long moment[3];
  628. } convertBoxTotalRec;
  629. typedef struct {
  630. unsigned char lower[3]; /* Lower bounds for box (along each axis) */
  631. unsigned char upper[3]; /* Upper bounds for box (along each axis) */
  632. unsigned char index; /* Which box will be chosen as next split */
  633. unsigned char plane; /* Axis & Position of optimum split plane */
  634. double split; /* The best split available for named box */
  635. } convertBoxRec;
  636. typedef struct {
  637. convertBoxTotalRec total;
  638. unsigned long int slice[3][32];
  639. } convertBoxCountRec;
  640. /* --------------------------- CountBox --------------------------- */
  641. /* Count the number of occupied cells in a specified subbox.
  642. */
  643. static unsigned long CountBox (
  644. convertBoxRec *pBox,
  645. unsigned long *Ftable,
  646. convertBoxCountRec *count
  647. )
  648. {
  649. int axis, plane, index, rgb[3];
  650. count->total.number = 0;
  651. for ( axis = 0 ; axis < 3 ; axis++ ) {
  652. rgb[axis] = pBox->lower[axis];
  653. count->total.moment[axis] = 0;
  654. for ( plane = 0 ; plane < 32 ; plane++ ) count->slice[axis][plane] = 0;
  655. }
  656. L: for ( index = 0, axis = 0 ; axis < 3 ; axis++ ) index = (index << 5) + rgb[axis];
  657. if ( Ftable[index] ) {
  658. count->total.number += Ftable[index];
  659. for ( axis = 0 ; axis < 3 ; axis++ ) count->slice[axis][rgb[axis]] += Ftable[index];
  660. }
  661. for ( axis = 2 ; axis >= 0 ; axis-- ) {
  662. if ( ++rgb[axis] <= pBox->upper[axis] ) goto L;
  663. rgb[axis] = pBox->lower[axis];
  664. }
  665. for ( axis = 0 ; axis < 3 ; axis++ )
  666. for ( plane = 0 ; plane < 32 ; plane++ )
  667. count->total.moment[axis] += count->slice[axis][plane]*plane;
  668. #if 0
  669. printf("CountBox: %2d:%-2d %2d:%-2d %2d:%-2d %8d\n",
  670. pBox->lower[0], pBox->upper[0], pBox->lower[1], pBox->upper[1],
  671. pBox->lower[2], pBox->upper[2], count->total.number );
  672. #endif
  673. return count->total.number;
  674. }
  675. static int ScanBox(
  676. int box,
  677. unsigned long *Ftable,
  678. convertBoxRec *BoxTable,
  679. int nBoxes,
  680. int nColors
  681. )
  682. {
  683. convertBoxTotalRec total, part1, part2;
  684. convertBoxCountRec count;
  685. convertBoxRec slice;
  686. convertBoxRec *pBox = &BoxTable[box];
  687. double temp, ssq1 = 0.0f, ssq2;
  688. int axis, plane, rgb, n;
  689. if ( CountBox( pBox, Ftable, &count ) ) {
  690. total = count.total;
  691. while ( count.slice[0][pBox->lower[0]] == 0 ) pBox->lower[0]++;
  692. while ( count.slice[0][pBox->upper[0]] == 0 ) pBox->upper[0]--;
  693. while ( count.slice[1][pBox->lower[1]] == 0 ) pBox->lower[1]++;
  694. while ( count.slice[1][pBox->upper[1]] == 0 ) pBox->upper[1]--;
  695. while ( count.slice[2][pBox->lower[2]] == 0 ) pBox->lower[2]++;
  696. while ( count.slice[2][pBox->upper[2]] == 0 ) pBox->upper[2]--;
  697. slice = *pBox;
  698. slice.split = 0.0 ;
  699. slice.index = box ;
  700. for ( axis = 0 ; axis < 3 ; axis++ )
  701. if ( pBox->upper[axis] > pBox->lower[axis] ) {
  702. part1.number = 0;
  703. part1.moment[0] = 0;
  704. part1.moment[1] = 0;
  705. part1.moment[2] = 0;
  706. part2 = total;
  707. for ( plane = pBox->lower[axis] ; ; plane++ ) {
  708. slice.lower[axis] = plane;
  709. slice.upper[axis] = plane;
  710. if ( !CountBox( &slice, Ftable, &count ) ) continue;
  711. slice.lower[axis] = pBox->lower[axis];
  712. ssq1 = 0.0;
  713. ssq2 = 0.0;
  714. for ( rgb = 0 ; rgb < 3 ; rgb++ ) {
  715. temp = weight[rgb]*(part1.moment[rgb] += count.total.moment[rgb]);
  716. ssq1 += temp*temp;
  717. temp = weight[rgb]*(part2.moment[rgb] -= count.total.moment[rgb]);
  718. ssq2 += temp*temp;
  719. }
  720. part1.number += count.total.number;
  721. part2.number -= count.total.number;
  722. if ( part2.number == 0 ) break;
  723. temp = (ssq1 / part1.number) + (ssq2 / part2.number);
  724. if ( slice.split < temp ) {
  725. slice.split = temp;
  726. slice.plane = (axis << 5) | plane;
  727. }
  728. }
  729. }
  730. if ( (slice.split -= ssq1 / total.number) > BoxTable[n = nColors - 1].split ) {
  731. while ( (--n >= nBoxes) && (slice.split > BoxTable[n].split) ) BoxTable[n+1] = BoxTable[n];
  732. BoxTable[++n] = slice;
  733. }
  734. #if 0
  735. printf( " Adjusted box %3d [%2d:%-2d %2d:%-2d %2d:%-2d] @ %1d.%-2d %10.0lf\n",
  736. box, slice.lower[0], slice.upper[0], slice.lower[1],
  737. slice.upper[1], slice.lower[2], slice.upper[2],
  738. slice.plane >> 5, slice.plane & 31, slice.split );
  739. #endif
  740. }
  741. return (BoxTable[nBoxes].split > 0.0);
  742. }
  743. /* --------------------- ilChooseColorsExecute ------------------------- */
  744. /* Execute() pipe element function for IL_CHOOSE_COLORS option.
  745. */
  746. static ilError ilChooseColorsExecute (
  747. ilExecuteData *pData,
  748. long dstLine,
  749. long *pNLines
  750. )
  751. {
  752. ilDitherPrivPtr pPriv;
  753. long srcRowBytes, dstRowBytes, nRowsM1, nLinesM1;
  754. long width, height;
  755. ilPtr pSrcLine, pDstLine;
  756. long rowCount;
  757. ilPtr pSrc, pDst;
  758. unsigned short *pPalette;
  759. int nBoxes, nColors;
  760. int index, axis, plane, inner, outer;
  761. unsigned long *Ftable;
  762. convertBoxRec box[256];
  763. convertBoxTotalRec total[256];
  764. /* Get pointers to src, dst scan lines, bytes/row (aka "stride"),
  765. and width, # lines minus 1 (M1).
  766. */
  767. pPriv = (ilDitherPrivPtr)pData->pPrivate;
  768. pPalette = pPriv->pPalette;
  769. nColors = pPriv->nColors;
  770. width = pPriv->width;
  771. height = *pNLines;
  772. srcRowBytes = pPriv->srcRowBytes;
  773. dstRowBytes = pPriv->dstRowBytes;
  774. if ( !(Ftable = (unsigned long *) calloc( sizeof *Ftable, 32*32*32 )) )
  775. return IL_ERROR_MALLOC;
  776. pSrcLine = pPriv->pSrcPixels + pData->srcLine * srcRowBytes;
  777. nRowsM1 = width - 1;
  778. nLinesM1 = height - 1;
  779. do {
  780. pSrc = pSrcLine;
  781. pSrcLine += srcRowBytes;
  782. rowCount = nRowsM1;
  783. do {
  784. ilByte R, G, B;
  785. R = *pSrc++; /* red */
  786. G = *pSrc++; /* green */
  787. B = *pSrc++; /* blue */
  788. Ftable[((R & 0xF8) << 7) + ((G & 0xF8) << 2) + ((B & 0xF8) >> 3)]++;
  789. } while (--rowCount >= 0);
  790. } while (--nLinesM1 >= 0);
  791. box[0].lower[0] = box[0].lower[1] = box[0].lower[2] = 0;
  792. box[0].upper[0] = box[0].upper[1] = box[0].upper[2] = 31;
  793. for ( index = 0 ; index < 256 ; index++ ) box[index].split = 0.0;
  794. if ( (nBoxes = 1) < nColors ) while ( 1 ) {
  795. if ( !ScanBox( nBoxes-1, Ftable, box, nBoxes, nColors ) ) break;
  796. index = box[nBoxes].index;
  797. plane = box[nBoxes].plane & 31;
  798. axis = box[nBoxes].plane >> 5;
  799. box[nBoxes] = box[index];
  800. box[nBoxes].upper[axis] = plane;
  801. box[ index].lower[axis] = plane + 1;
  802. if ( ++nBoxes == nColors ) break;
  803. ScanBox( index, Ftable, box, nBoxes, nColors );
  804. }
  805. for ( index = 0 ; index < nBoxes ; index++ ) {
  806. convertBoxCountRec count;
  807. CountBox( &box[index], Ftable, &count );
  808. pPalette[ 0 + index] = (2048.0*count.total.moment[0])/count.total.number + 1024.0;
  809. pPalette[256 + index] = (2048.0*count.total.moment[1])/count.total.number + 1024.0;
  810. pPalette[512 + index] = (2048.0*count.total.moment[2])/count.total.number + 1024.0;
  811. }
  812. for ( outer = 0 ; outer < nBoxes ; outer++ ) {
  813. convertBoxRec *pBox = &box[outer];
  814. int R, G, B;
  815. int rgb_inner, rgb_outer, rgb_limit;
  816. unsigned char multiple, candidate[256];
  817. double ssq_inner, ssq_outer, distance;
  818. multiple = 0;
  819. candidate[outer] = 1;
  820. for ( inner = 0 ; inner < nBoxes ; inner++ ) {
  821. if ( inner == outer ) continue;
  822. candidate[inner] = 0;
  823. ssq_inner = 0.0;
  824. ssq_outer = 0.0;
  825. for ( axis = 0 ; axis < 3 ; axis++ ) {
  826. rgb_inner = pPalette[inner + (axis << 8)];
  827. rgb_outer = pPalette[outer + (axis << 8)];
  828. rgb_limit = (((rgb_inner < rgb_outer) ? pBox->lower[axis] : pBox->upper[axis]) << 11) + 0x0400;
  829. distance = weight[axis]*(rgb_limit - rgb_inner); ssq_inner += distance*distance;
  830. distance = weight[axis]*(rgb_limit - rgb_outer); ssq_outer += distance*distance;
  831. }
  832. if ( ssq_inner < ssq_outer ) candidate[inner] = multiple = 1;
  833. }
  834. for ( R = pBox->lower[0] ; R <= pBox->upper[0] ; R++ )
  835. for ( G = pBox->lower[1] ; G <= pBox->upper[1] ; G++ )
  836. for ( B = pBox->lower[2] ; B <= pBox->upper[2] ; B++ )
  837. if ( multiple ) {
  838. index = (R << 10) + (G << 5) + B;
  839. ssq_outer = 1.0e12;
  840. for ( inner = 0 ; inner < nBoxes ; inner++ ) if ( candidate[inner] ) {
  841. distance = weight[0]*(((R << 11) + 0x0400) - pPalette[inner + 0 ]); ssq_inner = distance*distance;
  842. distance = weight[1]*(((G << 11) + 0x0400) - pPalette[inner + 256]); ssq_inner += distance*distance;
  843. distance = weight[2]*(((B << 11) + 0x0400) - pPalette[inner + 512]); ssq_inner += distance*distance;
  844. if ( ssq_inner < ssq_outer ) {ssq_outer = ssq_inner; Ftable[index] = inner;}
  845. }
  846. } else Ftable[(R << 10) + (G << 5) + B] = outer;
  847. }
  848. for ( index = 0 ; index < nBoxes ; index++ )
  849. total[index].number = total[index].moment[0] = total[index].moment[1] = total[index].moment[2] = 0;
  850. pSrcLine = pPriv->pSrcPixels + pData->srcLine * srcRowBytes;
  851. pDstLine = pPriv->pDstPixels + dstLine * dstRowBytes;
  852. nRowsM1 = width - 1;
  853. nLinesM1 = height - 1;
  854. do {
  855. pSrc = pSrcLine;
  856. pSrcLine += srcRowBytes;
  857. pDst = pDstLine;
  858. pDstLine += dstRowBytes;
  859. rowCount = nRowsM1;
  860. do {
  861. ilByte R, G, B, P;
  862. R = *pSrc++; /* red */
  863. G = *pSrc++; /* green */
  864. B = *pSrc++; /* blue */
  865. P = Ftable[((R & 0xF8) << 7) + ((G & 0xF8) << 2) + ((B & 0xF8) >> 3)];
  866. *pDst++ = P;
  867. total[P].number += 1;
  868. total[P].moment[0] += R;
  869. total[P].moment[1] += G;
  870. total[P].moment[2] += B;
  871. } while (--rowCount >= 0);
  872. } while (--nLinesM1 >= 0);
  873. for ( index = 0 ; index < nBoxes ; index++ ) {
  874. pPalette[ 0 + index] = (256.0*total[index].moment[0])/total[index].number;
  875. pPalette[256 + index] = (256.0*total[index].moment[1])/total[index].number;
  876. pPalette[512 + index] = (256.0*total[index].moment[2])/total[index].number;
  877. }
  878. free( Ftable );
  879. return IL_OK;
  880. }
  881. /* =========================== "MAINLINE" FUNCTION =============================== */
  882. /* ---------------------------- ilConvertRGBToPalette ----------------------- */
  883. /* Convert from source type (pDes->type) == RGB to Palette.
  884. pFormat points to the source format; on return, *pFormat is updated
  885. to the dst format. *pDes ->the src (pipe) des; on return *pDes is the new des.
  886. */
  887. IL_PRIVATE ilBool _ilConvertRGBToPalette (
  888. ilPipe pipe,
  889. ilPipeInfo *pInfo,
  890. ilImageDes *pDes,
  891. ilImageFormat *pFormat,
  892. int option,
  893. ilConvertToPaletteInfo *pData
  894. )
  895. {
  896. ilDitherPrivPtr pPriv;
  897. ilDstElementData dstData;
  898. ilSrcElementData srcData;
  899. ilError (*executeFunction)(), (*cleanupFunction)();
  900. ilPtr pTranslate;
  901. unsigned short *pPalette;
  902. long *pColorTable;
  903. ilBool diffusion, chooseColors;
  904. int i, shifts[3] = { 0, 0, 0 }, nColors = 0;
  905. const unsigned short *pMulTable[3] = { NULL, NULL, NULL }; /* dither other than 484 only: pMul? */
  906. static ilConvertToPaletteInfo defaultConvert =
  907. {IL_DIFFUSION, { 4, 8, 4 }, 8, IL_PALETTE, (ilObject)NULL};
  908. /* Init to null those things freed by "cleanup" if error. */
  909. pPalette = (unsigned short *)NULL;
  910. pColorTable = (long *)NULL;
  911. /* Get format = planar order, 8 bits / pixel, or error.
  912. Src image already guaranteed to be 256-level RGB image.
  913. */
  914. if ((pFormat->nBitsPerSample[0] != 8)
  915. || (pFormat->nBitsPerSample[1] != 8)
  916. || (pFormat->nBitsPerSample[2] != 8)
  917. || (pFormat->sampleOrder != IL_SAMPLE_PIXELS)) {
  918. if (!ilConvert (pipe, (ilImageDes *)NULL, IL_FORMAT_3BYTE_PIXEL, 0, NULL))
  919. return FALSE;
  920. }
  921. /* Validate option code; default pData if not present */
  922. if ((option != 0) && (option != IL_CONVERT_TO_PALETTE))
  923. return ilDeclarePipeInvalid (pipe, IL_ERROR_INVALID_OPTION);
  924. if (!pData)
  925. pData = &defaultConvert;
  926. /* Validate and choose pipe functions based on convert method. */
  927. switch (pData->method) {
  928. case IL_AREA_DITHER:
  929. if (pData->kernelSize != 8)
  930. return ilDeclarePipeInvalid (pipe, IL_ERROR_CONVERT_TO_PALETTE);
  931. if ((pData->levels[0] == 4)
  932. && (pData->levels[1] == 8)
  933. && (pData->levels[2] == 4))
  934. executeFunction = ilExecuteDitherRGBTo484;
  935. else {
  936. /* Not 484 dithering: each level must be 2, 4 or 8; product <= 256.
  937. Set pMulTable and shifts based on # of levels each component.
  938. */
  939. if ((pData->levels[0] * pData->levels[1] * pData->levels[2]) > 256)
  940. return ilDeclarePipeInvalid (pipe, IL_ERROR_CONVERT_TO_PALETTE);
  941. for (i = 0; i < 3; i++)
  942. switch ((unsigned short)pData->levels[i]) {
  943. case 2: shifts[i] = 7; pMulTable[i] = _ilMul2; break;
  944. case 4: shifts[i] = 6; pMulTable[i] = _ilMul4; break;
  945. case 8: shifts[i] = 5; pMulTable[i] = _ilMul8; break;
  946. default: return ilDeclarePipeInvalid (pipe,IL_ERROR_CONVERT_TO_PALETTE);
  947. }
  948. executeFunction = ilExecuteDitherRGB;
  949. }
  950. cleanupFunction = IL_NPF;
  951. diffusion = FALSE;
  952. chooseColors = FALSE;
  953. break;
  954. /* (Quick) diffusion: all powers of 2 levels (min = 2) supported; product of all
  955. levels <= 256, so 64 is max level for any one. Store shifts = 8 - # bits.
  956. */
  957. case IL_DIFFUSION:
  958. case IL_QUICK_DIFFUSION:
  959. for (i = 0; i < 3; i++)
  960. switch ((unsigned short)pData->levels[i]) {
  961. case 2: shifts[i] = 7; break;
  962. case 4: shifts[i] = 6; break;
  963. case 8: shifts[i] = 5; break;
  964. case 16: shifts[i] = 4; break;
  965. case 32: shifts[i] = 3; break;
  966. case 64: shifts[i] = 2; break;
  967. default: return ilDeclarePipeInvalid (pipe, IL_ERROR_CONVERT_TO_PALETTE);
  968. }
  969. if ((pData->levels[0] * pData->levels[1] * pData->levels[2]) > 256)
  970. return ilDeclarePipeInvalid (pipe, IL_ERROR_CONVERT_TO_PALETTE);
  971. cleanupFunction = ilCleanupDitherRGB;
  972. diffusion = TRUE;
  973. chooseColors = FALSE;
  974. if (pData->method == IL_DIFFUSION)
  975. if ((pData->levels[0]==4) && (pData->levels[1]==8) && (pData->levels[2]==4))
  976. executeFunction = ilExecuteDiffusion484;
  977. else executeFunction = ilExecuteDiffusionRGB;
  978. else executeFunction = ilExecuteQuickDiffusionRGB;
  979. break;
  980. /* Choose colors: use the "best" pData->levels[0] (1..255) colors and fit to them.
  981. mapImage, dstType and kernelSize are ignored. Need a single strip, so set
  982. srcData to request a single strip (height = image, constantStrip = TRUE).
  983. */
  984. case IL_CHOOSE_COLORS:
  985. nColors = pData->levels[0];
  986. if ((nColors < 1)
  987. || (nColors > 256)
  988. || pData->mapImage
  989. || (pData->dstType != IL_PALETTE))
  990. return ilDeclarePipeInvalid (pipe, IL_ERROR_CONVERT_TO_PALETTE);
  991. executeFunction = ilChooseColorsExecute;
  992. cleanupFunction = IL_NPF;
  993. diffusion = FALSE;
  994. chooseColors = TRUE;
  995. srcData.consumerImage = (ilObject)NULL;
  996. srcData.stripHeight = pInfo->height; /* need one strip = whole image */
  997. srcData.constantStrip = TRUE;
  998. srcData.minBufferHeight = 0;
  999. break;
  1000. default:
  1001. return ilDeclarePipeInvalid (pipe, IL_ERROR_CONVERT_TO_PALETTE);
  1002. }
  1003. /* If mapImage given, validate it and point to its pixels. If not given,
  1004. pTranslate becomes null and will point to "identity" mapImage below.
  1005. */
  1006. pTranslate = (ilPtr)NULL;
  1007. if (pData->mapImage && !chooseColors) {
  1008. ilImageInfo *pInfo;
  1009. if (!ilQueryClientImage (pData->mapImage, &pInfo, 0)
  1010. || (pInfo->width != 256) || (pInfo->height != 1)
  1011. || (pInfo->pDes->compression != IL_UNCOMPRESSED)
  1012. || (pInfo->pDes->nSamplesPerPixel != 1)
  1013. || (pInfo->pFormat->nBitsPerSample[0] != 8))
  1014. return ilDeclarePipeInvalid (pipe, IL_ERROR_MAP_IMAGE);
  1015. pTranslate = pInfo->plane[0].pPixels;
  1016. }
  1017. /* If diffusion: init table: indexed by a pixel packed as <R><G><B><P>, each
  1018. with number of levels "n?Levels" (must be a power of 2), * 4. The red, green,
  1019. blue and pixel values appear in that order; table is indexed by pixel*4.
  1020. "pixel" is the translated pixel, i.e. pTranslate[pixel].
  1021. Note that this table has same values as palette, except 0..255 and ordered
  1022. with r/g/b/pixel together, instead of 0..65535 and rgb spread apart.
  1023. */
  1024. if (diffusion) {
  1025. int i, index;
  1026. int red, green, blue;
  1027. int redLevel, greenLevel, blueLevel;
  1028. long *pColorTemp;
  1029. pColorTable = (long *)IL_MALLOC (sizeof (long) * 256);
  1030. if (!pColorTable) {
  1031. ilDeclarePipeInvalid (pipe, IL_ERROR_MALLOC);
  1032. goto cleanup;
  1033. }
  1034. pColorTemp = pColorTable;
  1035. for (index = 0, red = 0; red < pData->levels[0]; red++) {
  1036. redLevel = 255 * red / (pData->levels[0] - 1);
  1037. for (green = 0; green < pData->levels[1]; green++) {
  1038. greenLevel = 255 * green / (pData->levels[1] - 1);
  1039. for (blue = 0; blue < pData->levels[2]; blue++) {
  1040. blueLevel = 255 * blue / (pData->levels[2] - 1);
  1041. i = (blueLevel << 24) | (greenLevel << 16) | (redLevel << 8);
  1042. if (pTranslate)
  1043. i |= pTranslate[index];
  1044. else i |= index;
  1045. *pColorTemp++ = i;
  1046. index++;
  1047. }
  1048. }
  1049. }
  1050. }
  1051. /* alloc pPalette unless not palette dst; init with ramp if not choosing */
  1052. if ((pData->dstType == IL_PALETTE) || chooseColors) {
  1053. pPalette = (unsigned short *)IL_MALLOC_ZERO (3 * 256 * sizeof(unsigned short));
  1054. if (!pPalette) {
  1055. ilDeclarePipeInvalid (pipe, IL_ERROR_MALLOC);
  1056. goto cleanup;
  1057. }
  1058. if (!chooseColors) {
  1059. int red, green, blue;
  1060. int redLevel, greenLevel, blueLevel;
  1061. unsigned short *pPal;
  1062. pPal = pPalette;
  1063. for (red = 0; red < pData->levels[0]; red++) {
  1064. redLevel = 65535 * red / (pData->levels[0] - 1);
  1065. for (green = 0; green < pData->levels[1]; green++) {
  1066. greenLevel = 65535 * green / (pData->levels[1] - 1);
  1067. for (blue = 0; blue < pData->levels[2]; blue++) {
  1068. blueLevel = 65535 * blue / (pData->levels[2] - 1);
  1069. pPal [0] = redLevel;
  1070. pPal [256] = greenLevel;
  1071. pPal [512] = blueLevel;
  1072. pPal++;
  1073. }
  1074. }
  1075. }
  1076. }
  1077. } /* END create palette */
  1078. /* Add filter to write byte palette or private type image. If the type is
  1079. "palette", mark as being dithered unless colors choosen.
  1080. */
  1081. if (chooseColors)
  1082. *pDes = *IL_DES_PALETTE;
  1083. else {
  1084. *pDes = *IL_DES_GRAY;
  1085. pDes->type = pData->dstType;
  1086. if (pDes->type == IL_PALETTE) {
  1087. pDes->flags = IL_DITHERED_PALETTE;
  1088. pDes->typeInfo.palette.levels[0] = pData->levels[0];
  1089. pDes->typeInfo.palette.levels[1] = pData->levels[1];
  1090. pDes->typeInfo.palette.levels[2] = pData->levels[2];
  1091. }
  1092. }
  1093. *pFormat = *IL_FORMAT_BYTE;
  1094. dstData.producerObject = (ilObject)NULL;
  1095. dstData.pDes = pDes;
  1096. dstData.pFormat = pFormat;
  1097. dstData.width = pInfo->width;
  1098. dstData.height = pInfo->height;
  1099. dstData.stripHeight = 0;
  1100. dstData.constantStrip = FALSE;
  1101. dstData.pPalette = pPalette;
  1102. pPriv = (ilDitherPrivPtr)ilAddPipeElement (pipe, IL_FILTER, sizeof(ilDitherPrivRec), 0,
  1103. (chooseColors) ? &srcData : (ilSrcElementData *)NULL, &dstData,
  1104. ilInitDitherRGB, cleanupFunction, ilDestroyDitherRGB, executeFunction, NULL, 0);
  1105. if (!pPriv)
  1106. goto cleanup;
  1107. /* Init pPriv; point pTranslate to identity image if no mapImage given.
  1108. Store stuff from above into *pPriv even if not needed for this case.
  1109. */
  1110. pPriv->diffusion = diffusion;
  1111. if (pTranslate)
  1112. pPriv->pTranslate = pTranslate;
  1113. else if (!chooseColors) {
  1114. int i;
  1115. pPriv->pTranslate = pPriv->translate;
  1116. for (i = 0; i < 256; i++)
  1117. pPriv->translate[i] = i;
  1118. }
  1119. pPriv->pPalette = pPalette;
  1120. pPriv->pColorTable = pColorTable;
  1121. pPriv->shifts[0] = shifts[0];
  1122. pPriv->shifts[1] = shifts[1];
  1123. pPriv->shifts[2] = shifts[2];
  1124. pPriv->pMulTable[0] = pMulTable[0];
  1125. pPriv->pMulTable[1] = pMulTable[1];
  1126. pPriv->pMulTable[2] = pMulTable[2];
  1127. pPriv->nColors = nColors;
  1128. return TRUE;
  1129. /* goto point if error: free anything that has been malloc'd; return false */
  1130. cleanup:
  1131. if (pPalette) IL_FREE (pPalette);
  1132. if (pColorTable) IL_FREE (pColorTable);
  1133. return FALSE;
  1134. }