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
11 KiB

  1. /*----------------------------------------------------------------------------*\
  2. | Routines for dealing with Device independent bitmaps |
  3. | |
  4. | History: |
  5. | 06/23/89 toddla Created |
  6. | |
  7. \*----------------------------------------------------------------------------*/
  8. #include <windows.h>
  9. #include <stdio.h>
  10. #include "dib.h"
  11. #define HUGE_T
  12. /*
  13. * Open a DIB file and return a MEMORY DIB, a memory handle containing..
  14. *
  15. * BITMAP INFO bi
  16. * palette data
  17. * bits....
  18. *
  19. */
  20. HANDLE OpenDIB(LPTSTR szFile, HFILE fh)
  21. {
  22. BITMAPINFOHEADER bi;
  23. LPBITMAPINFOHEADER lpbi;
  24. DWORD dwLen;
  25. DWORD dwBits;
  26. HANDLE hdib;
  27. HANDLE h;
  28. #ifndef UNICODE
  29. OFSTRUCT of;
  30. #endif
  31. BOOL fOpened = FALSE;
  32. if (szFile != NULL)
  33. {
  34. #ifdef UNICODE
  35. fh = (HFILE)HandleToUlong(CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ,
  36. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL));
  37. #else
  38. fh = OpenFile(szFile, &of, OF_READ);
  39. #endif
  40. fOpened = TRUE;
  41. }
  42. if (fh == -1)
  43. return NULL;
  44. hdib = ReadDibBitmapInfo(fh);
  45. if (!hdib)
  46. return NULL;
  47. DibInfo((LPBITMAPINFOHEADER)GlobalLock(hdib),&bi); GlobalUnlock(hdib);
  48. /* How much memory do we need to hold the DIB */
  49. dwBits = bi.biSizeImage;
  50. dwLen = bi.biSize + PaletteSize(&bi) + dwBits;
  51. /* Can we get more memory? */
  52. h = GlobalReAlloc(hdib,dwLen,GMEM_MOVEABLE);
  53. if (!h)
  54. {
  55. GlobalFree(hdib);
  56. hdib = NULL;
  57. }
  58. else
  59. {
  60. hdib = h;
  61. }
  62. if (hdib)
  63. {
  64. lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib);
  65. /* read in the bits */
  66. _lread(fh, (LPBYTE)lpbi + (UINT)lpbi->biSize + PaletteSize(lpbi), dwBits);
  67. GlobalUnlock(hdib);
  68. }
  69. if (fOpened)
  70. _lclose(fh);
  71. return hdib;
  72. }
  73. /*
  74. * DibInfo(hbi, lpbi)
  75. *
  76. * retrives the DIB info associated with a CF_DIB format memory block.
  77. */
  78. BOOL DibInfo(LPBITMAPINFOHEADER lpbiSource, LPBITMAPINFOHEADER lpbiTarget)
  79. {
  80. if (lpbiSource)
  81. {
  82. *lpbiTarget = *lpbiSource;
  83. if (lpbiTarget->biSize == sizeof(BITMAPCOREHEADER))
  84. {
  85. BITMAPCOREHEADER bc;
  86. bc = *(LPBITMAPCOREHEADER)lpbiTarget;
  87. lpbiTarget->biSize = sizeof(BITMAPINFOHEADER);
  88. lpbiTarget->biWidth = (DWORD)bc.bcWidth;
  89. lpbiTarget->biHeight = (DWORD)bc.bcHeight;
  90. lpbiTarget->biPlanes = (UINT)bc.bcPlanes;
  91. lpbiTarget->biBitCount = (UINT)bc.bcBitCount;
  92. lpbiTarget->biCompression = BI_RGB;
  93. lpbiTarget->biSizeImage = 0;
  94. lpbiTarget->biXPelsPerMeter = 0;
  95. lpbiTarget->biYPelsPerMeter = 0;
  96. lpbiTarget->biClrUsed = 0;
  97. lpbiTarget->biClrImportant = 0;
  98. }
  99. /*
  100. * fill in the default fields
  101. */
  102. if (lpbiTarget->biSize != sizeof(BITMAPCOREHEADER))
  103. {
  104. if (lpbiTarget->biSizeImage == 0L)
  105. lpbiTarget->biSizeImage = (DWORD)DIBWIDTHBYTES(*lpbiTarget) * lpbiTarget->biHeight;
  106. if (lpbiTarget->biClrUsed == 0L)
  107. lpbiTarget->biClrUsed = DibNumColors(lpbiTarget);
  108. }
  109. return TRUE;
  110. }
  111. return FALSE;
  112. }
  113. /*
  114. * ReadDibBitmapInfo()
  115. *
  116. * Will read a file in DIB format and return a global HANDLE to it's
  117. * BITMAPINFO. This function will work with both "old" and "new"
  118. * bitmap formats, but will always return a "new" BITMAPINFO
  119. *
  120. */
  121. HANDLE ReadDibBitmapInfo(HFILE fh)
  122. {
  123. DWORD off;
  124. HANDLE hbi = NULL;
  125. int size;
  126. int i;
  127. UINT nNumColors;
  128. RGBQUAD FAR *pRgb;
  129. BITMAPINFOHEADER bi;
  130. BITMAPCOREHEADER bc;
  131. LPBITMAPINFOHEADER lpbi;
  132. BITMAPFILEHEADER bf;
  133. if (fh == -1)
  134. return NULL;
  135. off = _llseek(fh,0L,SEEK_CUR);
  136. if (sizeof(bf) != _lread(fh,(LPBYTE)&bf,sizeof(bf)))
  137. return FALSE;
  138. /*
  139. * do we have a RC HEADER?
  140. */
  141. if (!ISDIB(bf.bfType))
  142. {
  143. bf.bfOffBits = 0L;
  144. _llseek(fh,off,SEEK_SET);
  145. }
  146. if (sizeof(bi) != _lread(fh,(LPBYTE)&bi,sizeof(bi)))
  147. return FALSE;
  148. nNumColors = DibNumColors(&bi);
  149. /*
  150. * what type of bitmap info is this?
  151. */
  152. switch (size = (int)bi.biSize)
  153. {
  154. case sizeof(BITMAPINFOHEADER):
  155. break;
  156. case sizeof(BITMAPCOREHEADER):
  157. bc = *(BITMAPCOREHEADER*)&bi;
  158. bi.biSize = sizeof(BITMAPINFOHEADER);
  159. bi.biWidth = (DWORD)bc.bcWidth;
  160. bi.biHeight = (DWORD)bc.bcHeight;
  161. bi.biPlanes = (UINT)bc.bcPlanes;
  162. bi.biBitCount = (UINT)bc.bcBitCount;
  163. bi.biCompression = BI_RGB;
  164. bi.biSizeImage = 0;
  165. bi.biXPelsPerMeter = 0;
  166. bi.biYPelsPerMeter = 0;
  167. bi.biClrUsed = nNumColors;
  168. bi.biClrImportant = nNumColors;
  169. _llseek(fh,(LONG)sizeof(BITMAPCOREHEADER)-sizeof(BITMAPINFOHEADER),SEEK_CUR);
  170. break;
  171. default:
  172. return NULL; /* not a DIB */
  173. }
  174. /*
  175. * fill in some default values!
  176. */
  177. if (bi.biSizeImage == 0)
  178. {
  179. bi.biSizeImage = (DWORD)DIBWIDTHBYTES(bi) * bi.biHeight;
  180. }
  181. if (bi.biXPelsPerMeter == 0)
  182. {
  183. bi.biXPelsPerMeter = 0; // ??????????????
  184. }
  185. if (bi.biYPelsPerMeter == 0)
  186. {
  187. bi.biYPelsPerMeter = 0; // ??????????????
  188. }
  189. if (bi.biClrUsed == 0)
  190. {
  191. bi.biClrUsed = DibNumColors(&bi);
  192. }
  193. hbi = GlobalAlloc(GMEM_MOVEABLE,(LONG)bi.biSize + nNumColors * sizeof(RGBQUAD));
  194. if (!hbi)
  195. return NULL;
  196. lpbi = (BITMAPINFOHEADER *)GlobalLock(hbi);
  197. *lpbi = bi;
  198. pRgb = (RGBQUAD FAR *)((LPBYTE)lpbi + bi.biSize);
  199. if (nNumColors)
  200. {
  201. if (size == (int)sizeof(BITMAPCOREHEADER))
  202. {
  203. /*
  204. * convert a old color table (3 byte entries) to a new
  205. * color table (4 byte entries)
  206. */
  207. _lread(fh,(LPBYTE)pRgb,nNumColors * sizeof(RGBTRIPLE));
  208. for (i=nNumColors-1; i>=0; i--)
  209. {
  210. RGBQUAD rgb;
  211. rgb.rgbRed = ((RGBTRIPLE FAR *)pRgb)[i].rgbtRed;
  212. rgb.rgbBlue = ((RGBTRIPLE FAR *)pRgb)[i].rgbtBlue;
  213. rgb.rgbGreen = ((RGBTRIPLE FAR *)pRgb)[i].rgbtGreen;
  214. rgb.rgbReserved = (BYTE)0;
  215. pRgb[i] = rgb;
  216. }
  217. }
  218. else
  219. {
  220. _lread(fh,(LPBYTE)pRgb,nNumColors * sizeof(RGBQUAD));
  221. }
  222. }
  223. if (bf.bfOffBits != 0L)
  224. _llseek(fh,off + bf.bfOffBits,SEEK_SET);
  225. GlobalUnlock(hbi);
  226. return hbi;
  227. }
  228. /* How big is the palette? if bits per pel not 24
  229. * no of bytes to read is 6 for 1 bit, 48 for 4 bits
  230. * 256*3 for 8 bits and 0 for 24 bits
  231. */
  232. UINT PaletteSize(VOID FAR * pv)
  233. {
  234. #define lpbi ((LPBITMAPINFOHEADER)pv)
  235. #define lpbc ((LPBITMAPCOREHEADER)pv)
  236. UINT NumColors;
  237. NumColors = DibNumColors(lpbi);
  238. if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  239. return NumColors * sizeof(RGBTRIPLE);
  240. else
  241. return NumColors * sizeof(RGBQUAD);
  242. #undef lpbi
  243. #undef lpbc
  244. }
  245. /* How Many colors does this DIB have?
  246. * this will work on both PM and Windows bitmap info structures.
  247. */
  248. UINT DibNumColors(VOID FAR * pv)
  249. {
  250. #define lpbi ((LPBITMAPINFOHEADER)pv)
  251. #define lpbc ((LPBITMAPCOREHEADER)pv)
  252. int bits;
  253. /*
  254. * with the new format headers, the size of the palette is in biClrUsed
  255. * else is dependent on bits per pixel
  256. */
  257. if (lpbi->biSize != sizeof(BITMAPCOREHEADER))
  258. {
  259. if (lpbi->biClrUsed != 0)
  260. return (UINT)lpbi->biClrUsed;
  261. bits = lpbi->biBitCount;
  262. }
  263. else
  264. {
  265. bits = lpbc->bcBitCount;
  266. }
  267. switch (bits)
  268. {
  269. case 1:
  270. return 2;
  271. case 4:
  272. return 16;
  273. case 8:
  274. return 256;
  275. default:
  276. return 0;
  277. }
  278. #undef lpbi
  279. #undef lpbc
  280. }
  281. /*
  282. * DibFromBitmap()
  283. *
  284. * Will create a global memory block in DIB format that represents the DDB
  285. * passed in
  286. *
  287. */
  288. HANDLE DibFromBitmap(HBITMAP hbm, DWORD biStyle, WORD biBits, HPALETTE hpal, UINT wUsage)
  289. {
  290. BITMAP bm;
  291. BITMAPINFOHEADER bi;
  292. BITMAPINFOHEADER FAR *lpbi;
  293. DWORD dwLen;
  294. int nColors;
  295. HANDLE hdib;
  296. HANDLE h;
  297. HDC hdc;
  298. if (wUsage == 0)
  299. wUsage = DIB_RGB_COLORS;
  300. if (!hbm)
  301. return NULL;
  302. if (hpal == NULL)
  303. hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
  304. GetObject(hbm,sizeof(bm),(LPBYTE)&bm);
  305. #ifdef WIN32
  306. nColors = 0; // GetObject only stores two bytes
  307. #endif
  308. GetObject(hpal,sizeof(nColors),(LPBYTE)&nColors);
  309. if (biBits == 0)
  310. biBits = bm.bmPlanes * bm.bmBitsPixel;
  311. bi.biSize = sizeof(BITMAPINFOHEADER);
  312. bi.biWidth = bm.bmWidth;
  313. bi.biHeight = bm.bmHeight;
  314. bi.biPlanes = 1;
  315. bi.biBitCount = biBits;
  316. bi.biCompression = biStyle;
  317. bi.biSizeImage = 0;
  318. bi.biXPelsPerMeter = 0;
  319. bi.biYPelsPerMeter = 0;
  320. bi.biClrUsed = 0;
  321. bi.biClrImportant = 0;
  322. dwLen = bi.biSize + PaletteSize(&bi);
  323. hdc = CreateCompatibleDC(NULL);
  324. hpal = SelectPalette(hdc,hpal,TRUE);
  325. RealizePalette(hdc); // why is this needed on a MEMORY DC? GDI bug??
  326. hdib = GlobalAlloc(GMEM_MOVEABLE,dwLen);
  327. if (!hdib)
  328. goto exit;
  329. lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib);
  330. *lpbi = bi;
  331. /*
  332. * call GetDIBits with a NULL lpBits param, so it will calculate the
  333. * biSizeImage field for us
  334. */
  335. GetDIBits(hdc, hbm, 0, (UINT)bi.biHeight,
  336. NULL, (LPBITMAPINFO)lpbi, wUsage);
  337. bi = *lpbi;
  338. GlobalUnlock(hdib);
  339. /*
  340. * HACK! if the driver did not fill in the biSizeImage field, make one up
  341. */
  342. if (bi.biSizeImage == 0)
  343. {
  344. bi.biSizeImage = (DWORD)WIDTHBYTES(bm.bmWidth * biBits) * bm.bmHeight;
  345. if (biStyle != BI_RGB)
  346. bi.biSizeImage = (bi.biSizeImage * 3) / 2;
  347. }
  348. /*
  349. * realloc the buffer big enough to hold all the bits
  350. */
  351. dwLen = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
  352. if (h = GlobalReAlloc(hdib,dwLen,GMEM_MOVEABLE))
  353. {
  354. hdib = h;
  355. }
  356. else
  357. {
  358. GlobalFree(hdib);
  359. hdib = NULL;
  360. goto exit;
  361. }
  362. /*
  363. * call GetDIBits with a NON-NULL lpBits param, and actualy get the
  364. * bits this time
  365. */
  366. lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib);
  367. GetDIBits(hdc, hbm, 0, (UINT)bi.biHeight,
  368. (LPBYTE)lpbi + (UINT)lpbi->biSize + PaletteSize(lpbi),
  369. (LPBITMAPINFO)lpbi, wUsage);
  370. bi = *lpbi;
  371. lpbi->biClrUsed = DibNumColors(lpbi) ;
  372. GlobalUnlock(hdib);
  373. exit:
  374. SelectPalette(hdc,hpal,TRUE);
  375. DeleteDC(hdc);
  376. return hdib;
  377. }
  378. /*
  379. * DibBlt()
  380. *
  381. * draws a bitmap in CF_DIB format, using SetDIBits to device.
  382. *
  383. * takes the same parameters as BitBlt()
  384. */
  385. BOOL DibBlt(HDC hdc, int x0, int y0, int dx, int dy, HANDLE hdib, int x1, int y1, LONG rop, UINT wUsage)
  386. {
  387. LPBITMAPINFOHEADER lpbi;
  388. LPBYTE pBuf;
  389. BOOL f;
  390. if (!hdib)
  391. return PatBlt(hdc,x0,y0,dx,dy,rop);
  392. if (wUsage == 0)
  393. wUsage = DIB_RGB_COLORS;
  394. lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib);
  395. if (!lpbi)
  396. return FALSE;
  397. if (dx == -1 && dy == -1)
  398. {
  399. if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  400. {
  401. dx = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
  402. dy = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
  403. }
  404. else
  405. {
  406. dx = (int)lpbi->biWidth;
  407. dy = (int)lpbi->biHeight;
  408. }
  409. }
  410. pBuf = (LPBYTE)lpbi + (UINT)lpbi->biSize + PaletteSize(lpbi);
  411. f = StretchDIBits (
  412. hdc,
  413. x0,y0,
  414. dx,dy,
  415. x1,y1,
  416. dx,dy,
  417. pBuf, (LPBITMAPINFO)lpbi,
  418. wUsage,
  419. rop);
  420. GlobalUnlock(hdib);
  421. return f;
  422. }