DIBFILE.CPP 22 KB

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