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.

356 lines
10 KiB

  1. #include <windows.h>
  2. #include <windowsx.h>
  3. #include "drawdibi.h"
  4. #include "dither.h"
  5. //#define GRAY_SCALE
  6. extern BOOL gf286;
  7. extern UINT gwRasterCaps;
  8. void FAR PASCAL Map16to24(LPBITMAPINFOHEADER,LPVOID,int,int,int,int,LPBITMAPINFOHEADER,LPVOID,int,int,LPVOID);
  9. extern LPVOID glpDitherTable;
  10. //////////////////////////////////////////////////////////////////////////////
  11. //
  12. // DitherInit()
  13. //
  14. //////////////////////////////////////////////////////////////////////////////
  15. LPVOID VFWAPI
  16. DitherInit(LPBITMAPINFOHEADER lpbiIn,
  17. LPBITMAPINFOHEADER lpbiOut,
  18. DITHERPROC FAR * lpDitherProc,
  19. LPVOID lpDitherTable)
  20. {
  21. switch ((int)lpbiOut->biBitCount)
  22. {
  23. case 8:
  24. if ((int)lpbiIn->biBitCount == 8 && (gwRasterCaps & RC_PALETTE))
  25. return Dither8Init(lpbiIn, lpbiOut, lpDitherProc, lpDitherTable);
  26. if ((int)lpbiIn->biBitCount == 8 && !(gwRasterCaps & RC_PALETTE))
  27. return DitherDeviceInit(lpbiIn, lpbiOut, lpDitherProc, lpDitherTable);
  28. if ((int)lpbiIn->biBitCount == 16)
  29. return Dither16Init(lpbiIn, lpbiOut, lpDitherProc, lpDitherTable);
  30. if ((int)lpbiIn->biBitCount == 24)
  31. return Dither24Init(lpbiIn, lpbiOut, lpDitherProc, lpDitherTable);
  32. if ((int)lpbiIn->biBitCount == 32)
  33. return Dither32Init(lpbiIn, lpbiOut, lpDitherProc, lpDitherTable);
  34. return (LPVOID)-1;
  35. case 24:
  36. #ifndef _WIN32
  37. if (!gf286)
  38. #endif
  39. {
  40. if (lpbiIn->biBitCount == 16) {
  41. *lpDitherProc = Map16to24;
  42. return NULL;
  43. } else if (lpbiIn->biBitCount == 32) {
  44. *lpDitherProc = Map32to24;
  45. return NULL;
  46. }
  47. }
  48. return (LPVOID)-1;
  49. default:
  50. return (LPVOID)-1;
  51. }
  52. }
  53. //////////////////////////////////////////////////////////////////////////////
  54. //
  55. // DitherTerm()
  56. //
  57. //////////////////////////////////////////////////////////////////////////////
  58. void VFWAPI
  59. DitherTerm(LPVOID lpDitherTable)
  60. {
  61. if (lpDitherTable == glpDitherTable)
  62. Dither16Term(lpDitherTable);
  63. else
  64. Dither8Term(lpDitherTable);
  65. }
  66. //////////////////////////////////////////////////////////////////////////////
  67. //
  68. // DitherDeviceInit() - dither to the colors of the display driver
  69. //
  70. //////////////////////////////////////////////////////////////////////////////
  71. LPVOID FAR PASCAL DitherDeviceInit(LPBITMAPINFOHEADER lpbi, LPBITMAPINFOHEADER lpbiOut, DITHERPROC FAR *lpDitherProc, LPVOID lpDitherTable)
  72. {
  73. HBRUSH hbr;
  74. HDC hdcMem;
  75. HDC hdc;
  76. HBITMAP hbm;
  77. HBITMAP hbmT;
  78. int i;
  79. int nColors;
  80. LPRGBQUAD prgb;
  81. BITMAPINFOHEADER biSave = *lpbiOut;
  82. //
  83. // we dont need to re-init the dither table, unless it is not ours then
  84. // we should free it.
  85. //
  86. if (lpDitherTable == glpDitherTable)
  87. {
  88. DitherTerm(lpDitherTable);
  89. lpDitherTable = NULL;
  90. }
  91. if (lpDitherTable == NULL)
  92. {
  93. lpDitherTable = GlobalAllocPtr(GHND, 256*8*8);
  94. }
  95. if (lpDitherTable == NULL)
  96. return (LPVOID)-1;
  97. hdc = GetDC(NULL);
  98. hdcMem = CreateCompatibleDC(hdc);
  99. hbm = CreateCompatibleBitmap(hdc, 256*8, 8);
  100. hbmT = SelectObject(hdcMem, hbm);
  101. if ((nColors = (int)lpbi->biClrUsed) == 0)
  102. nColors = 1 << (int)lpbi->biBitCount;
  103. prgb = (LPRGBQUAD)(lpbi+1);
  104. for (i=0; i<nColors; i++)
  105. {
  106. hbr = CreateSolidBrush(RGB(prgb[i].rgbRed,prgb[i].rgbGreen,prgb[i].rgbBlue));
  107. hbr = SelectObject(hdcMem, hbr);
  108. PatBlt(hdcMem, i*8, 0, 8, 8, PATCOPY);
  109. hbr = SelectObject(hdcMem, hbr);
  110. DeleteObject(hbr);
  111. }
  112. #ifdef XDEBUG
  113. for (i=0; i<16; i++)
  114. BitBlt(hdc,0,i*8,16*8,8,hdcMem,i*(16*8),0,SRCCOPY);
  115. #endif
  116. SelectObject(hdcMem, hbmT);
  117. DeleteDC(hdcMem);
  118. lpbiOut->biSize = sizeof(BITMAPINFOHEADER);
  119. lpbiOut->biPlanes = 1;
  120. lpbiOut->biBitCount = 8;
  121. lpbiOut->biWidth = 256*8;
  122. lpbiOut->biHeight = 8;
  123. lpbiOut->biCompression = BI_RGB;
  124. lpbiOut->biSizeImage = 256*8*8;
  125. lpbiOut->biXPelsPerMeter = 0;
  126. lpbiOut->biYPelsPerMeter = 0;
  127. lpbiOut->biClrUsed = 0;
  128. lpbiOut->biClrImportant = 0;
  129. GetDIBits(hdc, hbm, 0, 8, lpDitherTable, (LPBITMAPINFO)lpbiOut, DIB_RGB_COLORS);
  130. i = (int)lpbiOut->biClrUsed;
  131. *lpbiOut = biSave;
  132. lpbiOut->biClrUsed = i;
  133. DeleteObject(hbm);
  134. ReleaseDC(NULL, hdc);
  135. *lpDitherProc = Dither8;
  136. return (LPVOID)lpDitherTable;
  137. }
  138. //////////////////////////////////////////////////////////////////////////////
  139. //
  140. // DitherTerm()
  141. //
  142. //////////////////////////////////////////////////////////////////////////////
  143. void FAR PASCAL Dither8Term(LPVOID lpDitherTable)
  144. {
  145. if (lpDitherTable)
  146. GlobalFreePtr(lpDitherTable);
  147. }
  148. #ifdef _WIN32
  149. //
  150. // call this to actually do the dither.
  151. //
  152. void FAR PASCAL Dither8(
  153. LPBITMAPINFOHEADER biDst, // --> BITMAPINFO of the dest
  154. LPVOID lpDst, // --> to destination bits
  155. int DstX, // Destination origin - x coordinate
  156. int DstY, // Destination origin - y coordinate
  157. int DstXE, // x extent of the BLT
  158. int DstYE, // y extent of the BLT
  159. LPBITMAPINFOHEADER biSrc, // --> BITMAPINFO of the source
  160. LPVOID lpSrc, // --> to source bits
  161. int SrcX, // Source origin - x coordinate
  162. int SrcY, // Source origin - y coordinate
  163. LPVOID lpDitherTable) // dither table.
  164. {
  165. int x,y;
  166. UINT wWidthSrc;
  167. UINT wWidthDst;
  168. BYTE _huge *pbS;
  169. BYTE _huge *pbD;
  170. DWORD dw;
  171. if (biDst->biBitCount != 8 || biSrc->biBitCount != 8)
  172. return;
  173. // tomor -- A little help! seems initialization is not done yet.
  174. if(!lpDitherTable)
  175. return;
  176. wWidthSrc = ((UINT)biSrc->biWidth+3)&~3;
  177. wWidthDst = ((UINT)biDst->biWidth+3)&~3;
  178. pbD = (BYTE _huge *)lpDst + DstX + DstY * wWidthDst;
  179. pbS = (BYTE _huge *)lpSrc + SrcX + SrcY * wWidthSrc;
  180. wWidthSrc -= DstXE;
  181. wWidthDst -= DstXE;
  182. #define DODITH8(px, x, y) ((LPBYTE)lpDitherTable)[((y) & 7) * 256 * 8 + (px) * 8 + (x & 7)]
  183. for (y=0; y<DstYE; y++) {
  184. /* write two DWORDs (one dither cell horizontally) at once */
  185. for (x=0; x <= (DstXE - 8); x += 8) {
  186. dw = DODITH8(*pbS++, 0, y);
  187. dw |= (DODITH8(*pbS++, 1, y) << 8);
  188. dw |= (DODITH8(*pbS++, 2, y) << 16);
  189. dw |= (DODITH8(*pbS++, 3, y) << 24);
  190. * ( (DWORD _huge UNALIGNED *) pbD)++ = dw;
  191. dw = DODITH8(*pbS++, 4, y);
  192. dw |= (DODITH8(*pbS++, 5, y) << 8);
  193. dw |= (DODITH8(*pbS++, 6, y) << 16);
  194. dw |= (DODITH8(*pbS++, 7, y) << 24);
  195. * ( (DWORD _huge UNALIGNED *) pbD)++ = dw;
  196. }
  197. /* clean up remainder (less than 8 bytes per row) */
  198. for ( ; x < DstXE; x++) {
  199. *pbD++ = DODITH8(*pbS++, x, y);
  200. }
  201. pbS += wWidthSrc;
  202. pbD += wWidthDst;
  203. }
  204. #undef DODITH8
  205. }
  206. /*
  207. * C version of 16->24 mapping (in asm for win16)
  208. */
  209. extern void FAR PASCAL Map16to24(
  210. LPBITMAPINFOHEADER biDst, // --> BITMAPINFO of the dest
  211. LPVOID lpDst, // --> to destination bits
  212. int DstX, // Destination origin - x coordinate
  213. int DstY, // Destination origin - y coordinate
  214. int DstXE, // x extent of the BLT
  215. int DstYE, // y extent of the BLT
  216. LPBITMAPINFOHEADER biSrc, // --> BITMAPINFO of the source
  217. LPVOID lpSrc, // --> to source bits
  218. int SrcX, // Source origin - x coordinate
  219. int SrcY, // Source origin - y coordinate
  220. LPVOID lpDitherTable) // dither table.
  221. {
  222. int x,y;
  223. UINT wWidthSrc;
  224. UINT wWidthDst;
  225. BYTE _huge *pbS;
  226. BYTE _huge *pbD;
  227. WORD wRGB;
  228. if (biDst->biBitCount != 24 || biSrc->biBitCount != 16)
  229. return;
  230. /* width of one row is nr pixels * size of pixel rounded to 4-bytes */
  231. wWidthSrc = ((UINT) (biSrc->biWidth * 2) +3)&~3;
  232. wWidthDst = ((UINT) (biDst->biWidth * 3) +3)&~3;
  233. /* advance to start of source, dest rect within DIB */
  234. pbD = (BYTE _huge *)lpDst + (DstX * 3) + DstY * wWidthDst;
  235. pbS = (BYTE _huge *)lpSrc + (SrcX * 2) + SrcY * wWidthSrc;
  236. /* amount to advance pointer to next line from end of source, dest rect */
  237. wWidthSrc -= (DstXE * 2);
  238. wWidthDst -= (DstXE * 3);
  239. for (y=0; y<DstYE; y++) {
  240. for (x=0; x<DstXE; x++) {
  241. wRGB = *((LPWORD)pbS)++;
  242. *pbD++ = (wRGB << 3) & 0xf8;
  243. *pbD++ = (wRGB >> 2) & 0xf8;
  244. *pbD++ = (wRGB >> 7) & 0xf8;
  245. }
  246. pbS += wWidthSrc;
  247. pbD += wWidthDst;
  248. }
  249. }
  250. void FAR PASCAL Map32to24(
  251. LPBITMAPINFOHEADER biDst, // --> BITMAPINFO of the dest
  252. LPVOID lpDst, // --> to destination bits
  253. int DstX, // Destination origin - x coordinate
  254. int DstY, // Destination origin - y coordinate
  255. int DstXE, // x extent of the BLT
  256. int DstYE, // y extent of the BLT
  257. LPBITMAPINFOHEADER biSrc, // --> BITMAPINFO of the source
  258. LPVOID lpSrc, // --> to source bits
  259. int SrcX, // Source origin - x coordinate
  260. int SrcY, // Source origin - y coordinate
  261. LPVOID lpDitherTable) // dither table.
  262. {
  263. int x,y;
  264. UINT wWidthSrc;
  265. UINT wWidthDst;
  266. BYTE _huge *pbS;
  267. BYTE _huge *pbD;
  268. if (biDst->biBitCount != 24 || biSrc->biBitCount != 32)
  269. return;
  270. /* width of one row is nr pixels * size of pixel rounded to 4-bytes */
  271. //wWidthSrc = ((UINT) (biSrc->biWidth * 4) +3)&~3;
  272. // Multiplying by 4 ensures it is rounded to 4 bytes...
  273. wWidthSrc = (UINT) (biSrc->biWidth * 4);
  274. wWidthDst = ((UINT) (biDst->biWidth * 3) +3)&~3;
  275. /* advance to start of source, dest rect within DIB */
  276. pbD = (BYTE _huge *)lpDst + (DstX * 3) + DstY * wWidthDst;
  277. pbS = (BYTE _huge *)lpSrc + (SrcX * 4) + SrcY * wWidthSrc;
  278. /* amount to advance pointer to next line from end of source, dest rect */
  279. wWidthSrc -= (DstXE * 4);
  280. wWidthDst -= (DstXE * 3);
  281. for (y=0; y<DstYE; y++) {
  282. for (x=0; x<DstXE; x++) {
  283. *pbD++ = *pbS++;
  284. *pbD++ = *pbS++;
  285. *pbD++ = *pbS++;
  286. pbS++;
  287. }
  288. pbS += wWidthSrc;
  289. pbD += wWidthDst;
  290. }
  291. }
  292. #endif