DIBFILE.CPP 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  1. /*
  2. ** Command & Conquer Red Alert(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. //*******************************************************************
  19. //
  20. // file.c
  21. //
  22. // Source file for Device-Independent Bitmap (DIB) API. Provides
  23. // the following functions:
  24. //
  25. // SaveDIB() - Saves the specified dib in a file
  26. // LoadDIB() - Loads a DIB from a file
  27. // DestroyDIB() - Deletes DIB when finished using it
  28. //
  29. // Development Team: Mark Bader
  30. // Patrick Schreiber
  31. // Garrett McAuliffe
  32. // Eric Flo
  33. // Tony Claflin
  34. //
  35. // Written by Microsoft Product Support Services, Developer Support.
  36. // COPYRIGHT:
  37. //
  38. // (C) Copyright Microsoft Corp. 1993. All rights reserved.
  39. //
  40. // You have a royalty-free right to use, modify, reproduce and
  41. // distribute the Sample Files (and/or any modified version) in
  42. // any way you find useful, provided that you agree that
  43. // Microsoft has no warranty obligations or liability for any
  44. // Sample Application Files which are modified.
  45. //
  46. //*******************************************************************
  47. #include <windows.h>
  48. #include <string.h>
  49. #include <stdio.h>
  50. #include <math.h>
  51. #include <io.h>
  52. #include <direct.h>
  53. #include <stdlib.h>
  54. #include "dibutil.h"
  55. #include "dibapi.h"
  56. //#include "WolDebug.h"
  57. /*
  58. * Dib Header Marker - used in writing DIBs to files
  59. */
  60. #define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B')
  61. /*********************************************************************
  62. *
  63. * Local Function Prototypes
  64. *
  65. *********************************************************************/
  66. HANDLE ReadDIBFile(int);
  67. BOOL MyRead(int, LPSTR, DWORD);
  68. BOOL SaveDIBFile(void);
  69. BOOL WriteDIB(LPSTR, HANDLE);
  70. DWORD PASCAL MyWrite(int, VOID FAR *, DWORD);
  71. /*************************************************************************
  72. *
  73. * LoadDIB()
  74. *
  75. * Loads the specified DIB from a file, allocates memory for it,
  76. * and reads the disk file into the memory.
  77. *
  78. *
  79. * Parameters:
  80. *
  81. * LPSTR lpFileName - specifies the file to load a DIB from
  82. *
  83. * Returns: A handle to a DIB, or NULL if unsuccessful.
  84. *
  85. * NOTE: The DIB API were not written to handle OS/2 DIBs; This
  86. * function will reject any file that is not a Windows DIB.
  87. *
  88. * History: Date Author Reason
  89. * 9/15/91 Mark Bader Based on DIBVIEW
  90. *
  91. *************************************************************************/
  92. HDIB FAR LoadDIB(LPSTR lpFileName)
  93. {
  94. HDIB hDIB;
  95. int hFile;
  96. OFSTRUCT ofs;
  97. /*
  98. * Set the cursor to a hourglass, in case the loading operation
  99. * takes more than a sec, the user will know what's going on.
  100. */
  101. SetCursor(LoadCursor(NULL, IDC_WAIT));
  102. if ((hFile = OpenFile(lpFileName, &ofs, OF_READ)) != -1)
  103. {
  104. hDIB = ReadDIBFile(hFile);
  105. _lclose(hFile);
  106. SetCursor(LoadCursor(NULL, IDC_ARROW));
  107. return hDIB;
  108. }
  109. else
  110. {
  111. // DIBError(ERR_FILENOTFOUND);
  112. SetCursor(LoadCursor(NULL, IDC_ARROW));
  113. return NULL;
  114. }
  115. }
  116. /*************************************************************************
  117. *
  118. * SaveDIB()
  119. *
  120. * Saves the specified DIB into the specified file name on disk. No
  121. * error checking is done, so if the file already exists, it will be
  122. * written over.
  123. *
  124. * Parameters:
  125. *
  126. * HDIB hDib - Handle to the dib to save
  127. *
  128. * LPSTR lpFileName - pointer to full pathname to save DIB under
  129. *
  130. * Return value: 0 if successful, or one of:
  131. * ERR_INVALIDHANDLE
  132. * ERR_OPEN
  133. * ERR_LOCK
  134. *
  135. * History:
  136. *
  137. * NOTE: The DIB API were not written to handle OS/2 DIBs, so this
  138. * function will not save a file if it is not a Windows DIB.
  139. *
  140. * History: Date Author Reason
  141. * 9/15/91 Mark Bader Taken from DIBVIEW (which was taken
  142. * from SHOWDIB)
  143. * 1/30/92 Mark Bader Fixed problem of writing too many
  144. * bytes to the file
  145. * 6/24/92 Mark Bader Added check for OS/2 DIB
  146. *
  147. *************************************************************************/
  148. WORD FAR SaveDIB(HDIB hDib, LPSTR lpFileName)
  149. {
  150. BITMAPFILEHEADER bmfHdr; // Header for Bitmap file
  151. LPBITMAPINFOHEADER lpBI; // Pointer to DIB info structure
  152. int fh; // file handle for opened file
  153. OFSTRUCT of; // OpenFile structure
  154. DWORD dwDIBSize;
  155. DWORD dwError; // Error return from MyWrite
  156. if (!hDib)
  157. return ERR_INVALIDHANDLE;
  158. fh = OpenFile(lpFileName, &of, OF_CREATE | OF_READWRITE);
  159. if (fh == -1)
  160. return ERR_OPEN;
  161. /*
  162. * Get a pointer to the DIB memory, the first of which contains
  163. * a BITMAPINFO structure
  164. */
  165. lpBI = (LPBITMAPINFOHEADER)GlobalLock(hDib);
  166. if (!lpBI)
  167. return ERR_LOCK;
  168. // Check to see if we're dealing with an OS/2 DIB. If so, don't
  169. // save it because our functions aren't written to deal with these
  170. // DIBs.
  171. if (lpBI->biSize != sizeof(BITMAPINFOHEADER))
  172. {
  173. GlobalUnlock(hDib);
  174. return ERR_NOT_DIB;
  175. }
  176. /*
  177. * Fill in the fields of the file header
  178. */
  179. /* Fill in file type (first 2 bytes must be "BM" for a bitmap) */
  180. bmfHdr.bfType = DIB_HEADER_MARKER; // "BM"
  181. // Calculating the size of the DIB is a bit tricky (if we want to
  182. // do it right). The easiest way to do this is to call GlobalSize()
  183. // on our global handle, but since the size of our global memory may have
  184. // been padded a few bytes, we may end up writing out a few too
  185. // many bytes to the file (which may cause problems with some apps,
  186. // like HC 3.0).
  187. //
  188. // So, instead let's calculate the size manually.
  189. //
  190. // To do this, find size of header plus size of color table. Since the
  191. // first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains
  192. // the size of the structure, let's use this.
  193. dwDIBSize = *(LPDWORD)lpBI + PaletteSize((LPSTR)lpBI); // Partial Calculation
  194. // Now calculate the size of the image
  195. if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4)) {
  196. // It's an RLE bitmap, we can't calculate size, so trust the
  197. // biSizeImage field
  198. dwDIBSize += lpBI->biSizeImage;
  199. }
  200. else {
  201. DWORD dwBmBitsSize; // Size of Bitmap Bits only
  202. // It's not RLE, so size is Width (DWORD aligned) * Height
  203. dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight;
  204. dwDIBSize += dwBmBitsSize;
  205. // Now, since we have calculated the correct size, why don't we
  206. // fill in the biSizeImage field (this will fix any .BMP files which
  207. // have this field incorrect).
  208. lpBI->biSizeImage = dwBmBitsSize;
  209. }
  210. // Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER)
  211. bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
  212. bmfHdr.bfReserved1 = 0;
  213. bmfHdr.bfReserved2 = 0;
  214. /*
  215. * Now, calculate the offset the actual bitmap bits will be in
  216. * the file -- It's the Bitmap file header plus the DIB header,
  217. * plus the size of the color table.
  218. */
  219. bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize +
  220. PaletteSize((LPSTR)lpBI);
  221. /* Write the file header */
  222. _lwrite(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
  223. /*
  224. * Write the DIB header and the bits -- use local version of
  225. * MyWrite, so we can write more than 32767 bytes of data
  226. */
  227. dwError = MyWrite(fh, (LPSTR)lpBI, dwDIBSize);
  228. GlobalUnlock(hDib);
  229. _lclose(fh);
  230. if (dwError == 0)
  231. return ERR_OPEN; // oops, something happened in the write
  232. else
  233. return 0; // Success code
  234. }
  235. /*************************************************************************
  236. *
  237. * DestroyDIB ()
  238. *
  239. * Purpose: Frees memory associated with a DIB
  240. *
  241. * Returns: Nothing
  242. *
  243. * History: Date Author Reason
  244. * 9/15/91 Mark Bader Created
  245. *
  246. *************************************************************************/
  247. WORD FAR DestroyDIB(HDIB hDib)
  248. {
  249. GlobalFree(hDib);
  250. return 0;
  251. }
  252. //************************************************************************
  253. //
  254. // Auxiliary Functions which the above procedures use
  255. //
  256. //************************************************************************
  257. /*************************************************************************
  258. *
  259. * Function: ReadDIBFile (int)
  260. *
  261. * Purpose: Reads in the specified DIB file into a global chunk of
  262. * memory.
  263. *
  264. * Returns: A handle to a dib (hDIB) if successful.
  265. * NULL if an error occurs.
  266. *
  267. * Comments: BITMAPFILEHEADER is stripped off of the DIB. Everything
  268. * from the end of the BITMAPFILEHEADER structure on is
  269. * returned in the global memory handle.
  270. *
  271. *
  272. * NOTE: The DIB API were not written to handle OS/2 DIBs, so this
  273. * function will reject any file that is not a Windows DIB.
  274. *
  275. * History: Date Author Reason
  276. * 9/15/91 Mark Bader Based on DIBVIEW
  277. * 6/25/92 Mark Bader Added check for OS/2 DIB
  278. * 7/21/92 Mark Bader Added code to deal with bfOffBits
  279. * field in BITMAPFILEHEADER
  280. * 9/11/92 Mark Bader Fixed Realloc Code to free original mem
  281. *
  282. *************************************************************************/
  283. HANDLE ReadDIBFile(int hFile)
  284. {
  285. BITMAPFILEHEADER bmfHeader;
  286. DWORD dwBitsSize;
  287. UINT nNumColors; // Number of colors in table
  288. HANDLE hDIB;
  289. HANDLE hDIBtmp; // Used for GlobalRealloc() //MPB
  290. LPBITMAPINFOHEADER lpbi;
  291. DWORD offBits;
  292. /*
  293. * get length of DIB in bytes for use when reading
  294. */
  295. dwBitsSize = filelength(hFile);
  296. // Allocate memory for header & color table. We'll enlarge this
  297. // memory as needed.
  298. hDIB = GlobalAlloc(GMEM_MOVEABLE,
  299. (DWORD)(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)));
  300. if (!hDIB) return NULL;
  301. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  302. if (!lpbi)
  303. {
  304. GlobalFree(hDIB);
  305. return NULL;
  306. }
  307. // read the BITMAPFILEHEADER from our file
  308. if (sizeof (BITMAPFILEHEADER) != _lread (hFile, (LPSTR)&bmfHeader, sizeof (BITMAPFILEHEADER)))
  309. goto ErrExit;
  310. if (bmfHeader.bfType != 0x4d42) /* 'BM' */
  311. goto ErrExit;
  312. // read the BITMAPINFOHEADER
  313. if (sizeof(BITMAPINFOHEADER) != _lread (hFile, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER)))
  314. goto ErrExit;
  315. // Check to see that it's a Windows DIB -- an OS/2 DIB would cause
  316. // strange problems with the rest of the DIB API since the fields
  317. // in the header are different and the color table entries are
  318. // smaller.
  319. //
  320. // If it's not a Windows DIB (e.g. if biSize is wrong), return NULL.
  321. if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  322. goto ErrExit;
  323. // Now determine the size of the color table and read it. Since the
  324. // bitmap bits are offset in the file by bfOffBits, we need to do some
  325. // special processing here to make sure the bits directly follow
  326. // the color table (because that's the format we are susposed to pass
  327. // back)
  328. nNumColors = (UINT)lpbi->biClrUsed;
  329. if (!nNumColors)
  330. {
  331. // no color table for 24-bit, default size otherwise
  332. if (lpbi->biBitCount != 24)
  333. nNumColors = 1 << lpbi->biBitCount; /* standard size table */
  334. }
  335. // fill in some default values if they are zero
  336. if (lpbi->biClrUsed == 0)
  337. lpbi->biClrUsed = nNumColors;
  338. if (lpbi->biSizeImage == 0)
  339. {
  340. lpbi->biSizeImage = ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 31) & ~31) >> 3)
  341. * lpbi->biHeight;
  342. }
  343. // get a proper-sized buffer for header, color table and bits
  344. GlobalUnlock(hDIB);
  345. hDIBtmp = GlobalReAlloc(hDIB, lpbi->biSize +
  346. nNumColors * sizeof(RGBQUAD) +
  347. lpbi->biSizeImage, 0);
  348. if (!hDIBtmp) // can't resize buffer for loading
  349. goto ErrExitNoUnlock; //MPB
  350. else
  351. hDIB = hDIBtmp;
  352. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  353. // read the color table
  354. _lread (hFile, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBQUAD));
  355. // offset to the bits from start of DIB header
  356. offBits = lpbi->biSize + nNumColors * sizeof(RGBQUAD);
  357. // If the bfOffBits field is non-zero, then the bits might *not* be
  358. // directly following the color table in the file. Use the value in
  359. // bfOffBits to seek the bits.
  360. if (bmfHeader.bfOffBits != 0L)
  361. _llseek(hFile, bmfHeader.bfOffBits, SEEK_SET);
  362. if (MyRead(hFile, (LPSTR)lpbi + offBits, lpbi->biSizeImage))
  363. goto OKExit;
  364. ErrExit:
  365. GlobalUnlock(hDIB);
  366. ErrExitNoUnlock:
  367. GlobalFree(hDIB);
  368. return NULL;
  369. OKExit:
  370. GlobalUnlock(hDIB);
  371. return hDIB;
  372. }
  373. /*************************************************************************
  374. Function: MyRead (int, LPSTR, DWORD)
  375. Purpose: Routine to read files greater than 64K in size.
  376. Returns: TRUE if successful.
  377. FALSE if an error occurs.
  378. History: Date Author Reason
  379. 9/15/91 Mark Bader Based on DIBVIEW
  380. *************************************************************************/
  381. BOOL MyRead(int hFile, LPSTR lpBuffer, DWORD dwSize)
  382. {
  383. char huge *lpInBuf = (char huge *)lpBuffer;
  384. int nBytes;
  385. /*
  386. * Read in the data in 32767 byte chunks (or a smaller amount if it's
  387. * the last chunk of data read)
  388. */
  389. while (dwSize)
  390. {
  391. nBytes = (int)(dwSize > (DWORD)32767 ? 32767 : LOWORD (dwSize));
  392. if (_lread(hFile, (LPSTR)lpInBuf, nBytes) != (WORD)nBytes)
  393. return FALSE;
  394. dwSize -= nBytes;
  395. lpInBuf += nBytes;
  396. }
  397. return TRUE;
  398. }
  399. /****************************************************************************
  400. FUNCTION : MyWrite(int fh, VOID FAR *pv, DWORD ul)
  401. PURPOSE : Writes data in steps of 32k till all the data is written.
  402. Normal _lwrite uses a WORD as 3rd parameter, so it is
  403. limited to 32767 bytes, but this procedure is not.
  404. RETURNS : 0 - If write did not proceed correctly.
  405. number of bytes written otherwise.
  406. History: Date Author Reason
  407. 9/15/91 Mark Bader Based on DIBVIEW
  408. ****************************************************************************/
  409. DWORD PASCAL MyWrite(int iFileHandle, VOID FAR *lpBuffer, DWORD dwBytes)
  410. {
  411. DWORD dwBytesTmp = dwBytes; // Save # of bytes for return value
  412. BYTE huge *hpBuffer = (BYTE huge *)lpBuffer; // make a huge pointer to the data
  413. /*
  414. * Write out the data in 32767 byte chunks.
  415. */
  416. while (dwBytes > 32767)
  417. {
  418. if (_lwrite(iFileHandle, (LPSTR)hpBuffer, (WORD)32767) != 32767)
  419. return 0;
  420. dwBytes -= 32767;
  421. hpBuffer += 32767;
  422. }
  423. /* Write out the last chunk (which is < 32767 bytes) */
  424. if (_lwrite(iFileHandle, (LPSTR)hpBuffer, (WORD)dwBytes) != (WORD)dwBytes)
  425. return 0;
  426. return dwBytesTmp;
  427. }
  428. // ajw added
  429. // Added to allow "loading" from a location in memory.
  430. // A modification of ReadDIBFile(), above.
  431. //***********************************************************************************************
  432. HDIB LoadDIB_FromMemory( const unsigned char* pData, DWORD dwBitsSize )
  433. {
  434. BITMAPFILEHEADER bmfHeader;
  435. UINT nNumColors; // Number of colors in table
  436. HANDLE hDIB;
  437. HANDLE hDIBtmp; // Used for GlobalRealloc() //MPB
  438. LPBITMAPINFOHEADER lpbi;
  439. DWORD offBits;
  440. const unsigned char* const pDataStart = pData;
  441. const unsigned char* pDataEnd = pData + dwBitsSize; // One char past end of "file".
  442. // Allocate memory for header & color table. We'll enlarge this
  443. // memory as needed.
  444. // debugprint( "LoadDIB_FromMemory, GlobalAlloc\n" );
  445. hDIB = GlobalAlloc(GMEM_MOVEABLE, (DWORD)(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)));
  446. // debugprint( "hDIB from GlobalALloc is %i\n", hDIB );
  447. if (!hDIB)
  448. {
  449. // debugprint( "LoadDIB_FromMemory error: failed alloc\n" );
  450. return NULL;
  451. }
  452. // debugprint( "LoadDIB_FromMemory, lpbi Lock\n" );
  453. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  454. // debugprint( "lpbi is %i\n", lpbi );
  455. if (!lpbi)
  456. {
  457. // debugprint( "LoadDIB_FromMemory error: failed lock\n" );
  458. GlobalFree(hDIB);
  459. return NULL;
  460. }
  461. // read the BITMAPFILEHEADER from our file
  462. // if (sizeof (BITMAPFILEHEADER) != _lread (hFile, (LPSTR)&bmfHeader, sizeof (BITMAPFILEHEADER)))
  463. // goto ErrExit;
  464. if( pData + sizeof( BITMAPFILEHEADER ) >= pDataEnd )
  465. {
  466. // debugprint( "LoadDIB_FromMemory error: bad size\n" );
  467. goto ErrExit;
  468. }
  469. // debugprint( "LoadDIB_FromMemory, memcpy BITMAPFILEHEADER %i bytes\n", sizeof( BITMAPFILEHEADER ) );
  470. memcpy( &bmfHeader, pData, sizeof( BITMAPFILEHEADER ) );
  471. pData += sizeof( BITMAPFILEHEADER );
  472. if (bmfHeader.bfType != 0x4d42) /* 'BM' */
  473. {
  474. // debugprint( "LoadDIB_FromMemory error: no BM\n" );
  475. goto ErrExit;
  476. }
  477. // read the BITMAPINFOHEADER
  478. // if (sizeof(BITMAPINFOHEADER) != _lread (hFile, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER)))
  479. // goto ErrExit;
  480. if( pData + sizeof( BITMAPINFOHEADER ) >= pDataEnd )
  481. {
  482. // debugprint( "LoadDIB_FromMemory error: bad size 2\n" );
  483. goto ErrExit;
  484. }
  485. // debugprint( "LoadDIB_FromMemory, memcpy BITMAPINFOHEADER %i bytes\n", sizeof( BITMAPINFOHEADER ) );
  486. memcpy( lpbi, pData, sizeof( BITMAPINFOHEADER ) );
  487. pData += sizeof( BITMAPINFOHEADER );
  488. // Check to see that it's a Windows DIB -- an OS/2 DIB would cause
  489. // strange problems with the rest of the DIB API since the fields
  490. // in the header are different and the color table entries are
  491. // smaller.
  492. //
  493. // If it's not a Windows DIB (e.g. if biSize is wrong), return NULL.
  494. if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  495. {
  496. // debugprint( "LoadDIB_FromMemory error: lpbi->biSize bad\n" );
  497. goto ErrExit;
  498. }
  499. if( lpbi->biCompression != BI_RGB )
  500. {
  501. // debugprint( "LoadDIB_FromMemory error: Image is compressed\n" );
  502. goto ErrExit;
  503. }
  504. // Now determine the size of the color table and read it. Since the
  505. // bitmap bits are offset in the file by bfOffBits, we need to do some
  506. // special processing here to make sure the bits directly follow
  507. // the color table (because that's the format we are susposed to pass
  508. // back)
  509. nNumColors = (UINT)lpbi->biClrUsed;
  510. if (!nNumColors)
  511. {
  512. // no color table for 24-bit, default size otherwise
  513. if (lpbi->biBitCount != 24)
  514. nNumColors = 1 << lpbi->biBitCount; /* standard size table */
  515. }
  516. // fill in some default values if they are zero
  517. if (lpbi->biClrUsed == 0)
  518. lpbi->biClrUsed = nNumColors;
  519. // debugprint( "biSizeImage is %i. I would say it was %i, because the bpp is %i.\n", lpbi->biSizeImage, ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 31) & ~31) >> 3) * lpbi->biHeight, lpbi->biBitCount );
  520. if (lpbi->biSizeImage == 0)
  521. {
  522. lpbi->biSizeImage = ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 31) & ~31) >> 3) * lpbi->biHeight;
  523. }
  524. // get a proper-sized buffer for header, color table and bits
  525. GlobalUnlock(hDIB);
  526. // debugprint( "LoadDIB_FromMemory, GlobalReAlloc: lpbi->biSize=%i, nNumColors=%i, lpbi->biSizeImage=%i\n", lpbi->biSize, nNumColors,lpbi->biSizeImage );
  527. hDIBtmp = GlobalReAlloc(hDIB, lpbi->biSize + nNumColors * sizeof(RGBQUAD) + lpbi->biSizeImage, 0);
  528. if (!hDIBtmp) // can't resize buffer for loading
  529. {
  530. // debugprint( "LoadDIB_FromMemory error: realloc failed\n" );
  531. goto ErrExitNoUnlock; //MPB
  532. }
  533. else
  534. hDIB = hDIBtmp;
  535. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  536. // read the color table
  537. // _lread (hFile, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBQUAD));
  538. // debugprint( "LoadDIB_FromMemory, memcpy color table %i colors, so %i bytes\n", nNumColors, nNumColors * sizeof(RGBQUAD) );
  539. memcpy( (LPSTR)(lpbi) + lpbi->biSize, pData, nNumColors * sizeof(RGBQUAD) );
  540. pData += nNumColors * sizeof(RGBQUAD);
  541. // offset to the bits from start of DIB header
  542. offBits = lpbi->biSize + nNumColors * sizeof(RGBQUAD);
  543. // If the bfOffBits field is non-zero, then the bits might *not* be
  544. // directly following the color table in the file. Use the value in
  545. // bfOffBits to seek the bits.
  546. if (bmfHeader.bfOffBits != 0L)
  547. // _llseek(hFile, bmfHeader.bfOffBits, SEEK_SET);
  548. pData = pDataStart + bmfHeader.bfOffBits;
  549. // debugprint( "bmfHeader.bfOffBits is %i\n", bmfHeader.bfOffBits );
  550. // if (MyRead(hFile, (LPSTR)lpbi + offBits, lpbi->biSizeImage))
  551. // goto OKExit;
  552. // debugprint( "Checking that pData(%i) + biSizeImage(%i), which is %i, is equal to pDataEnd(%i)\n",
  553. // pData, lpbi->biSizeImage, pData + lpbi->biSizeImage, pDataEnd );
  554. // if( pData + lpbi->biSizeImage != pDataEnd ) condition relaxed
  555. // {
  556. // debugprint( "LoadDIB_FromMemory error: bad size 3\n" );
  557. // goto ErrExit;
  558. // }
  559. // debugprint( "LoadDIB_FromMemory, memcpy the bits, %i bytes. Image is w %i, h.%i\n",
  560. // lpbi->biSizeImage, lpbi->biWidth, lpbi->biHeight );
  561. // debugprint( "Writing to lpbi (%i) + offBits (%i)\n", lpbi, offBits );
  562. memcpy( (LPSTR)lpbi + offBits, pData, lpbi->biSizeImage );
  563. // pData += lpbi->biSizeImage;
  564. // if( pData != pDataEnd ) // Should end up one byte past end of data. - condition relaxed
  565. // debugprint( "LoadDIB_FromMemory: ERROR! Ended up at %i instead of %i\n", pData, pDataEnd );
  566. goto OKExit;
  567. ErrExit:
  568. GlobalUnlock(hDIB);
  569. ErrExitNoUnlock:
  570. GlobalFree(hDIB);
  571. // debugprint( "LoadDIB_FromMemory Error!\n" );
  572. return NULL;
  573. OKExit:
  574. GlobalUnlock(hDIB);
  575. return hDIB;
  576. }