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.

650 lines
22 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: ssdib.c
  3. *
  4. * Operations on .bmp files
  5. *
  6. * Copyright (c) 1995 Microsoft Corporation
  7. *
  8. \**************************************************************************/
  9. #include <windows.h>
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include "mtk.h"
  14. #include "texture.hxx"
  15. #define BFT_BITMAP 0x4d42 // 'BM' -- indicates structure is BITMAPFILEHEADER
  16. // struct BITMAPFILEHEADER {
  17. // WORD bfType
  18. // DWORD bfSize
  19. // WORD bfReserved1
  20. // WORD bfReserved2
  21. // DWORD bfOffBits
  22. // }
  23. #define OFFSET_bfType 0
  24. #define OFFSET_bfSize 2
  25. #define OFFSET_bfReserved1 6
  26. #define OFFSET_bfReserved2 8
  27. #define OFFSET_bfOffBits 10
  28. #define SIZEOF_BITMAPFILEHEADER 14
  29. // Read a WORD-aligned DWORD. Needed because BITMAPFILEHEADER has
  30. // WORD-alignment.
  31. #define READDWORD(pv) ( (DWORD)((PWORD)(pv))[0] \
  32. | ((DWORD)((PWORD)(pv))[1] << 16) ) \
  33. // Computes the number of BYTES needed to contain n number of bits.
  34. #define BITS2BYTES(n) ( ((n) + 7) >> 3 )
  35. /****************************************************************************
  36. * *
  37. * FUNCTION : DibNumColors(VOID FAR * pv) *
  38. * *
  39. * PURPOSE : Determines the number of colors in the DIB by looking at *
  40. * the BitCount filed in the info block. *
  41. * *
  42. * RETURNS : The number of colors in the DIB. *
  43. * *
  44. * Stolen from SDK ShowDIB example. *
  45. ****************************************************************************/
  46. static WORD DibNumColors(VOID FAR * pv)
  47. {
  48. WORD bits;
  49. BITMAPINFOHEADER UNALIGNED *lpbi;
  50. BITMAPCOREHEADER UNALIGNED *lpbc;
  51. lpbi = ((LPBITMAPINFOHEADER)pv);
  52. lpbc = ((LPBITMAPCOREHEADER)pv);
  53. /* With the BITMAPINFO format headers, the size of the palette
  54. * is in biClrUsed, whereas in the BITMAPCORE - style headers, it
  55. * is dependent on the bits per pixel ( = 2 raised to the power of
  56. * bits/pixel).
  57. *
  58. * Because of the way we use this call, BITMAPINFOHEADER may be out
  59. * of alignment if it follows a BITMAPFILEHEADER. So use the macro
  60. * to safely access DWORD fields.
  61. */
  62. if (READDWORD(&lpbi->biSize) != sizeof(BITMAPCOREHEADER)){
  63. if (READDWORD(&lpbi->biClrUsed) != 0)
  64. {
  65. return (WORD) READDWORD(&lpbi->biClrUsed);
  66. }
  67. bits = lpbi->biBitCount;
  68. }
  69. else
  70. bits = lpbc->bcBitCount;
  71. switch (bits){
  72. case 1:
  73. return 2;
  74. case 4:
  75. return 16;
  76. case 8:
  77. return 256;
  78. default:
  79. /* A 24 bitcount DIB has no color table */
  80. return 0;
  81. }
  82. }
  83. static PBYTE PackTexImage( BITMAPINFOHEADER *pbmih, PBYTE pjSrc )
  84. {
  85. // Note the malloc used here, for consistency with tk (app may use free() on it)
  86. //mf: can change to overwrite pjSrc, instead of allocating new memomory, once
  87. // no longer using TEX_BMP resource or old way of reading .bmp files
  88. PBYTE pjTKBits = (PBYTE) malloc(pbmih->biSizeImage);
  89. if( !pjTKBits )
  90. {
  91. return NULL;
  92. }
  93. PBYTE pjDst = pjTKBits;
  94. // src lines end on LONG boundary - so need to skip over any padding bytes
  95. int padBytes = pbmih->biWidth % sizeof(LONG);
  96. int rowSize = pbmih->biWidth * sizeof(RGB8);
  97. if( !padBytes ) {
  98. RtlCopyMemory( pjDst, pjSrc, pbmih->biHeight * rowSize );
  99. } else {
  100. for (int i = 0; i < pbmih->biHeight; i++ )
  101. {
  102. RtlCopyMemory( pjDst, pjSrc, rowSize );
  103. pjDst += rowSize;
  104. pjSrc += (rowSize + padBytes );
  105. }
  106. }
  107. return pjTKBits; // to be free'd by the caller
  108. }
  109. /******************************Public*Routine******************************\
  110. * ss_DIBImageLoad
  111. *
  112. * Hacked form of tk_DIBImageLoad(), for reading a .bmp file from a resource
  113. *
  114. * Loads a DIB file (specified as either an ANSI or Unicode filename,
  115. * depending on the bUnicode flag) and converts it into a TK image format.
  116. *
  117. * The technique used is based on CreateDIBSection and SetDIBits.
  118. * CreateDIBSection is used to create a DIB with a format easily converted
  119. * into the TK image format (packed 24BPP RGB). The only conversion
  120. * required is swapping R and B in each RGB triplet (see history below)
  121. * The resulting bitmap is selected into a memory DC.
  122. *
  123. * The DIB file is mapped into memory and SetDIBits called to initialize
  124. * the memory DC bitmap. It is during this step that GDI converts the
  125. * arbitrary DIB file format to RGB format.
  126. *
  127. * Finally, the RGB data in the DIB section is read out and repacked
  128. * as 24BPP 'BGR'.
  129. *
  130. * Returns:
  131. * BOOL.
  132. *
  133. * History:
  134. * - 11/30/95: [marcfo]
  135. * Modified from tkDIBImageLoad, to work on resource bmp file.
  136. * At first I tried accessing the bitmap resource as an RT_BITMAP, where
  137. * the resource compiler strips out file information, and leaves you simple
  138. * bitmap data. But this only worked on the Alpha architecture, x86
  139. * produced a resource with corrupted image data (?palette :)). So I ended
  140. * up just slamming the entire .bmp file in as a resource.
  141. *
  142. \**************************************************************************/
  143. #if 0
  144. //mf: this is no longer needed, since bitmaps are always 'BITMAP' resources now.
  145. BOOL
  146. TEXTURE::DIBImageLoad(PVOID pv )
  147. {
  148. BOOL fSuccess = FALSE;
  149. WORD wNumColors; // Number of colors in color table
  150. BITMAPFILEHEADER *pbmf; // Ptr to file header
  151. BITMAPINFOHEADER UNALIGNED *pbmihFile;
  152. BITMAPCOREHEADER UNALIGNED *pbmchFile; // Ptr to file's core header (if it exists)
  153. PVOID pvBits; // Ptr to bitmap bits in file
  154. PBYTE pjBitsRGB; // Ptr to 24BPP RGB image in DIB section
  155. PBYTE pjTKBits = (PBYTE) NULL; // Ptr to final TK image bits
  156. // These need to be cleaned up when we exit:
  157. HDC hdcMem = (HDC) NULL; // 24BPP mem DC
  158. HBITMAP hbmRGB = (HBITMAP) NULL; // 24BPP RGB bitmap
  159. BITMAPINFO *pbmiSource = (BITMAPINFO *) NULL; // Ptr to source BITMAPINFO
  160. BITMAPINFO *pbmiRGB = (BITMAPINFO *) NULL; // Ptr to file's BITMAPINFO
  161. int i;
  162. // Otherwise, this may be a raw BITMAPINFOHEADER or BITMAPCOREHEADER
  163. // followed immediately with the color table and the bitmap bits.
  164. pbmf = (BITMAPFILEHEADER *) pv;
  165. if ( pbmf->bfType == BFT_BITMAP )
  166. {
  167. pbmihFile = (BITMAPINFOHEADER *) ((PBYTE) pbmf + SIZEOF_BITMAPFILEHEADER);
  168. // BITMAPFILEHEADER is WORD aligned, so use safe macro to read DWORD
  169. // bfOffBits field.
  170. pvBits = (PVOID *) ((PBYTE) pbmf
  171. + READDWORD((PBYTE) pbmf + OFFSET_bfOffBits));
  172. }
  173. else
  174. {
  175. pbmihFile = (BITMAPINFOHEADER *) pv;
  176. // Determination of where the bitmaps bits are needs to wait until we
  177. // know for sure whether we have a BITMAPINFOHEADER or a BITMAPCOREHEADER.
  178. }
  179. // Determine the number of colors in the DIB palette. This is non-zero
  180. // only for 8BPP or less.
  181. wNumColors = DibNumColors(pbmihFile);
  182. // Create a BITMAPINFO (with color table) for the DIB file. Because the
  183. // file may not have one (BITMAPCORE case) and potential alignment problems,
  184. // we will create a new one in memory we allocate.
  185. //
  186. // We distinguish between BITMAPINFO and BITMAPCORE cases based upon
  187. // BITMAPINFOHEADER.biSize.
  188. pbmiSource = (BITMAPINFO *)
  189. LocalAlloc(LMEM_FIXED, sizeof(BITMAPINFO)
  190. + wNumColors * sizeof(RGBQUAD));
  191. if (!pbmiSource)
  192. {
  193. MESSAGEBOX(GetFocus(), "Out of memory.", "Error", MB_OK);
  194. goto tkDIBLoadImage_cleanup;
  195. }
  196. // Note: need to use safe READDWORD macro because pbmihFile may
  197. // have only WORD alignment if it follows a BITMAPFILEHEADER.
  198. switch (READDWORD(&pbmihFile->biSize))
  199. {
  200. case sizeof(BITMAPINFOHEADER):
  201. // Convert WORD-aligned BITMAPINFOHEADER to aligned BITMAPINFO.
  202. pbmiSource->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  203. pbmiSource->bmiHeader.biWidth = READDWORD(&pbmihFile->biWidth);
  204. pbmiSource->bmiHeader.biHeight = READDWORD(&pbmihFile->biHeight);
  205. pbmiSource->bmiHeader.biPlanes = pbmihFile->biPlanes;
  206. pbmiSource->bmiHeader.biBitCount = pbmihFile->biBitCount;
  207. pbmiSource->bmiHeader.biCompression =
  208. READDWORD(&pbmihFile->biCompression);
  209. pbmiSource->bmiHeader.biSizeImage =
  210. READDWORD(&pbmihFile->biSizeImage);
  211. pbmiSource->bmiHeader.biXPelsPerMeter =
  212. READDWORD(&pbmihFile->biXPelsPerMeter);
  213. pbmiSource->bmiHeader.biYPelsPerMeter =
  214. READDWORD(&pbmihFile->biYPelsPerMeter);
  215. pbmiSource->bmiHeader.biClrUsed =
  216. READDWORD(&pbmihFile->biClrUsed);
  217. pbmiSource->bmiHeader.biClrImportant =
  218. READDWORD(&pbmihFile->biClrImportant);
  219. // Copy color table. It immediately follows the BITMAPINFOHEADER.
  220. memcpy((PVOID) &pbmiSource->bmiColors[0], (PVOID) (pbmihFile + 1),
  221. wNumColors * sizeof(RGBQUAD));
  222. // If we haven't already determined the position of the image bits,
  223. // we may now assume that they immediately follow the color table.
  224. if (!pvBits)
  225. pvBits = (PVOID) ((PBYTE) (pbmihFile + 1)
  226. + wNumColors * sizeof(RGBQUAD));
  227. break;
  228. case sizeof(BITMAPCOREHEADER):
  229. pbmchFile = (BITMAPCOREHEADER *) pbmihFile;
  230. // Convert BITMAPCOREHEADER to BITMAPINFOHEADER.
  231. pbmiSource->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  232. pbmiSource->bmiHeader.biWidth = (DWORD) pbmchFile->bcWidth;
  233. pbmiSource->bmiHeader.biHeight = (DWORD) pbmchFile->bcHeight;
  234. pbmiSource->bmiHeader.biPlanes = pbmchFile->bcPlanes;
  235. pbmiSource->bmiHeader.biBitCount = pbmchFile->bcBitCount;
  236. pbmiSource->bmiHeader.biCompression = BI_RGB;
  237. pbmiSource->bmiHeader.biSizeImage = 0;
  238. pbmiSource->bmiHeader.biXPelsPerMeter = 0;
  239. pbmiSource->bmiHeader.biYPelsPerMeter = 0;
  240. pbmiSource->bmiHeader.biClrUsed = wNumColors;
  241. pbmiSource->bmiHeader.biClrImportant = wNumColors;
  242. // Convert RGBTRIPLE color table into RGBQUAD color table.
  243. {
  244. RGBQUAD *rgb4 = pbmiSource->bmiColors;
  245. RGBTRIPLE *rgb3 = (RGBTRIPLE *) (pbmchFile + 1);
  246. for (i = 0; i < wNumColors; i++)
  247. {
  248. rgb4->rgbRed = rgb3->rgbtRed ;
  249. rgb4->rgbGreen = rgb3->rgbtGreen;
  250. rgb4->rgbBlue = rgb3->rgbtBlue ;
  251. rgb4->rgbReserved = 0;
  252. rgb4++;
  253. rgb3++;
  254. }
  255. }
  256. // If we haven't already determined the position of the image bits,
  257. // we may now assume that they immediately follow the color table.
  258. if (!pvBits)
  259. pvBits = (PVOID) ((PBYTE) (pbmihFile + 1)
  260. + wNumColors * sizeof(RGBTRIPLE));
  261. break;
  262. default:
  263. MESSAGEBOX(GetFocus(), "Unknown DIB file format.", "Error", MB_OK);
  264. goto tkDIBLoadImage_cleanup;
  265. }
  266. // Fill in default values (for fields that can have defaults).
  267. if (pbmiSource->bmiHeader.biSizeImage == 0)
  268. pbmiSource->bmiHeader.biSizeImage =
  269. BITS2BYTES( (DWORD) pbmiSource->bmiHeader.biWidth *
  270. pbmiSource->bmiHeader.biBitCount ) *
  271. pbmiSource->bmiHeader.biHeight;
  272. if (pbmiSource->bmiHeader.biClrUsed == 0)
  273. pbmiSource->bmiHeader.biClrUsed = wNumColors;
  274. // Create memory DC.
  275. hdcMem = CreateCompatibleDC(NULL);
  276. if (!hdcMem) {
  277. MESSAGEBOX(GetFocus(), "Out of memory.", "Error", MB_OK);
  278. goto tkDIBLoadImage_cleanup;
  279. }
  280. // Create a 24BPP RGB DIB section and select it into the memory DC.
  281. pbmiRGB = (BITMAPINFO *)
  282. LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, sizeof(BITMAPINFO) );
  283. if (!pbmiRGB)
  284. {
  285. MESSAGEBOX(GetFocus(), "Out of memory.", "Error", MB_OK);
  286. goto tkDIBLoadImage_cleanup;
  287. }
  288. pbmiRGB->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  289. pbmiRGB->bmiHeader.biWidth = pbmiSource->bmiHeader.biWidth;
  290. pbmiRGB->bmiHeader.biHeight = pbmiSource->bmiHeader.biHeight;
  291. pbmiRGB->bmiHeader.biPlanes = 1;
  292. pbmiRGB->bmiHeader.biBitCount = 24;
  293. pbmiRGB->bmiHeader.biCompression = BI_RGB;
  294. pbmiRGB->bmiHeader.biSizeImage = pbmiRGB->bmiHeader.biWidth
  295. * abs(pbmiRGB->bmiHeader.biHeight) * 3;
  296. hbmRGB = CreateDIBSection(hdcMem, pbmiRGB, DIB_RGB_COLORS,
  297. (PVOID *) &pjBitsRGB, NULL, 0);
  298. if (!hbmRGB)
  299. {
  300. MESSAGEBOX(GetFocus(), "Out of memory.", "Error", MB_OK);
  301. goto tkDIBLoadImage_cleanup;
  302. }
  303. if (!SelectObject(hdcMem, hbmRGB))
  304. {
  305. MESSAGEBOX(GetFocus(), "Out of memory.", "Error", MB_OK);
  306. goto tkDIBLoadImage_cleanup;
  307. }
  308. // Slam the DIB file image into the memory DC. GDI will do the work of
  309. // translating whatever format the DIB file has into RGB format.
  310. if (!SetDIBits(hdcMem, hbmRGB, 0, pbmiSource->bmiHeader.biHeight,
  311. pvBits, pbmiSource, DIB_RGB_COLORS))
  312. {
  313. MESSAGEBOX(GetFocus(), "Image file conversion error.", "Error", MB_OK);
  314. goto tkDIBLoadImage_cleanup;
  315. }
  316. GdiFlush(); // make sure that SetDIBits executes
  317. /// *******************************************************************
  318. // Convert to TK image format (packed RGB format).
  319. // Allocate with malloc to be consistent with tkRGBImageLoad (i.e., app
  320. // can deallocate with free()).
  321. pjTKBits = PackTexImage( &pbmiRGB->bmiHeader, pjBitsRGB );
  322. if( !pjTKBits ) {
  323. SS_ERROR( "ConvertToOpenGLTexFormat : memory failure\n" );
  324. goto tkDIBLoadImage_cleanup;
  325. }
  326. // Initialize the texture structure
  327. // If we get to here, we have suceeded!
  328. width = pbmiSource->bmiHeader.biWidth;
  329. height = pbmiSource->bmiHeader.biHeight;
  330. format = GL_RGB;
  331. components = 3;
  332. // do we keep the data around , since it's not needed after the texture is
  333. // downloaded into GL and have texObj's ?
  334. data = pjTKBits;
  335. pal_size = 0;
  336. pal = NULL;
  337. fSuccess = TRUE;
  338. // Cleanup objects.
  339. tkDIBLoadImage_cleanup:
  340. {
  341. if (hdcMem)
  342. DeleteDC(hdcMem);
  343. if (hbmRGB)
  344. DeleteObject(hbmRGB);
  345. if (pbmiRGB)
  346. LocalFree(pbmiRGB);
  347. if (pbmiSource)
  348. LocalFree(pbmiSource);
  349. }
  350. // Check for error.
  351. if (!fSuccess)
  352. {
  353. if (pjTKBits)
  354. free(pjTKBits);
  355. }
  356. return fSuccess;
  357. }
  358. #endif
  359. BOOL
  360. TEXTURE::DIBImageLoad( HBITMAP hbmRGB )
  361. {
  362. BOOL fSuccess = FALSE;
  363. PBYTE pjTKBits = (PBYTE) NULL; // Ptr to final TK image bits
  364. BITMAPINFOHEADER *pbmih;
  365. // These need to be cleaned up when we exit:
  366. PVOID pvBits = NULL; // Ptr to bitmap bits in file
  367. HDC hdcMem = (HDC) NULL; // 24BPP mem DC
  368. BITMAPINFO *pbmiRGB = (BITMAPINFO *) NULL; // Ptr to file's BITMAPINFO
  369. // Create memory DC.
  370. hdcMem = CreateCompatibleDC(NULL);
  371. if (!hdcMem) {
  372. SS_ERROR( "TEXTURE::DIBImageLoad : CreateCompatibleDC failure\n" );
  373. goto tkDIBLoadImage2_cleanup;
  374. }
  375. // Allocate BITMAPINFO structure
  376. pbmiRGB = (BITMAPINFO *)
  377. LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, sizeof(BITMAPINFO) );
  378. if (!pbmiRGB)
  379. {
  380. SS_ERROR( "TEXTURE::DIBImageLoad : memory failure\n" );
  381. goto tkDIBLoadImage2_cleanup;
  382. }
  383. pbmih = (BITMAPINFOHEADER *) &pbmiRGB->bmiHeader;
  384. pbmih->biSize = sizeof( BITMAPINFOHEADER );
  385. // Query bitmap values into pbmih
  386. if( ! GetDIBits( hdcMem, hbmRGB, 0, 0, NULL, pbmiRGB,
  387. DIB_RGB_COLORS ) )
  388. {
  389. SS_ERROR( "TEXTURE::DIBImageLoad : GetDIBits failure\n" );
  390. goto tkDIBLoadImage2_cleanup;
  391. }
  392. // Now pbmiRGB->bmiHeader should've been filled in with stuff
  393. pbmih->biPlanes = 1;
  394. pbmih->biBitCount = 24;
  395. pbmih->biCompression = BI_RGB;
  396. //mf:suppsedly this can be set to 0 for BI_RGB
  397. pbmih->biSizeImage = pbmih->biWidth
  398. * abs(pbmih->biHeight) * 3;
  399. pvBits = (PVOID) LocalAlloc(LMEM_FIXED, pbmih->biSizeImage);
  400. if (!pvBits)
  401. {
  402. SS_ERROR( "TEXTURE::DIBImageLoad : memory failure\n" );
  403. goto tkDIBLoadImage2_cleanup;
  404. }
  405. // Get the image bits
  406. if( ! GetDIBits( hdcMem, hbmRGB, 0, pbmih->biHeight, pvBits,
  407. pbmiRGB, DIB_RGB_COLORS ) )
  408. {
  409. SS_ERROR( "TEXTURE::DIBImageLoad : GetDIBits failure\n" );
  410. goto tkDIBLoadImage2_cleanup;
  411. }
  412. // Convert to TK image format (packed RGB format).
  413. // Allocate with malloc to be consistent with tkRGBImageLoad (i.e., app
  414. // can deallocate with free()).
  415. pjTKBits = PackTexImage( pbmih, (PBYTE) pvBits );
  416. if( !pjTKBits ) {
  417. SS_ERROR( "ConvertToOpenGLTexFormat : memory failure\n" );
  418. goto tkDIBLoadImage2_cleanup;
  419. }
  420. // Initialize the texture structure
  421. // If we get to here, we have suceeded!
  422. width = pbmih->biWidth;
  423. height = pbmih->biHeight;
  424. format = GL_BGR_EXT;
  425. components = 3;
  426. data = pjTKBits;
  427. pal_size = 0;
  428. pal = NULL;
  429. fSuccess = TRUE;
  430. // Cleanup objects.
  431. tkDIBLoadImage2_cleanup:
  432. {
  433. if( pvBits )
  434. LocalFree(pvBits);
  435. if (hdcMem)
  436. DeleteDC(hdcMem);
  437. if (pbmiRGB)
  438. LocalFree(pbmiRGB);
  439. }
  440. // Check for error.
  441. if (!fSuccess)
  442. {
  443. if (pjTKBits)
  444. free(pjTKBits);
  445. }
  446. return fSuccess;
  447. }
  448. /******************************Public*Routine******************************\
  449. *
  450. * bVerifyDIB
  451. *
  452. * Stripped down version of tkDIBImageLoadAW that verifies that a bitmap
  453. * file is valid and, if so, returns the bitmap dimensions.
  454. *
  455. * Returns:
  456. * TRUE if valid bitmap file; otherwise, FALSE.
  457. *
  458. \**************************************************************************/
  459. BOOL
  460. bVerifyDIB(LPTSTR pszFileName, ISIZE *pSize )
  461. {
  462. BOOL bRet = FALSE;
  463. BITMAPFILEHEADER *pbmf; // Ptr to file header
  464. BITMAPINFOHEADER *pbmihFile; // Ptr to file's info header (if it exists)
  465. BITMAPCOREHEADER *pbmchFile; // Ptr to file's core header (if it exists)
  466. // These need to be cleaned up when we exit:
  467. HANDLE hFile = INVALID_HANDLE_VALUE; // File handle
  468. HANDLE hMap = (HANDLE) NULL; // Mapping object handle
  469. PVOID pvFile = (PVOID) NULL; // Ptr to mapped file
  470. // Map the DIB file into memory.
  471. hFile = CreateFile((LPTSTR) pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
  472. if (hFile == INVALID_HANDLE_VALUE)
  473. goto bVerifyDIB_cleanup;
  474. hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
  475. if (!hMap)
  476. goto bVerifyDIB_cleanup;
  477. pvFile = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
  478. if (!pvFile)
  479. goto bVerifyDIB_cleanup;
  480. // Check the file header. If the BFT_BITMAP magic number is there,
  481. // then the file format is a BITMAPFILEHEADER followed immediately
  482. // by either a BITMAPINFOHEADER or a BITMAPCOREHEADER. The bitmap
  483. // bits, in this case, are located at the offset bfOffBits from the
  484. // BITMAPFILEHEADER.
  485. //
  486. // Otherwise, this may be a raw BITMAPINFOHEADER or BITMAPCOREHEADER
  487. // followed immediately with the color table and the bitmap bits.
  488. pbmf = (BITMAPFILEHEADER *) pvFile;
  489. if ( pbmf->bfType == BFT_BITMAP )
  490. pbmihFile = (BITMAPINFOHEADER *) ((PBYTE) pbmf + SIZEOF_BITMAPFILEHEADER);
  491. else
  492. pbmihFile = (BITMAPINFOHEADER *) pvFile;
  493. // Get the width and height from whatever header we have.
  494. //
  495. // We distinguish between BITMAPINFO and BITMAPCORE cases based upon
  496. // BITMAPINFOHEADER.biSize.
  497. // Note: need to use safe READDWORD macro because pbmihFile may
  498. // have only WORD alignment if it follows a BITMAPFILEHEADER.
  499. switch (READDWORD(&pbmihFile->biSize))
  500. {
  501. case sizeof(BITMAPINFOHEADER):
  502. if( pSize != NULL ) {
  503. pSize->width = READDWORD(&pbmihFile->biWidth);
  504. pSize->height = READDWORD(&pbmihFile->biHeight);
  505. }
  506. bRet = TRUE;
  507. break;
  508. case sizeof(BITMAPCOREHEADER):
  509. pbmchFile = (BITMAPCOREHEADER *) pbmihFile;
  510. // Convert BITMAPCOREHEADER to BITMAPINFOHEADER.
  511. if( pSize != NULL ) {
  512. pSize->width = (DWORD) pbmchFile->bcWidth;
  513. pSize->height = (DWORD) pbmchFile->bcHeight;
  514. }
  515. bRet = TRUE;
  516. break;
  517. default:
  518. break;
  519. }
  520. bVerifyDIB_cleanup:
  521. if (pvFile)
  522. UnmapViewOfFile(pvFile);
  523. if (hMap)
  524. CloseHandle(hMap);
  525. if (hFile != INVALID_HANDLE_VALUE)
  526. CloseHandle(hFile);
  527. return bRet;
  528. }