Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

994 lines
29 KiB

  1. #include "stdafx.h"
  2. #include "dithers.h"
  3. #ifndef _DEBUG
  4. #define INLINE __inline
  5. #else
  6. #define INLINE
  7. #endif
  8. //-----------------------------------------------------------------------------
  9. // helpers
  10. //-----------------------------------------------------------------------------
  11. const BYTE g_abClamp[] = {
  12. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  13. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  14. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  15. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  16. 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
  17. 25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,
  18. 47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,
  19. 69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,
  20. 90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,
  21. 109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,
  22. 126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,
  23. 143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
  24. 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,
  25. 177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,
  26. 194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,
  27. 211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,
  28. 228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,
  29. 245,246,247,248,249,250,251,252,253,254,255,255,255,255,255,255,255,
  30. 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  31. 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  32. 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  33. 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  34. 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  35. 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  36. 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  37. 255,255,255
  38. };
  39. INLINE UINT Clamp8(int z)
  40. {
  41. #ifdef _DEBUG
  42. UINT t = (z & 0xff00) ? (0xff & ~(z >> 16)) : z;
  43. if (t != g_abClamp[z + 128])
  44. DebugBreak();
  45. #endif
  46. return g_abClamp[z + 128];
  47. }
  48. INLINE WORD rgb555(BYTE r, BYTE g, BYTE b)
  49. {
  50. return( WORD( ((((WORD)(r) << 5) | (WORD)(g)) << 5) | (WORD)(b) ) );
  51. }
  52. //-----------------------------------------------------------------------------
  53. // Halftoning stuff
  54. //-----------------------------------------------------------------------------
  55. //
  56. // This table is used to halftone from 8 to 5 bpp. Typically, 16 bit
  57. // halftoning code will map an 8 bit value to a 5 bit value, map it back to
  58. // 8 bits, compute some error, and use a halftone table to adjust the 5 bit
  59. // value for the error. This array is a concatenation of 8 different 8-to-5
  60. // tables that include the error factoring in their mapping. It is used with
  61. // the halftoning table below, which gives indices to each of the mapping
  62. // tables within the array. Given the correct table pointer for a pixel,
  63. // callers can perform a single lookup per color component in this table to get
  64. // a halftoned 5 bit component.
  65. //
  66. #pragma data_seg(".text", "CODE")
  67. BYTE aHT16Data[] =
  68. {
  69. 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
  70. 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
  71. 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
  72. 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6,
  73. 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8,
  74. 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
  75. 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12,
  76. 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14,
  77. 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
  78. 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18,
  79. 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20,
  80. 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
  81. 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24,
  82. 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
  83. 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28,
  84. 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 31,
  85. 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  86. 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3,
  87. 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5,
  88. 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7,
  89. 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9,
  90. 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 11,
  91. 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 13,
  92. 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 15,
  93. 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 17,
  94. 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19,
  95. 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 21,
  96. 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 23,
  97. 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 25,
  98. 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 27,
  99. 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29,
  100. 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 31,
  101. 31, 31, 31, 31, 31, 31
  102. };
  103. UINT aHT16Heads[4][4] =
  104. {
  105. 262, 256, 261, 0,
  106. 258, 260, 257, 259,
  107. 261, 0, 262, 256,
  108. 257, 259, 258, 260,
  109. };
  110. #pragma data_seg()
  111. INLINE UINT *
  112. Get555HalftoneRow(UINT y)
  113. {
  114. return aHT16Heads[y % 4];
  115. }
  116. INLINE BYTE *
  117. Get555HalftoneTable(UINT *row, UINT x)
  118. {
  119. return aHT16Data + row[x % 4];
  120. }
  121. //-----------------------------------------------------------------------------
  122. // Rounding stuff
  123. //-----------------------------------------------------------------------------
  124. //
  125. // round an 8bit value to a 5bit value with good distribution
  126. //
  127. #if 0 // not presently used
  128. #pragma data_seg(".text", "CODE")
  129. BYTE aRound8to5[] = {
  130. 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
  131. 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4,
  132. 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6,
  133. 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8,
  134. 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10,
  135. 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 12,
  136. 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13,
  137. 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
  138. 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17,
  139. 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19,
  140. 19, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21,
  141. 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23,
  142. 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25,
  143. 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27,
  144. 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29,
  145. 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31,
  146. };
  147. #pragma data_seg()
  148. #endif // not presently used
  149. //
  150. // complement of table above
  151. //
  152. #pragma data_seg(".text", "CODE")
  153. BYTE aRound5to8[] = {
  154. 0, 8, 16, 25, 33, 41, 49, 58, 66, 74, 82, 90, 99,107,115,123,
  155. 132,140,148,156,165,173,181,189,197,206,214,222,230,239,247,255,
  156. };
  157. #pragma data_seg()
  158. ///////////////////////////////////////////////////////////////////////////////
  159. //
  160. // Dithering stuff.
  161. //
  162. // This code implements error-diffusion to an arbitrary set of colors,
  163. // optionally with transparency. Since the output colors can be arbitrary,
  164. // the color picker for the dither is a 32k inverse-mapping table. 24bpp
  165. // values are whacked down to 16bpp (555) and used as indices into the table.
  166. // To compensate for posterization effects when converting 24bpp to 16bpp, an
  167. // ordered dither (16bpp halftone) is used to generate the 555 color.
  168. //
  169. ///////////////////////////////////////////////////////////////////////////////
  170. INLINE void SwapError(ERRBUF **a, ERRBUF **b)
  171. {
  172. ERRBUF *te;
  173. te = *a;
  174. *a = *b;
  175. *b = te;
  176. }
  177. INLINE void ZeroError(ERRBUF *err, size_t pels)
  178. {
  179. ZeroMemory(err - 1, ErrbufBytes(pels));
  180. }
  181. ///////////////////////////////////////////////////////////////////////////////
  182. //
  183. // Dith8to8() 8bpp to 8bpp dither.
  184. //
  185. // Computes the 24bpp source color by combining the source pixel's color table
  186. // entry with accumulated error for the pixel. Halftones this 24bpp value to a
  187. // 16bpp 555 color. Uses the 16bpp color as a lookup into an inverse mapping
  188. // table to pick the output color for the pixel. Uses the destination color
  189. // table entry to compute and accumulates error for neighboring pixels.
  190. //
  191. ///////////////////////////////////////////////////////////////////////////////
  192. INLINE void DithScan8to8(BYTE *dst, const BYTE *src, const RGBQUAD *colorsIN,
  193. const RGBQUAD *colorsOUT, const BYTE *map, ERRBUF *cur_err,
  194. ERRBUF *nxt_err, UINT x, UINT xl, UINT y)
  195. {
  196. UINT *row = Get555HalftoneRow(y);
  197. for (; x < xl; src++, x++)
  198. {
  199. register const RGBQUAD *pChosen;
  200. register BYTE *tbl;
  201. register int r;
  202. register int g;
  203. register int b;
  204. pChosen = colorsIN + *src;
  205. r = Clamp8((int)pChosen->rgbRed + (cur_err->r >> 4));
  206. g = Clamp8((int)pChosen->rgbGreen + (cur_err->g >> 4));
  207. b = Clamp8((int)pChosen->rgbBlue + (cur_err->b >> 4));
  208. cur_err++;
  209. tbl = Get555HalftoneTable(row, x);
  210. pChosen = colorsOUT + (*dst++ = map[rgb555(tbl[r], tbl[g], tbl[b])]);
  211. r -= (int)pChosen->rgbRed;
  212. (nxt_err+1)->r += r * 1;
  213. (nxt_err-1)->r += r * 3;
  214. (nxt_err )->r += r * 5;
  215. (cur_err )->r += r * 7;
  216. g -= (int)pChosen->rgbGreen;
  217. (nxt_err+1)->g += g * 1;
  218. (nxt_err-1)->g += g * 3;
  219. (nxt_err )->g += g * 5;
  220. (cur_err )->g += g * 7;
  221. b -= (int)pChosen->rgbBlue;
  222. (nxt_err+1)->b += b * 1;
  223. (nxt_err-1)->b += b * 3;
  224. (nxt_err )->b += b * 5;
  225. (cur_err )->b += b * 7;
  226. nxt_err++;
  227. }
  228. }
  229. void Dith8to8(BYTE *dst, const BYTE *src, int dst_next_scan, int src_next_scan,
  230. const RGBQUAD *colorsIN, const RGBQUAD *colorsOUT, const BYTE *map,
  231. ERRBUF *cur_err, ERRBUF *nxt_err, UINT x, UINT cx, UINT y, int cy)
  232. {
  233. int dy;
  234. cx += x;
  235. if (cy < 0)
  236. {
  237. dy = -1;
  238. cy *= -1;
  239. }
  240. else
  241. dy = 1;
  242. if (y & 1)
  243. SwapError(&cur_err, &nxt_err);
  244. while (cy)
  245. {
  246. DithScan8to8(dst, src, colorsIN, colorsOUT, map, cur_err, nxt_err,
  247. x, cx, y);
  248. ZeroError(cur_err, cx);
  249. SwapError(&cur_err, &nxt_err);
  250. *(BYTE **)&src += src_next_scan;
  251. *(BYTE **)&dst += dst_next_scan;
  252. y += dy;
  253. cy--;
  254. }
  255. }
  256. INLINE void ConvertScan8to8( BYTE* pbDest, const BYTE* pbSrc,
  257. const RGBQUAD* prgbColors, const BYTE* pbMap, UINT x, UINT xl, UINT y )
  258. {
  259. UINT* pRow = Get555HalftoneRow( y );
  260. BYTE* pbTable;
  261. BYTE r;
  262. BYTE g;
  263. BYTE b;
  264. for (; x < xl; pbSrc += 3, x++ )
  265. {
  266. r = prgbColors[*pbSrc].rgbRed;
  267. g = prgbColors[*pbSrc].rgbGreen;
  268. b = prgbColors[*pbSrc].rgbBlue;
  269. pbTable = Get555HalftoneTable( pRow, x );
  270. *pbDest = pbMap[rgb555( pbTable[r], pbTable[g], pbTable[b] )];
  271. }
  272. }
  273. void Convert8to8( BYTE* pbDest, const BYTE* pbSrc, int nDestPitch,
  274. int nSrcPitch, const RGBQUAD* prgbColors, const BYTE* pbMap, UINT x,
  275. UINT nWidth, UINT y, int nHeight )
  276. {
  277. int dy;
  278. UINT x2;
  279. x2 = x+nWidth;
  280. if( nHeight < 0 )
  281. {
  282. dy = -1;
  283. nHeight *= -1;
  284. }
  285. else
  286. {
  287. dy = 1;
  288. }
  289. while( nHeight )
  290. {
  291. ConvertScan8to8( pbDest, pbSrc, prgbColors, pbMap, x, x2, y );
  292. pbSrc += nSrcPitch;
  293. pbDest += nDestPitch;
  294. y += dy;
  295. nHeight--;
  296. }
  297. }
  298. INLINE void DithScanGray8to8( BYTE* pbDest, const BYTE* pbSrc,
  299. const RGBQUAD* prgbColors, const BYTE* pbMap, ERRBUF* pCurrentError,
  300. ERRBUF* pNextError, UINT x, UINT xl, UINT y )
  301. {
  302. BYTE bSrc;
  303. BYTE bDest;
  304. UINT* pRow = Get555HalftoneRow( y );
  305. for(; x < xl; pbSrc++, x++ )
  306. {
  307. const RGBQUAD* prgbChosen;
  308. BYTE* pbTable;
  309. int r;
  310. int g;
  311. int b;
  312. bSrc = *pbSrc;
  313. r = Clamp8( (int)bSrc + pCurrentError->r/16 );
  314. g= Clamp8( (int)bSrc + pCurrentError->g/16 );
  315. b = Clamp8( (int)bSrc + pCurrentError->b/16 );
  316. pCurrentError++;
  317. pbTable = Get555HalftoneTable( pRow, x );
  318. bDest = pbMap[rgb555( pbTable[r], pbTable[g], pbTable[b] )];
  319. prgbChosen = prgbColors+bDest;
  320. *pbDest = bDest;
  321. pbDest++;
  322. r -= (int)prgbChosen->rgbRed;
  323. (pNextError+1)->r += r * 1;
  324. (pNextError-1)->r += r * 3;
  325. (pNextError)->r += r * 5;
  326. (pCurrentError)->r += r * 7;
  327. g -= (int)prgbChosen->rgbGreen;
  328. (pNextError+1)->g += g * 1;
  329. (pNextError-1)->g += g * 3;
  330. (pNextError)->g += g * 5;
  331. (pCurrentError)->g += g * 7;
  332. b -= (int)prgbChosen->rgbBlue;
  333. (pNextError+1)->b += b * 1;
  334. (pNextError-1)->b += b * 3;
  335. (pNextError)->b += b * 5;
  336. (pCurrentError)->b += b * 7;
  337. pNextError++;
  338. }
  339. }
  340. void DithGray8to8( BYTE* pbDest, const BYTE* pbSrc, int nDestPitch,
  341. int nSrcPitch, const RGBQUAD* prgbColors, const BYTE* pbMap,
  342. ERRBUF* pCurrentError, ERRBUF* pNextError, UINT x, UINT cx, UINT y, int cy )
  343. {
  344. int dy;
  345. cx += x;
  346. if (cy < 0)
  347. {
  348. dy = -1;
  349. cy *= -1;
  350. }
  351. else
  352. {
  353. dy = 1;
  354. }
  355. if (y & 1)
  356. {
  357. SwapError( &pCurrentError, &pNextError );
  358. }
  359. while (cy)
  360. {
  361. DithScanGray8to8( pbDest, pbSrc, prgbColors, pbMap, pCurrentError,
  362. pNextError, x, cx, y );
  363. ZeroError( pCurrentError, cx );
  364. SwapError( &pCurrentError, &pNextError );
  365. *(BYTE **)&pbSrc += nSrcPitch;
  366. *(BYTE **)&pbDest += nDestPitch;
  367. y += dy;
  368. cy--;
  369. }
  370. }
  371. INLINE void ConvertScanGray8to8( BYTE* pbDest, const BYTE* pbSrc,
  372. const BYTE* pbMap, UINT x, UINT xl, UINT y )
  373. {
  374. UINT* pRow = Get555HalftoneRow( y );
  375. BYTE* pbTable;
  376. BYTE g;
  377. for (; x < xl; pbSrc++, x++ )
  378. {
  379. g = *pbSrc;
  380. pbTable = Get555HalftoneTable( pRow, x );
  381. *pbDest = pbMap[rgb555( pbTable[g], pbTable[g], pbTable[g] )];
  382. }
  383. }
  384. void ConvertGray8to8( BYTE* pbDest, const BYTE* pbSrc, int nDestPitch,
  385. int nSrcPitch, const BYTE* pbMap, UINT x, UINT nWidth, UINT y, int nHeight )
  386. {
  387. int dy;
  388. UINT x2;
  389. x2 = x+nWidth;
  390. if( nHeight < 0 )
  391. {
  392. dy = -1;
  393. nHeight *= -1;
  394. }
  395. else
  396. {
  397. dy = 1;
  398. }
  399. while( nHeight )
  400. {
  401. ConvertScanGray8to8( pbDest, pbSrc, pbMap, x, x2, y );
  402. pbSrc += nSrcPitch;
  403. pbDest += nDestPitch;
  404. y += dy;
  405. nHeight--;
  406. }
  407. }
  408. ///////////////////////////////////////////////////////////////////////////////
  409. //
  410. // Dith8to8t() 8bpp to 8bpp dither with transparency.
  411. //
  412. // If the source pixel is the given source transparency color, this routine
  413. // picks the destination transparency color for output and zero error is
  414. // accumulated to the pixel's neighbors.
  415. // Otherwise, this routine functions identically to Dith8to8.
  416. //
  417. ///////////////////////////////////////////////////////////////////////////////
  418. INLINE void DithScan8to8t(BYTE *dst, const BYTE *src,
  419. const RGBQUAD *colorsIN, const RGBQUAD *colorsOUT, const BYTE *map,
  420. ERRBUF *cur_err, ERRBUF *nxt_err, UINT x, UINT xl, UINT y,
  421. BYTE indexTxpOUT, BYTE indexTxpIN)
  422. {
  423. UINT *row = Get555HalftoneRow(y);
  424. for (; x < xl; src++, x++)
  425. {
  426. register const RGBQUAD *pChosen;
  427. register BYTE *tbl;
  428. register BYTE index;
  429. register int r;
  430. register int g;
  431. register int b;
  432. index = *src;
  433. if (index == indexTxpIN)
  434. {
  435. *dst++ = indexTxpOUT;
  436. cur_err++;
  437. nxt_err++;
  438. continue;
  439. }
  440. pChosen = colorsIN + index;
  441. r = Clamp8((int)pChosen->rgbRed + (cur_err->r >> 4));
  442. g = Clamp8((int)pChosen->rgbGreen + (cur_err->g >> 4));
  443. b = Clamp8((int)pChosen->rgbBlue + (cur_err->b >> 4));
  444. cur_err++;
  445. tbl = Get555HalftoneTable(row, x);
  446. pChosen = colorsOUT + (*dst++ = map[rgb555(tbl[r], tbl[g], tbl[b])]);
  447. r -= (int)pChosen->rgbRed;
  448. (nxt_err+1)->r += r * 1;
  449. (nxt_err-1)->r += r * 3;
  450. (nxt_err )->r += r * 5;
  451. (cur_err )->r += r * 7;
  452. g -= (int)pChosen->rgbGreen;
  453. (nxt_err+1)->g += g * 1;
  454. (nxt_err-1)->g += g * 3;
  455. (nxt_err )->g += g * 5;
  456. (cur_err )->g += g * 7;
  457. b -= (int)pChosen->rgbBlue;
  458. (nxt_err+1)->b += b * 1;
  459. (nxt_err-1)->b += b * 3;
  460. (nxt_err )->b += b * 5;
  461. (cur_err )->b += b * 7;
  462. nxt_err++;
  463. }
  464. }
  465. void Dith8to8t(BYTE *dst, const BYTE *src, int dst_next_scan,
  466. int src_next_scan, const RGBQUAD *colorsIN, const RGBQUAD *colorsOUT,
  467. const BYTE *map, ERRBUF *cur_err, ERRBUF *nxt_err, UINT x, UINT cx, UINT y,
  468. int cy, BYTE indexTxpOUT, BYTE indexTxpIN)
  469. {
  470. int dy;
  471. cx += x;
  472. if (cy < 0)
  473. {
  474. dy = -1;
  475. cy *= -1;
  476. }
  477. else
  478. dy = 1;
  479. if (y & 1)
  480. SwapError(&cur_err, &nxt_err);
  481. while (cy)
  482. {
  483. DithScan8to8t(dst, src, colorsIN, colorsOUT, map, cur_err, nxt_err,
  484. x, cx, y, indexTxpOUT, indexTxpIN);
  485. ZeroError(cur_err, cx);
  486. SwapError(&cur_err, &nxt_err);
  487. *(BYTE **)&src += src_next_scan;
  488. *(BYTE **)&dst += dst_next_scan;
  489. y += dy;
  490. cy--;
  491. }
  492. }
  493. ///////////////////////////////////////////////////////////////////////////////
  494. //
  495. // Dith8to16() 8bpp to 16bpp dither.
  496. //
  497. // Computes the 24bpp source color by combining the source pixel's color table
  498. // entry with accumulated error for the pixel. Halftones this 24bpp value to a
  499. // 16bpp 555 color. Remaps this color to 24bpp to compute and accumulates
  500. // error for neighboring pixels.
  501. //
  502. ///////////////////////////////////////////////////////////////////////////////
  503. INLINE void DithScan8to16(WORD *dst, const BYTE *src, const RGBQUAD *colors,
  504. ERRBUF *cur_err, ERRBUF *nxt_err, UINT x, UINT xl, UINT y)
  505. {
  506. UINT *row = Get555HalftoneRow(y);
  507. for (; x < xl; src++, x++)
  508. {
  509. register const RGBQUAD *pChosen;
  510. register WORD wColor;
  511. register BYTE *tbl;
  512. register int r;
  513. register int g;
  514. register int b;
  515. pChosen = colors + *src;
  516. r = Clamp8((int)pChosen->rgbRed + cur_err->r / 16);
  517. g = Clamp8((int)pChosen->rgbGreen + cur_err->g / 16);
  518. b = Clamp8((int)pChosen->rgbBlue + cur_err->b / 16);
  519. cur_err++;
  520. tbl = Get555HalftoneTable(row, x);
  521. wColor = (*dst++ = rgb555(tbl[r], tbl[g], tbl[b]));
  522. b -= (int)aRound5to8[wColor & 0x1f];
  523. (nxt_err+1)->b += b * 1;
  524. (nxt_err-1)->b += b * 3;
  525. (nxt_err )->b += b * 5;
  526. (cur_err )->b += b * 7;
  527. g -= (int)aRound5to8[(wColor >> 5) & 0x1f];
  528. (nxt_err+1)->g += g * 1;
  529. (nxt_err-1)->g += g * 3;
  530. (nxt_err )->g += g * 5;
  531. (cur_err )->g += g * 7;
  532. r -= (int)aRound5to8[(wColor >> 10) & 0x1f];
  533. (nxt_err+1)->r += r * 1;
  534. (nxt_err-1)->r += r * 3;
  535. (nxt_err )->r += r * 5;
  536. (cur_err )->r += r * 7;
  537. nxt_err++;
  538. }
  539. }
  540. void Dith8to16(WORD *dst, const BYTE *src, int dst_next_scan,
  541. int src_next_scan, const RGBQUAD *colors, ERRBUF *cur_err, ERRBUF *nxt_err,
  542. UINT x, UINT cx, UINT y, int cy)
  543. {
  544. int dy;
  545. cx += x;
  546. if (cy < 0)
  547. {
  548. dy = -1;
  549. cy *= -1;
  550. }
  551. else
  552. dy = 1;
  553. if (y & 1)
  554. SwapError(&cur_err, &nxt_err);
  555. while (cy)
  556. {
  557. DithScan8to16(dst, src, colors, cur_err, nxt_err, x, cx, y);
  558. ZeroError(cur_err, cx);
  559. SwapError(&cur_err, &nxt_err);
  560. *(BYTE **)&src += src_next_scan;
  561. *(BYTE **)&dst += dst_next_scan;
  562. y += dy;
  563. cy--;
  564. }
  565. }
  566. ///////////////////////////////////////////////////////////////////////////////
  567. //
  568. // Dith8to16t() 8bpp to 16bpp dither with transparency.
  569. //
  570. // If the source pixel is the given source transparency color, this routine
  571. // picks the destination transparency color for output and zero error is
  572. // accumulated to the pixel's neighbors.
  573. // Otherwise, this routine functions identically to Dith8to16.
  574. //
  575. ///////////////////////////////////////////////////////////////////////////////
  576. INLINE void DithScan8to16t(WORD *dst, const BYTE *src, const RGBQUAD *colors,
  577. ERRBUF *cur_err, ERRBUF *nxt_err, UINT x, UINT xl, UINT y,
  578. WORD wColorTxpOUT, BYTE indexTxpIN)
  579. {
  580. UINT *row = Get555HalftoneRow(y);
  581. for (; x < xl; src ++, x++)
  582. {
  583. register const RGBQUAD *pChosen;
  584. register WORD wColor;
  585. register BYTE *tbl;
  586. register BYTE index;
  587. register int r;
  588. register int g;
  589. register int b;
  590. index = *src;
  591. if (index == indexTxpIN)
  592. {
  593. *dst++ = wColorTxpOUT;
  594. cur_err++;
  595. nxt_err++;
  596. continue;
  597. }
  598. pChosen = colors + index;
  599. r = Clamp8((int)pChosen->rgbRed + cur_err->r / 16);
  600. g = Clamp8((int)pChosen->rgbGreen + cur_err->g / 16);
  601. b = Clamp8((int)pChosen->rgbBlue + cur_err->b / 16);
  602. cur_err++;
  603. tbl = Get555HalftoneTable(row, x);
  604. wColor = (*dst++ = rgb555(tbl[r], tbl[g], tbl[b]));
  605. b -= (int)aRound5to8[wColor & 0x1f];
  606. (nxt_err+1)->b += b * 1;
  607. (nxt_err-1)->b += b * 3;
  608. (nxt_err )->b += b * 5;
  609. (cur_err )->b += b * 7;
  610. g -= (int)aRound5to8[(wColor >> 5) & 0x1f];
  611. (nxt_err+1)->g += g * 1;
  612. (nxt_err-1)->g += g * 3;
  613. (nxt_err )->g += g * 5;
  614. (cur_err )->g += g * 7;
  615. r -= (int)aRound5to8[(wColor >> 10) & 0x1f];
  616. (nxt_err+1)->r += r * 1;
  617. (nxt_err-1)->r += r * 3;
  618. (nxt_err )->r += r * 5;
  619. (cur_err )->r += r * 7;
  620. nxt_err++;
  621. }
  622. }
  623. void Dith8to16t(WORD *dst, const BYTE *src, int dst_next_scan,
  624. int src_next_scan, const RGBQUAD *colors, ERRBUF *cur_err, ERRBUF *nxt_err,
  625. UINT x, UINT cx, UINT y, int cy, WORD wColorTxpOUT, BYTE indexTxpIN)
  626. {
  627. int dy;
  628. cx += x;
  629. if (cy < 0)
  630. {
  631. dy = -1;
  632. cy *= -1;
  633. }
  634. else
  635. dy = 1;
  636. if (y & 1)
  637. SwapError(&cur_err, &nxt_err);
  638. while (cy)
  639. {
  640. DithScan8to16t(dst, src, colors, cur_err, nxt_err, x, cx, y,
  641. wColorTxpOUT, indexTxpIN);
  642. ZeroError(cur_err, cx);
  643. SwapError(&cur_err, &nxt_err);
  644. *(BYTE **)&src += src_next_scan;
  645. *(BYTE **)&dst += dst_next_scan;
  646. y += dy;
  647. cy--;
  648. }
  649. }
  650. ///////////////////////////////////////////////////////////////////////////////
  651. //
  652. // Dith24to8() 24bpp to 8bpp dither.
  653. //
  654. // Computes the 24bpp source color by combining the source pixel's color with
  655. // accumulated error for the pixel. Halftones this 24bpp value to a 16bpp 555
  656. // color. Uses the 16bpp color as a lookup into an inverse mapping table to
  657. // pick the output color for the pixel. Uses the destination color table entry
  658. // to compute and accumulates error for neighboring pixels.
  659. //
  660. ///////////////////////////////////////////////////////////////////////////////
  661. INLINE void DithScan24to8(BYTE *dst, const BYTE *src, const RGBQUAD *colors,
  662. const BYTE *map, ERRBUF *cur_err, ERRBUF *nxt_err, UINT x, UINT xl, UINT y)
  663. {
  664. UINT *row = Get555HalftoneRow(y);
  665. for (; x < xl; src += 3, x++)
  666. {
  667. register const RGBQUAD *pChosen;
  668. register BYTE *tbl;
  669. register int r;
  670. register int g;
  671. register int b;
  672. r = Clamp8((int)src[2] + cur_err->r / 16);
  673. g = Clamp8((int)src[1] + cur_err->g / 16);
  674. b = Clamp8((int)src[0] + cur_err->b / 16);
  675. cur_err++;
  676. tbl = Get555HalftoneTable(row, x);
  677. pChosen = colors + (*dst++ = map[rgb555(tbl[r], tbl[g], tbl[b])]);
  678. r -= (int)pChosen->rgbRed;
  679. (nxt_err+1)->r += r * 1;
  680. (nxt_err-1)->r += r * 3;
  681. (nxt_err )->r += r * 5;
  682. (cur_err )->r += r * 7;
  683. g -= (int)pChosen->rgbGreen;
  684. (nxt_err+1)->g += g * 1;
  685. (nxt_err-1)->g += g * 3;
  686. (nxt_err )->g += g * 5;
  687. (cur_err )->g += g * 7;
  688. b -= (int)pChosen->rgbBlue;
  689. (nxt_err+1)->b += b * 1;
  690. (nxt_err-1)->b += b * 3;
  691. (nxt_err )->b += b * 5;
  692. (cur_err )->b += b * 7;
  693. nxt_err++;
  694. }
  695. }
  696. void Dith24to8(BYTE *dst, const BYTE *src, int dst_next_scan,
  697. int src_next_scan, const RGBQUAD *colors, const BYTE *map, ERRBUF *cur_err,
  698. ERRBUF *nxt_err, UINT x, UINT cx, UINT y, int cy)
  699. {
  700. int dy;
  701. cx += x;
  702. if (cy < 0)
  703. {
  704. dy = -1;
  705. cy *= -1;
  706. }
  707. else
  708. dy = 1;
  709. if (y & 1)
  710. SwapError(&cur_err, &nxt_err);
  711. while (cy)
  712. {
  713. DithScan24to8(dst, src, colors, map, cur_err, nxt_err, x, cx, y);
  714. ZeroError(cur_err, cx);
  715. SwapError(&cur_err, &nxt_err);
  716. *(BYTE **)&src += src_next_scan;
  717. *(BYTE **)&dst += dst_next_scan;
  718. y += dy;
  719. cy--;
  720. }
  721. }
  722. INLINE void ConvertScan24to8( BYTE* pbDest, const BYTE* pbSrc,
  723. const BYTE* pbMap, UINT x, UINT xl, UINT y )
  724. {
  725. UINT* pRow;
  726. BYTE* pbTable;
  727. BYTE r;
  728. BYTE g;
  729. BYTE b;
  730. pRow = Get555HalftoneRow( y );
  731. for (; x < xl; pbSrc += 3, x++ )
  732. {
  733. r = pbSrc[2];
  734. g = pbSrc[1];
  735. b = pbSrc[0];
  736. pbTable = Get555HalftoneTable( pRow, x );
  737. *pbDest = pbMap[rgb555( pbTable[r], pbTable[g], pbTable[b] )];
  738. }
  739. }
  740. void Convert24to8( BYTE* pbDest, const BYTE* pbSrc, int nDestPitch,
  741. int nSrcPitch, const BYTE* pbMap, UINT x, UINT nWidth, UINT y, int nHeight )
  742. {
  743. int dy;
  744. UINT x2;
  745. x2 = x+nWidth;
  746. if( nHeight < 0 )
  747. {
  748. dy = -1;
  749. nHeight *= -1;
  750. }
  751. else
  752. {
  753. dy = 1;
  754. }
  755. while( nHeight )
  756. {
  757. ConvertScan24to8( pbDest, pbSrc, pbMap, x, x2, y );
  758. pbSrc += nSrcPitch;
  759. pbDest += nDestPitch;
  760. y += dy;
  761. nHeight--;
  762. }
  763. }
  764. ///////////////////////////////////////////////////////////////////////////////
  765. //
  766. // Dith24to16() 24bpp to 16bpp dither.
  767. //
  768. // Computes the 24bpp source color by combining the source pixel's color with
  769. // accumulated error for the pixel. Halftones this 24bpp value to a 16bpp 555
  770. // color. Remaps this color to 24bpp to compute and accumulates error for
  771. // neighboring pixels.
  772. //
  773. ///////////////////////////////////////////////////////////////////////////////
  774. INLINE void DithScan24to16(WORD *dst, const BYTE *src, ERRBUF *cur_err,
  775. ERRBUF *nxt_err, UINT x, UINT xl, UINT y)
  776. {
  777. UINT *row = Get555HalftoneRow(y);
  778. for (; x < xl; src += 3, x++)
  779. {
  780. register WORD wColor;
  781. register BYTE *tbl;
  782. register int r;
  783. register int g;
  784. register int b;
  785. r = Clamp8((int)src[2] + cur_err->r / 16);
  786. g = Clamp8((int)src[1] + cur_err->g / 16);
  787. b = Clamp8((int)src[0] + cur_err->b / 16);
  788. cur_err++;
  789. tbl = Get555HalftoneTable(row, x);
  790. wColor = (*dst++ = rgb555(tbl[r], tbl[g], tbl[b]));
  791. b -= (int)aRound5to8[wColor & 0x1f];
  792. (nxt_err+1)->b += b * 1;
  793. (nxt_err-1)->b += b * 3;
  794. (nxt_err )->b += b * 5;
  795. (cur_err )->b += b * 7;
  796. g -= (int)aRound5to8[(wColor >> 5) & 0x1f];
  797. (nxt_err+1)->g += g * 1;
  798. (nxt_err-1)->g += g * 3;
  799. (nxt_err )->g += g * 5;
  800. (cur_err )->g += g * 7;
  801. r -= (int)aRound5to8[(wColor >> 10) & 0x1f];
  802. (nxt_err+1)->r += r * 1;
  803. (nxt_err-1)->r += r * 3;
  804. (nxt_err )->r += r * 5;
  805. (cur_err )->r += r * 7;
  806. nxt_err++;
  807. }
  808. }
  809. void Dith24to16(WORD *dst, const BYTE *src, int dst_next_scan,
  810. int src_next_scan, ERRBUF *cur_err, ERRBUF *nxt_err, UINT x, UINT cx,
  811. UINT y, int cy)
  812. {
  813. int dy;
  814. cx += x;
  815. if (cy < 0)
  816. {
  817. dy = -1;
  818. cy *= -1;
  819. }
  820. else
  821. dy = 1;
  822. if (y & 1)
  823. SwapError(&cur_err, &nxt_err);
  824. while (cy)
  825. {
  826. DithScan24to16(dst, src, cur_err, nxt_err, x, cx, y);
  827. ZeroError(cur_err, cx);
  828. SwapError(&cur_err, &nxt_err);
  829. *(BYTE **)&src += src_next_scan;
  830. *(BYTE **)&dst += dst_next_scan;
  831. y += dy;
  832. cy--;
  833. }
  834. }
  835. ///////////////////////////////////////////////////////////////////////////////