Source code of Windows XP (NT5)
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.

516 lines
14 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // DITH666.C - full color dither (to a palette with 6 red, 6 green 6 blue
  4. // levels)
  5. //
  6. // NOTE this file contains the 'C' code and DITH666A.ASM has the ASM code.
  7. //
  8. // This file does the following dithering
  9. //
  10. // 32bpp -> 8bpp
  11. // 24bpp -> 8bpp
  12. // 16bpp -> 8bpp
  13. //
  14. // 8bpp -> 4bpp N/I
  15. // 16bpp -> 4bpp N/I
  16. // 24bpp -> 4bpp N/I
  17. // 32bpp -> 4bpp N/I
  18. //
  19. //////////////////////////////////////////////////////////////////////////////
  20. #include <windows.h>
  21. #include <windowsx.h>
  22. #include "drawdibi.h"
  23. #include "dither.h"
  24. #if defined(WIN32) || defined(WANT_286) // 'C' code for Win32
  25. #define USE_C
  26. #endif
  27. #include "dith666.h"
  28. int giDitherTableUsage = 0;
  29. LPVOID glpDitherTable;
  30. static void Get666Colors(LPBITMAPINFOHEADER lpbi);
  31. //////////////////////////////////////////////////////////////////////////////
  32. //
  33. //
  34. //////////////////////////////////////////////////////////////////////////////
  35. void FAR PASCAL Dither16(LPBITMAPINFOHEADER,LPVOID,int,int,int,int,LPBITMAPINFOHEADER,LPVOID,int,int,LPVOID);
  36. void FAR PASCAL Dither24(LPBITMAPINFOHEADER,LPVOID,int,int,int,int,LPBITMAPINFOHEADER,LPVOID,int,int,LPVOID);
  37. void FAR PASCAL Dither32(LPBITMAPINFOHEADER,LPVOID,int,int,int,int,LPBITMAPINFOHEADER,LPVOID,int,int,LPVOID);
  38. //////////////////////////////////////////////////////////////////////////////
  39. //
  40. // DitherTableInit()
  41. //
  42. //////////////////////////////////////////////////////////////////////////////
  43. static LPVOID DitherTableInit()
  44. {
  45. #ifdef DEBUG
  46. DWORD time = timeGetTime();
  47. #endif
  48. #ifdef XDEBUG
  49. int X,Y;
  50. char aBuffer[100];
  51. char far *pBuffer = aBuffer;
  52. GetProfileString("DrawDib", "Matrix5", "", aBuffer, sizeof(aBuffer));
  53. if (aBuffer[0])
  54. {
  55. for(Y = 0;Y < 4;Y++)
  56. {
  57. for(X = 0;X < 4;X++)
  58. {
  59. while(!isdigit(*pBuffer))
  60. {
  61. pBuffer++;
  62. }
  63. aHalftone4x4_5[X][Y] = *pBuffer - '0';
  64. pBuffer++;
  65. }
  66. }
  67. }
  68. #endif
  69. if (aHalftone8[0][0][0][0] == (BYTE)-1)
  70. {
  71. int i,x,y;
  72. for (x=0; x<4; x++)
  73. for (y=0; y<4; y++)
  74. for (i=0; i<256; i++)
  75. aHalftone8[0][x][y][i] = (i/51 + (i%51 > aHalftone4x4[x][y]));
  76. for (x=0; x<4; x++)
  77. for (y=0; y<4; y++)
  78. for (i=0; i<256; i++)
  79. aHalftone8[1][x][y][i] = 6 * (i/51 + (i%51 > aHalftone4x4[x][y]));
  80. for (x=0; x<4; x++)
  81. for (y=0; y<4; y++)
  82. for (i=0; i<256; i++)
  83. aHalftone8[2][x][y][i] = 36 * (i/51 + (i%51 > aHalftone4x4[x][y]));
  84. }
  85. #ifdef USE_C
  86. if (aHalftone5[0][0][0][0] == (BYTE)-1)
  87. {
  88. int i,x,y,z,n;
  89. for (x=0; x<4; x++)
  90. for (y=0; y<4; y++)
  91. for (z=0; z<256; z++) {
  92. n = (z >> 2) & 0x1F;
  93. i = n > 0 ? n-1 : 0;
  94. aHalftone5[0][x][y][z] = (i/6 + (i%6 > aHalftone4x4_5[x][y]));
  95. }
  96. for (x=0; x<4; x++)
  97. for (y=0; y<4; y++)
  98. for (z=0; z<256; z++) {
  99. n = (z & 0x1F);
  100. i = n > 0 ? n-1 : 0;
  101. aHalftone5[1][x][y][z] = 6 * (i/6 + (i%6 > aHalftone4x4_5[x][y]));
  102. }
  103. for (x=0; x<4; x++)
  104. for (y=0; y<4; y++)
  105. for (z=0; z<256; z++) {
  106. n = z & 0x1F;
  107. i = n > 0 ? n-1 : 0;
  108. aHalftone5[2][x][y][z] = 36 * (i/6 + (i%6 > aHalftone4x4_5[x][y]));
  109. }
  110. }
  111. #endif
  112. DPF(("DitherTableInit() took %ldms", timeGetTime() - time));
  113. return NULL;
  114. }
  115. //////////////////////////////////////////////////////////////////////////////
  116. //
  117. // DitherInit()
  118. //
  119. //////////////////////////////////////////////////////////////////////////////
  120. LPVOID FAR PASCAL Dither8Init(LPBITMAPINFOHEADER lpbi, LPBITMAPINFOHEADER lpbiOut, DITHERPROC FAR *lpDitherProc, LPVOID lpDitherTable)
  121. {
  122. UINT x,y,i,r,g,b;
  123. BYTE FAR *pb;
  124. Get666Colors(lpbiOut);
  125. DitherTableInit();
  126. if (lpDitherTable == NULL)
  127. lpDitherTable = GlobalAllocPtr(GHND, 256*8*8);
  128. if (lpDitherTable == NULL)
  129. return (LPVOID)-1;
  130. pb = (LPBYTE)lpDitherTable;
  131. for (y=0; y<8; y++)
  132. {
  133. for (i=0; i<256; i++)
  134. {
  135. r = ((LPRGBQUAD)(lpbi+1))[i].rgbRed;
  136. g = ((LPRGBQUAD)(lpbi+1))[i].rgbGreen;
  137. b = ((LPRGBQUAD)(lpbi+1))[i].rgbBlue;
  138. for (x=0; x<8; x++)
  139. {
  140. *pb++ = DITH8(x,y,r,g,b);
  141. }
  142. }
  143. }
  144. *lpDitherProc = Dither8;
  145. return lpDitherTable;
  146. }
  147. //////////////////////////////////////////////////////////////////////////////
  148. //
  149. // DitherInit()
  150. //
  151. //////////////////////////////////////////////////////////////////////////////
  152. LPVOID FAR PASCAL Dither16Init(LPBITMAPINFOHEADER lpbi, LPBITMAPINFOHEADER lpbiOut, DITHERPROC FAR *lpDitherProc, LPVOID lpDitherTable)
  153. {
  154. Get666Colors(lpbiOut);
  155. *lpDitherProc = Dither16;
  156. DitherTableInit();
  157. #ifndef USE_C
  158. //
  159. // we dont need to re-init the dither table, unless it is not ours then
  160. // we should free it.
  161. //
  162. if (lpDitherTable && lpDitherTable != glpDitherTable)
  163. {
  164. DitherTerm(lpDitherTable);
  165. lpDitherTable = NULL;
  166. }
  167. //
  168. // we dont need to re-init table
  169. //
  170. if (lpDitherTable != NULL)
  171. return lpDitherTable;
  172. if (glpDitherTable)
  173. {
  174. giDitherTableUsage++;
  175. return glpDitherTable;
  176. }
  177. else
  178. {
  179. //
  180. // build a table that maps a RGB555 directly to a palette index
  181. // we actualy build 4 tables, we assume a 2x2 dither and build
  182. // a table for each position in the matrix.
  183. //
  184. UINT x,y,r,g,b;
  185. BYTE FAR *pb;
  186. #ifdef DEBUG
  187. DWORD time = timeGetTime();
  188. #endif
  189. lpDitherTable = GlobalAllocPtr(GMEM_MOVEABLE|GMEM_SHARE, 32768l*4);
  190. if (lpDitherTable == NULL)
  191. return (LPVOID)-1;
  192. glpDitherTable = lpDitherTable;
  193. giDitherTableUsage = 1;
  194. for (y=0; y<2; y++)
  195. {
  196. if (y == 0)
  197. pb = (BYTE FAR *)lpDitherTable;
  198. else
  199. pb = (BYTE FAR *)((BYTE _huge *)lpDitherTable + 65536);
  200. for (r=0; r<32; r++)
  201. for (g=0; g<32; g++)
  202. for (b=0; b<32; b++)
  203. for (x=0; x<2; x++)
  204. *pb++ = DITH31(x,y,r,g,b);
  205. }
  206. DPF(("Dither16Init() took %ldms", timeGetTime() - time));
  207. }
  208. #endif
  209. return lpDitherTable;
  210. }
  211. //////////////////////////////////////////////////////////////////////////////
  212. //
  213. // DitherTerm()
  214. //
  215. //////////////////////////////////////////////////////////////////////////////
  216. void FAR PASCAL Dither16Term(LPVOID lpDitherTable)
  217. {
  218. if (giDitherTableUsage == 0 || --giDitherTableUsage > 0)
  219. return;
  220. if (glpDitherTable)
  221. {
  222. GlobalFreePtr(glpDitherTable);
  223. glpDitherTable = NULL;
  224. }
  225. }
  226. //////////////////////////////////////////////////////////////////////////////
  227. //
  228. // Dither24Init()
  229. //
  230. //////////////////////////////////////////////////////////////////////////////
  231. LPVOID FAR PASCAL Dither24Init(LPBITMAPINFOHEADER lpbi, LPBITMAPINFOHEADER lpbiOut, DITHERPROC FAR *lpDitherProc, LPVOID lpDitherTable)
  232. {
  233. Get666Colors(lpbiOut);
  234. *lpDitherProc = Dither24;
  235. return DitherTableInit();
  236. }
  237. //////////////////////////////////////////////////////////////////////////////
  238. //
  239. // Dither24Term()
  240. //
  241. //////////////////////////////////////////////////////////////////////////////
  242. void FAR PASCAL Dither24Term(LPVOID lpDitherTable)
  243. {
  244. }
  245. //////////////////////////////////////////////////////////////////////////////
  246. //
  247. // Dither32Init()
  248. //
  249. //////////////////////////////////////////////////////////////////////////////
  250. LPVOID FAR PASCAL Dither32Init(LPBITMAPINFOHEADER lpbi, LPBITMAPINFOHEADER lpbiOut, DITHERPROC FAR *lpDitherProc, LPVOID lpDitherTable)
  251. {
  252. Get666Colors(lpbiOut);
  253. *lpDitherProc = Dither32;
  254. return DitherTableInit();
  255. }
  256. //////////////////////////////////////////////////////////////////////////////
  257. //
  258. // Dither32Term()
  259. //
  260. //////////////////////////////////////////////////////////////////////////////
  261. void FAR PASCAL Dither32Term(LPVOID lpDitherTable)
  262. {
  263. }
  264. //////////////////////////////////////////////////////////////////////////////
  265. //
  266. // GetDithColors() get the dither palette
  267. //
  268. //////////////////////////////////////////////////////////////////////////////
  269. static void Get666Colors(LPBITMAPINFOHEADER lpbi)
  270. {
  271. RGBQUAD FAR *prgb = (RGBQUAD FAR *)(((LPBYTE)lpbi) + (UINT)lpbi->biSize);
  272. int i;
  273. for (i=0; i<256; i++)
  274. {
  275. prgb[i].rgbRed = pal666[i][0];
  276. prgb[i].rgbGreen = pal666[i][1];
  277. prgb[i].rgbBlue = pal666[i][2];
  278. prgb[i].rgbReserved = 0;
  279. }
  280. lpbi->biClrUsed = 256;
  281. }
  282. #ifdef USE_C
  283. //////////////////////////////////////////////////////////////////////////////
  284. //
  285. // Dither24 - dither from 24 to 8 using the Table method in 'C' Code
  286. //
  287. //////////////////////////////////////////////////////////////////////////////
  288. void FAR PASCAL Dither24(
  289. LPBITMAPINFOHEADER biDst, // --> BITMAPINFO of the dest
  290. LPVOID lpDst, // --> to destination bits
  291. int DstX, // Destination origin - x coordinate
  292. int DstY, // Destination origin - y coordinate
  293. int DstXE, // x extent of the BLT
  294. int DstYE, // y extent of the BLT
  295. LPBITMAPINFOHEADER biSrc, // --> BITMAPINFO of the source
  296. LPVOID lpSrc, // --> to source bits
  297. int SrcX, // Source origin - x coordinate
  298. int SrcY, // Source origin - y coordinate
  299. LPVOID lpDitherTable) // dither table.
  300. {
  301. int x,y;
  302. BYTE r,g,b;
  303. UINT wWidthSrc;
  304. UINT wWidthDst;
  305. BYTE _huge *pbS;
  306. BYTE _huge *pbD;
  307. if (biDst->biBitCount != 8 || biSrc->biBitCount != 24)
  308. return;
  309. wWidthSrc = ((UINT)biSrc->biWidth*3+3)&~3;
  310. wWidthDst = ((UINT)biDst->biWidth+3)&~3;
  311. pbD = (BYTE _huge *)lpDst + DstX + (DWORD)(UINT)DstY * (DWORD)wWidthDst;
  312. pbS = (BYTE _huge *)lpSrc + SrcX*3 + (DWORD)(UINT)SrcY * (DWORD)wWidthSrc;
  313. wWidthSrc -= DstXE*3;
  314. wWidthDst -= DstXE;
  315. #define GET24() \
  316. b = *pbS++; \
  317. g = *pbS++; \
  318. r = *pbS++;
  319. for (y=0; y<DstYE; y++) {
  320. for (x=0; x<DstXE; x++) {
  321. GET24(); *pbD++ = DITH8(x,y,r,g,b);
  322. }
  323. pbS += wWidthSrc;
  324. pbD += wWidthDst;
  325. }
  326. }
  327. //////////////////////////////////////////////////////////////////////////////
  328. //
  329. // Dither32 - dither from 32 to 8 using the Table method in 'C' Code
  330. //
  331. //////////////////////////////////////////////////////////////////////////////
  332. void FAR PASCAL Dither32(
  333. LPBITMAPINFOHEADER biDst, // --> BITMAPINFO of the dest
  334. LPVOID lpDst, // --> to destination bits
  335. int DstX, // Destination origin - x coordinate
  336. int DstY, // Destination origin - y coordinate
  337. int DstXE, // x extent of the BLT
  338. int DstYE, // y extent of the BLT
  339. LPBITMAPINFOHEADER biSrc, // --> BITMAPINFO of the source
  340. LPVOID lpSrc, // --> to source bits
  341. int SrcX, // Source origin - x coordinate
  342. int SrcY, // Source origin - y coordinate
  343. LPVOID lpDitherTable) // dither table.
  344. {
  345. int x,y;
  346. BYTE r,g,b;
  347. UINT wWidthSrc;
  348. UINT wWidthDst;
  349. BYTE _huge *pbS;
  350. BYTE _huge *pbD;
  351. if (biDst->biBitCount != 8 || biSrc->biBitCount != 32)
  352. return;
  353. wWidthSrc = ((UINT)biSrc->biWidth*4+3)&~3;
  354. wWidthDst = ((UINT)biDst->biWidth+3)&~3;
  355. pbD = (BYTE _huge *)lpDst + DstX + (DWORD)(UINT)DstY * (DWORD)wWidthDst;
  356. pbS = (BYTE _huge *)lpSrc + SrcX*4 + (DWORD)(UINT)SrcY * (DWORD)wWidthSrc;
  357. wWidthSrc -= DstXE*4;
  358. wWidthDst -= DstXE;
  359. #define GET32() \
  360. b = *pbS++; \
  361. g = *pbS++; \
  362. r = *pbS++; \
  363. pbS++;
  364. for (y=0; y<DstYE; y++) {
  365. for (x=0; x<DstXE; x++)
  366. {
  367. GET32();
  368. *pbD++ = DITH8(x,y,r,g,b);
  369. }
  370. pbS += wWidthSrc;
  371. pbD += wWidthDst;
  372. }
  373. }
  374. //////////////////////////////////////////////////////////////////////////////
  375. //
  376. // Dither16 - dither from 16 to 8 using the Table method in 'C' Code
  377. //
  378. //////////////////////////////////////////////////////////////////////////////
  379. void FAR PASCAL Dither16(
  380. LPBITMAPINFOHEADER biDst, // --> BITMAPINFO of the dest
  381. LPVOID lpDst, // --> to destination bits
  382. int DstX, // Destination origin - x coordinate
  383. int DstY, // Destination origin - y coordinate
  384. int DstXE, // x extent of the BLT
  385. int DstYE, // y extent of the BLT
  386. LPBITMAPINFOHEADER biSrc, // --> BITMAPINFO of the source
  387. LPVOID lpSrc, // --> to source bits
  388. int SrcX, // Source origin - x coordinate
  389. int SrcY, // Source origin - y coordinate
  390. LPVOID lpDitherTable) // dither table.
  391. {
  392. int x,y;
  393. WORD w;
  394. UINT wWidthSrc;
  395. UINT wWidthDst;
  396. BYTE _huge *pbS;
  397. BYTE _huge *pbD;
  398. if (biDst->biBitCount != 8 || biSrc->biBitCount != 16)
  399. return;
  400. wWidthSrc = ((UINT)biSrc->biWidth*2+3)&~3;
  401. wWidthDst = ((UINT)biDst->biWidth+3)&~3;
  402. pbD = (BYTE _huge *)lpDst + DstX + (DWORD)(UINT)DstY * (DWORD)wWidthDst;
  403. pbS = (BYTE _huge *)lpSrc + SrcX*2 + (DWORD)(UINT)SrcY * (DWORD)wWidthSrc;
  404. wWidthSrc -= DstXE*2;
  405. wWidthDst -= DstXE;
  406. #define GET16() \
  407. w = *((WORD _huge *)pbS)++;
  408. for (y=0; y<DstYE; y++) {
  409. for (x=0; x<DstXE; x++)
  410. {
  411. GET16();
  412. *pbD++ = DITH5(x,y,w);
  413. }
  414. pbS += wWidthSrc;
  415. pbD += wWidthDst;
  416. }
  417. }
  418. #endif