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.

466 lines
16 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: dib.c
  3. *
  4. * (Brief description)
  5. *
  6. * Created: 21-Feb-1994 23:12:58
  7. * Author: Gilman Wong [gilmanw]
  8. *
  9. * Copyright (c) 1994 Microsoft Corporation
  10. *
  11. * (General description of its use)
  12. *
  13. * Dependencies:
  14. *
  15. * (#defines)
  16. * (#includes)
  17. *
  18. \**************************************************************************/
  19. #include <windows.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <stdlib.h>
  23. #include "tk.h"
  24. #define BFT_BITMAP 0x4d42 // 'BM' -- indicates structure is BITMAPFILEHEADER
  25. // struct BITMAPFILEHEADER {
  26. // WORD bfType
  27. // DWORD bfSize
  28. // WORD bfReserved1
  29. // WORD bfReserved2
  30. // DWORD bfOffBits
  31. // }
  32. #define OFFSET_bfType 0
  33. #define OFFSET_bfSize 2
  34. #define OFFSET_bfReserved1 6
  35. #define OFFSET_bfReserved2 8
  36. #define OFFSET_bfOffBits 10
  37. #define SIZEOF_BITMAPFILEHEADER 14
  38. // Read a WORD-aligned DWORD. Needed because BITMAPFILEHEADER has
  39. // WORD-alignment.
  40. #define READDWORD(pv) ( (DWORD)((PWORD)(pv))[0] \
  41. | ((DWORD)((PWORD)(pv))[1] << 16) ) \
  42. // Computes the number of BYTES needed to contain n number of bits.
  43. #define BITS2BYTES(n) ( ((n) + 7) >> 3 )
  44. /****************************************************************************
  45. * *
  46. * FUNCTION : DibNumColors(VOID FAR * pv) *
  47. * *
  48. * PURPOSE : Determines the number of colors in the DIB by looking at *
  49. * the BitCount filed in the info block. *
  50. * *
  51. * RETURNS : The number of colors in the DIB. *
  52. * *
  53. * Stolen from SDK ShowDIB example. *
  54. ****************************************************************************/
  55. WORD DibNumColors(VOID FAR * pv)
  56. {
  57. WORD bits;
  58. LPBITMAPINFOHEADER lpbi;
  59. LPBITMAPCOREHEADER lpbc;
  60. lpbi = ((LPBITMAPINFOHEADER)pv);
  61. lpbc = ((LPBITMAPCOREHEADER)pv);
  62. /* With the BITMAPINFO format headers, the size of the palette
  63. * is in biClrUsed, whereas in the BITMAPCORE - style headers, it
  64. * is dependent on the bits per pixel ( = 2 raised to the power of
  65. * bits/pixel).
  66. *
  67. * Because of the way we use this call, BITMAPINFOHEADER may be out
  68. * of alignment if it follows a BITMAPFILEHEADER. So use the macro
  69. * to safely access DWORD fields.
  70. */
  71. if (READDWORD(&lpbi->biSize) != sizeof(BITMAPCOREHEADER)){
  72. if (READDWORD(&lpbi->biClrUsed) != 0)
  73. {
  74. return (WORD) READDWORD(&lpbi->biClrUsed);
  75. }
  76. bits = lpbi->biBitCount;
  77. }
  78. else
  79. bits = lpbc->bcBitCount;
  80. switch (bits){
  81. case 1:
  82. return 2;
  83. case 4:
  84. return 16;
  85. case 8:
  86. return 256;
  87. default:
  88. /* A 24 bitcount DIB has no color table */
  89. return 0;
  90. }
  91. }
  92. /******************************Public*Routine******************************\
  93. * tkDIBImageLoad
  94. *
  95. * ANSI version stub. Only here for orthogonality with tkRGBImageLoad.
  96. *
  97. * History:
  98. * 22-Feb-1994 -by- Gilman Wong [gilmanw]
  99. * Wrote it.
  100. \**************************************************************************/
  101. TK_RGBImageRec *tkDIBImageLoadAW(char *fileName, BOOL bUnicode);
  102. TK_RGBImageRec *tkDIBImageLoad(char *fileName)
  103. {
  104. return tkDIBImageLoadAW(fileName, FALSE);
  105. }
  106. /******************************Public*Routine******************************\
  107. * tkDIBImageLoadAW
  108. *
  109. * Loads a DIB file (specified as either an ANSI or Unicode filename,
  110. * depending on the bUnicode flag) and converts it into a TK image format.
  111. *
  112. * The technique used is based on CreateDIBSection and SetDIBits.
  113. * CreateDIBSection is used to create a DIB with a format easily converted
  114. * into the TK image format (packed 24BPP RGB)--namely 32BPP RGB. The
  115. * resulting bitmap is selected into a memory DC.
  116. *
  117. * The DIB file is mapped into memory and SetDIBits called to initialize
  118. * the memory DC bitmap. It is during this step that GDI converts the
  119. * arbitrary DIB file format to our 32BPP RGB format.
  120. *
  121. * Finally, the 32BPP RGB data in the DIB section is read out and repacked
  122. * as 24BPP RGB.
  123. *
  124. * Returns:
  125. * Pointer to TK_RGBImageRec. If an error occurs, a diagnostic error
  126. * message is put into the error stream and tkQuit() is called,
  127. * terminating the app.
  128. *
  129. * History:
  130. * 22-Feb-1994 -by- Gilman Wong [gilmanw]
  131. * Wrote it.
  132. \**************************************************************************/
  133. TK_RGBImageRec *tkDIBImageLoadAW(char *fileName, BOOL bUnicode)
  134. {
  135. TK_RGBImageRec *final = (TK_RGBImageRec *) NULL; // Ptr to TK image struct
  136. // to return. Non-NULL
  137. // only for success.
  138. WORD wNumColors; // Number of colors in color table
  139. BITMAPFILEHEADER *pbmf; // Ptr to file header
  140. BITMAPINFOHEADER *pbmihFile; // Ptr to file's info header (if it exists)
  141. BITMAPCOREHEADER *pbmchFile; // Ptr to file's core header (if it exists)
  142. PVOID pvBitsFile; // Ptr to bitmap bits in file
  143. PBYTE pjBitsRGB; // Ptr to 32BPP RGB image in DIB section
  144. PBYTE pjTKBits; // Ptr to final TK image bits
  145. PBYTE pjSrc; // Ptr to image file used for conversion
  146. PBYTE pjDst; // Ptr to TK image used for conversion
  147. // These need to be cleaned up when we exit:
  148. HANDLE hFile = INVALID_HANDLE_VALUE; // File handle
  149. HANDLE hMap = (HANDLE) NULL; // Mapping object handle
  150. PVOID pvFile = (PVOID) NULL; // Ptr to mapped file
  151. HDC hdcMem = (HDC) NULL; // 32BPP mem DC
  152. HBITMAP hbmRGB = (HBITMAP) NULL; // 32BPP RGB bitmap
  153. BITMAPINFO *pbmiSource = (BITMAPINFO *) NULL; // Ptr to 32BPP BITMAPINFO
  154. BITMAPINFO *pbmiRGB = (BITMAPINFO *) NULL; // Ptr tp file's BITMAPINFO
  155. int i, j;
  156. // Map the DIB file into memory.
  157. hFile = bUnicode ? CreateFileW((LPWSTR) fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0) :
  158. CreateFileA((LPSTR) fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
  159. if (hFile == INVALID_HANDLE_VALUE)
  160. goto tkDIBLoadImage_cleanup;
  161. hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
  162. if (!hMap)
  163. goto tkDIBLoadImage_cleanup;
  164. pvFile = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
  165. if (!pvFile)
  166. goto tkDIBLoadImage_cleanup;
  167. // Check the file header. If the BFT_BITMAP magic number is there,
  168. // then the file format is a BITMAPFILEHEADER followed immediately
  169. // by either a BITMAPINFOHEADER or a BITMAPCOREHEADER. The bitmap
  170. // bits, in this case, are located at the offset bfOffBits from the
  171. // BITMAPFILEHEADER.
  172. //
  173. // Otherwise, this may be a raw BITMAPINFOHEADER or BITMAPCOREHEADER
  174. // followed immediately with the color table and the bitmap bits.
  175. pbmf = (BITMAPFILEHEADER *) pvFile;
  176. if ( pbmf->bfType == BFT_BITMAP )
  177. {
  178. pbmihFile = (BITMAPINFOHEADER *) ((PBYTE) pbmf + SIZEOF_BITMAPFILEHEADER);
  179. // BITMAPFILEHEADER is WORD aligned, so use safe macro to read DWORD
  180. // bfOffBits field.
  181. pvBitsFile = (PVOID *) ((PBYTE) pbmf
  182. + READDWORD((PBYTE) pbmf + OFFSET_bfOffBits));
  183. }
  184. else
  185. {
  186. pbmihFile = (BITMAPINFOHEADER *) pvFile;
  187. // Determination of where the bitmaps bits are needs to wait until we
  188. // know for sure whether we have a BITMAPINFOHEADER or a BITMAPCOREHEADER.
  189. }
  190. // Determine the number of colors in the DIB palette. This is non-zero
  191. // only for 8BPP or less.
  192. wNumColors = DibNumColors(pbmihFile);
  193. // Create a BITMAPINFO (with color table) for the DIB file. Because the
  194. // file may not have one (BITMAPCORE case) and potential alignment problems,
  195. // we will create a new one in memory we allocate.
  196. //
  197. // We distinguish between BITMAPINFO and BITMAPCORE cases based upon
  198. // BITMAPINFOHEADER.biSize.
  199. pbmiSource = (BITMAPINFO *)
  200. LocalAlloc(LMEM_FIXED, sizeof(BITMAPINFO)
  201. + wNumColors * sizeof(RGBQUAD));
  202. if (!pbmiSource)
  203. {
  204. MessageBoxA(NULL, "Out of memory.", "Error", MB_OK);
  205. goto tkDIBLoadImage_cleanup;
  206. }
  207. // Note: need to use safe READDWORD macro because pbmihFile may
  208. // have only WORD alignment if it follows a BITMAPFILEHEADER.
  209. switch (READDWORD(&pbmihFile->biSize))
  210. {
  211. case sizeof(BITMAPINFOHEADER):
  212. // Convert WORD-aligned BITMAPINFOHEADER to aligned BITMAPINFO.
  213. pbmiSource->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  214. pbmiSource->bmiHeader.biWidth = READDWORD(&pbmihFile->biWidth);
  215. pbmiSource->bmiHeader.biHeight = READDWORD(&pbmihFile->biHeight);
  216. pbmiSource->bmiHeader.biPlanes = pbmihFile->biPlanes;
  217. pbmiSource->bmiHeader.biBitCount = pbmihFile->biBitCount;
  218. pbmiSource->bmiHeader.biCompression = READDWORD(&pbmihFile->biCompression);
  219. pbmiSource->bmiHeader.biSizeImage = READDWORD(&pbmihFile->biSizeImage);
  220. pbmiSource->bmiHeader.biXPelsPerMeter = READDWORD(&pbmihFile->biXPelsPerMeter);
  221. pbmiSource->bmiHeader.biYPelsPerMeter = READDWORD(&pbmihFile->biYPelsPerMeter);
  222. pbmiSource->bmiHeader.biClrUsed = READDWORD(&pbmihFile->biClrUsed);
  223. pbmiSource->bmiHeader.biClrImportant = READDWORD(&pbmihFile->biClrImportant);
  224. // Copy color table. It immediately follows the BITMAPINFOHEADER.
  225. memcpy((PVOID) &pbmiSource->bmiColors[0], (PVOID) (pbmihFile + 1),
  226. wNumColors * sizeof(RGBQUAD));
  227. // If we haven't already determined the position of the image bits,
  228. // we may now assume that they immediately follow the color table.
  229. if (!pvBitsFile)
  230. pvBitsFile = (PVOID) ((PBYTE) (pbmihFile + 1)
  231. + wNumColors * sizeof(RGBQUAD));
  232. break;
  233. case sizeof(BITMAPCOREHEADER):
  234. pbmchFile = (BITMAPCOREHEADER *) pbmihFile;
  235. // Convert BITMAPCOREHEADER to BITMAPINFOHEADER.
  236. pbmiSource->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  237. pbmiSource->bmiHeader.biWidth = (DWORD) pbmchFile->bcWidth;
  238. pbmiSource->bmiHeader.biHeight = (DWORD) pbmchFile->bcHeight;
  239. pbmiSource->bmiHeader.biPlanes = pbmchFile->bcPlanes;
  240. pbmiSource->bmiHeader.biBitCount = pbmchFile->bcBitCount;
  241. pbmiSource->bmiHeader.biCompression = BI_RGB;
  242. pbmiSource->bmiHeader.biSizeImage = 0;
  243. pbmiSource->bmiHeader.biXPelsPerMeter = 0;
  244. pbmiSource->bmiHeader.biYPelsPerMeter = 0;
  245. pbmiSource->bmiHeader.biClrUsed = wNumColors;
  246. pbmiSource->bmiHeader.biClrImportant = wNumColors;
  247. // Convert RGBTRIPLE color table into RGBQUAD color table.
  248. {
  249. RGBQUAD *rgb4 = pbmiSource->bmiColors;
  250. RGBTRIPLE *rgb3 = (RGBTRIPLE *) (pbmchFile + 1);
  251. for (i = 0; i < wNumColors; i++)
  252. {
  253. rgb4->rgbRed = rgb3->rgbtRed ;
  254. rgb4->rgbGreen = rgb3->rgbtGreen;
  255. rgb4->rgbBlue = rgb3->rgbtBlue ;
  256. rgb4->rgbReserved = 0;
  257. rgb4++;
  258. rgb3++;
  259. }
  260. }
  261. // If we haven't already determined the position of the image bits,
  262. // we may now assume that they immediately follow the color table.
  263. if (!pvBitsFile)
  264. pvBitsFile = (PVOID) ((PBYTE) (pbmihFile + 1)
  265. + wNumColors * sizeof(RGBTRIPLE));
  266. break;
  267. default:
  268. MessageBoxA(NULL, "Unknown DIB file format.", "Error", MB_OK);
  269. goto tkDIBLoadImage_cleanup;
  270. }
  271. // Fill in default values (for fields that can have defaults).
  272. if (pbmiSource->bmiHeader.biSizeImage == 0)
  273. pbmiSource->bmiHeader.biSizeImage = BITS2BYTES((DWORD) pbmiSource->bmiHeader.biWidth * pbmiSource->bmiHeader.biBitCount) * pbmiSource->bmiHeader.biHeight;
  274. if (pbmiSource->bmiHeader.biClrUsed == 0)
  275. pbmiSource->bmiHeader.biClrUsed = wNumColors;
  276. // Create memory DC.
  277. hdcMem = CreateCompatibleDC(NULL);
  278. if (!hdcMem)
  279. {
  280. MessageBoxA(NULL, "Out of memory.", "Error", MB_OK);
  281. goto tkDIBLoadImage_cleanup;
  282. }
  283. // Create a 32BPP RGB DIB section and select it into the memory DC.
  284. pbmiRGB = (BITMAPINFO *)
  285. LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, sizeof(BITMAPINFO)
  286. + 2 * sizeof(RGBQUAD));
  287. if (!pbmiRGB)
  288. {
  289. MessageBoxA(NULL, "Out of memory.", "Error", MB_OK);
  290. goto tkDIBLoadImage_cleanup;
  291. }
  292. pbmiRGB->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  293. pbmiRGB->bmiHeader.biWidth = pbmiSource->bmiHeader.biWidth;
  294. pbmiRGB->bmiHeader.biHeight = pbmiSource->bmiHeader.biHeight;
  295. pbmiRGB->bmiHeader.biPlanes = 1;
  296. pbmiRGB->bmiHeader.biBitCount = 32;
  297. pbmiRGB->bmiHeader.biCompression = BI_BITFIELDS;
  298. pbmiRGB->bmiHeader.biSizeImage = pbmiRGB->bmiHeader.biWidth
  299. * abs(pbmiRGB->bmiHeader.biHeight) * 4;
  300. // This may look backwards, but because of the ordering of RGBQUADS,
  301. // this will yield an RGB format (vs. the BGR format that will result
  302. // from the "natural" ordering).
  303. pbmiRGB->bmiColors[0].rgbBlue = 0xff; // red mask
  304. pbmiRGB->bmiColors[1].rgbGreen = 0xff; // green mask
  305. pbmiRGB->bmiColors[2].rgbRed = 0xff; // blue mask
  306. hbmRGB = CreateDIBSection(hdcMem, pbmiRGB, DIB_RGB_COLORS, (PVOID *) &pjBitsRGB, NULL, 0);
  307. if (!hbmRGB)
  308. {
  309. MessageBoxA(NULL, "Out of memory.", "Error", MB_OK);
  310. goto tkDIBLoadImage_cleanup;
  311. }
  312. if (!SelectObject(hdcMem, hbmRGB))
  313. {
  314. MessageBoxA(NULL, "Out of memory.", "Error", MB_OK);
  315. goto tkDIBLoadImage_cleanup;
  316. }
  317. // Slam the DIB file image into the memory DC. GDI will do the work of
  318. // translating whatever format the DIB file has into our 32BPP RGB format.
  319. if (!SetDIBits(hdcMem, hbmRGB, 0, pbmiSource->bmiHeader.biHeight, pvBitsFile, pbmiSource, DIB_RGB_COLORS))
  320. {
  321. MessageBoxA(NULL, "Image file conversion error.", "Error", MB_OK);
  322. goto tkDIBLoadImage_cleanup;
  323. }
  324. // Convert to TK image format (packed RGB format).
  325. pjTKBits = (PBYTE) LocalAlloc(LMEM_FIXED, pbmiRGB->bmiHeader.biSizeImage);
  326. if (!pjTKBits)
  327. {
  328. MessageBoxA(NULL, "Out of memory.", "Error", MB_OK);
  329. goto tkDIBLoadImage_cleanup;
  330. }
  331. pjSrc = pjBitsRGB;
  332. pjDst = pjTKBits;
  333. for (i = 0; i < pbmiSource->bmiHeader.biHeight; i++)
  334. {
  335. for (j = 0; j < pbmiSource->bmiHeader.biWidth; j++)
  336. {
  337. *pjDst++ = *pjSrc++;
  338. *pjDst++ = *pjSrc++;
  339. *pjDst++ = *pjSrc++;
  340. pjSrc++;
  341. }
  342. }
  343. // Allocate and initialize the TK_RGBImageRec.
  344. final = (TK_RGBImageRec *)malloc(sizeof(TK_RGBImageRec));
  345. if (final == NULL) {
  346. MessageBoxA(NULL, "Out of memory.", "Error", MB_OK);
  347. goto tkDIBLoadImage_cleanup;
  348. }
  349. // If we get to here, we have suceeded!
  350. final->sizeX = pbmiSource->bmiHeader.biWidth;
  351. final->sizeY = pbmiSource->bmiHeader.biHeight;
  352. final->data = pjTKBits;
  353. // Cleanup objects.
  354. tkDIBLoadImage_cleanup:
  355. {
  356. if (hdcMem)
  357. DeleteDC(hdcMem);
  358. if (hbmRGB)
  359. DeleteObject(hbmRGB);
  360. if (pbmiRGB)
  361. LocalFree(pbmiRGB);
  362. if (pbmiSource)
  363. LocalFree(pbmiSource);
  364. if (pvFile)
  365. UnmapViewOfFile(pvFile);
  366. if (hMap)
  367. CloseHandle(hMap);
  368. if (hFile != INVALID_HANDLE_VALUE)
  369. CloseHandle(hFile);
  370. }
  371. // Check for error.
  372. if (!final)
  373. {
  374. if ( (hFile == INVALID_HANDLE_VALUE) || !hMap || !pvFile )
  375. {
  376. CHAR ach[256];
  377. bUnicode ? wsprintf(ach, "Failed to open DIB file %ws.\n", fileName) :
  378. wsprintf(ach, "Failed to open DIB file %s.\n", fileName);
  379. MessageBoxA(NULL, ach, "Error", MB_OK);
  380. }
  381. tkQuit();
  382. }
  383. return final;
  384. }