Initial Source Code commit
Initial commit of original Tiberian Dawn and Red Alert source code converted to build as DLLs, and compatible with the release version of Command & Conquer Remastered.
This commit is contained in:
parent
ea8ecc76fa
commit
03416d24e1
1038 changed files with 629779 additions and 0 deletions
702
REDALERT/DIBFILE.CPP
Normal file
702
REDALERT/DIBFILE.CPP
Normal file
|
@ -0,0 +1,702 @@
|
|||
//
|
||||
// Copyright 2020 Electronic Arts Inc.
|
||||
//
|
||||
// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
|
||||
// software: you can redistribute it and/or modify it under the terms of
|
||||
// the GNU General Public License as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
|
||||
// in the hope that it will be useful, but with permitted additional restrictions
|
||||
// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
|
||||
// distributed with this program. You should have received a copy of the
|
||||
// GNU General Public License along with permitted additional restrictions
|
||||
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
|
||||
|
||||
//*******************************************************************
|
||||
//
|
||||
// file.c
|
||||
//
|
||||
// Source file for Device-Independent Bitmap (DIB) API. Provides
|
||||
// the following functions:
|
||||
//
|
||||
// SaveDIB() - Saves the specified dib in a file
|
||||
// LoadDIB() - Loads a DIB from a file
|
||||
// DestroyDIB() - Deletes DIB when finished using it
|
||||
//
|
||||
// Development Team: Mark Bader
|
||||
// Patrick Schreiber
|
||||
// Garrett McAuliffe
|
||||
// Eric Flo
|
||||
// Tony Claflin
|
||||
//
|
||||
// Written by Microsoft Product Support Services, Developer Support.
|
||||
// COPYRIGHT:
|
||||
//
|
||||
// (C) Copyright Microsoft Corp. 1993. All rights reserved.
|
||||
//
|
||||
// You have a royalty-free right to use, modify, reproduce and
|
||||
// distribute the Sample Files (and/or any modified version) in
|
||||
// any way you find useful, provided that you agree that
|
||||
// Microsoft has no warranty obligations or liability for any
|
||||
// Sample Application Files which are modified.
|
||||
//
|
||||
//*******************************************************************
|
||||
#if (0) // ST - 5/8/2019
|
||||
|
||||
#include <windows.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
#include <stdlib.h>
|
||||
#include "dibutil.h"
|
||||
#include "dibapi.h"
|
||||
|
||||
//#include "WolDebug.h"
|
||||
|
||||
/*
|
||||
* Dib Header Marker - used in writing DIBs to files
|
||||
*/
|
||||
#define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B')
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Local Function Prototypes
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
|
||||
HANDLE ReadDIBFile(int);
|
||||
BOOL MyRead(int, LPSTR, DWORD);
|
||||
BOOL SaveDIBFile(void);
|
||||
BOOL WriteDIB(LPSTR, HANDLE);
|
||||
DWORD PASCAL MyWrite(int, VOID FAR *, DWORD);
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* LoadDIB()
|
||||
*
|
||||
* Loads the specified DIB from a file, allocates memory for it,
|
||||
* and reads the disk file into the memory.
|
||||
*
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* LPSTR lpFileName - specifies the file to load a DIB from
|
||||
*
|
||||
* Returns: A handle to a DIB, or NULL if unsuccessful.
|
||||
*
|
||||
* NOTE: The DIB API were not written to handle OS/2 DIBs; This
|
||||
* function will reject any file that is not a Windows DIB.
|
||||
*
|
||||
* History: Date Author Reason
|
||||
* 9/15/91 Mark Bader Based on DIBVIEW
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
HDIB FAR LoadDIB(LPSTR lpFileName)
|
||||
{
|
||||
HDIB hDIB;
|
||||
int hFile;
|
||||
OFSTRUCT ofs;
|
||||
|
||||
/*
|
||||
* Set the cursor to a hourglass, in case the loading operation
|
||||
* takes more than a sec, the user will know what's going on.
|
||||
*/
|
||||
|
||||
SetCursor(LoadCursor(NULL, IDC_WAIT));
|
||||
if ((hFile = OpenFile(lpFileName, &ofs, OF_READ)) != -1)
|
||||
{
|
||||
hDIB = ReadDIBFile(hFile);
|
||||
_lclose(hFile);
|
||||
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
||||
return hDIB;
|
||||
}
|
||||
else
|
||||
{
|
||||
// DIBError(ERR_FILENOTFOUND);
|
||||
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* SaveDIB()
|
||||
*
|
||||
* Saves the specified DIB into the specified file name on disk. No
|
||||
* error checking is done, so if the file already exists, it will be
|
||||
* written over.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* HDIB hDib - Handle to the dib to save
|
||||
*
|
||||
* LPSTR lpFileName - pointer to full pathname to save DIB under
|
||||
*
|
||||
* Return value: 0 if successful, or one of:
|
||||
* ERR_INVALIDHANDLE
|
||||
* ERR_OPEN
|
||||
* ERR_LOCK
|
||||
*
|
||||
* History:
|
||||
*
|
||||
* NOTE: The DIB API were not written to handle OS/2 DIBs, so this
|
||||
* function will not save a file if it is not a Windows DIB.
|
||||
*
|
||||
* History: Date Author Reason
|
||||
* 9/15/91 Mark Bader Taken from DIBVIEW (which was taken
|
||||
* from SHOWDIB)
|
||||
* 1/30/92 Mark Bader Fixed problem of writing too many
|
||||
* bytes to the file
|
||||
* 6/24/92 Mark Bader Added check for OS/2 DIB
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
WORD FAR SaveDIB(HDIB hDib, LPSTR lpFileName)
|
||||
{
|
||||
BITMAPFILEHEADER bmfHdr; // Header for Bitmap file
|
||||
LPBITMAPINFOHEADER lpBI; // Pointer to DIB info structure
|
||||
int fh; // file handle for opened file
|
||||
OFSTRUCT of; // OpenFile structure
|
||||
DWORD dwDIBSize;
|
||||
DWORD dwError; // Error return from MyWrite
|
||||
|
||||
if (!hDib)
|
||||
return ERR_INVALIDHANDLE;
|
||||
fh = OpenFile(lpFileName, &of, OF_CREATE | OF_READWRITE);
|
||||
if (fh == -1)
|
||||
return ERR_OPEN;
|
||||
|
||||
/*
|
||||
* Get a pointer to the DIB memory, the first of which contains
|
||||
* a BITMAPINFO structure
|
||||
*/
|
||||
lpBI = (LPBITMAPINFOHEADER)GlobalLock(hDib);
|
||||
if (!lpBI)
|
||||
return ERR_LOCK;
|
||||
|
||||
// Check to see if we're dealing with an OS/2 DIB. If so, don't
|
||||
// save it because our functions aren't written to deal with these
|
||||
// DIBs.
|
||||
|
||||
if (lpBI->biSize != sizeof(BITMAPINFOHEADER))
|
||||
{
|
||||
GlobalUnlock(hDib);
|
||||
return ERR_NOT_DIB;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in the fields of the file header
|
||||
*/
|
||||
|
||||
/* Fill in file type (first 2 bytes must be "BM" for a bitmap) */
|
||||
bmfHdr.bfType = DIB_HEADER_MARKER; // "BM"
|
||||
|
||||
// Calculating the size of the DIB is a bit tricky (if we want to
|
||||
// do it right). The easiest way to do this is to call GlobalSize()
|
||||
// on our global handle, but since the size of our global memory may have
|
||||
// been padded a few bytes, we may end up writing out a few too
|
||||
// many bytes to the file (which may cause problems with some apps,
|
||||
// like HC 3.0).
|
||||
//
|
||||
// So, instead let's calculate the size manually.
|
||||
//
|
||||
// To do this, find size of header plus size of color table. Since the
|
||||
// first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains
|
||||
// the size of the structure, let's use this.
|
||||
|
||||
dwDIBSize = *(LPDWORD)lpBI + PaletteSize((LPSTR)lpBI); // Partial Calculation
|
||||
|
||||
// Now calculate the size of the image
|
||||
|
||||
if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4)) {
|
||||
|
||||
// It's an RLE bitmap, we can't calculate size, so trust the
|
||||
// biSizeImage field
|
||||
|
||||
dwDIBSize += lpBI->biSizeImage;
|
||||
}
|
||||
else {
|
||||
DWORD dwBmBitsSize; // Size of Bitmap Bits only
|
||||
|
||||
// It's not RLE, so size is Width (DWORD aligned) * Height
|
||||
|
||||
dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight;
|
||||
|
||||
dwDIBSize += dwBmBitsSize;
|
||||
|
||||
// Now, since we have calculated the correct size, why don't we
|
||||
// fill in the biSizeImage field (this will fix any .BMP files which
|
||||
// have this field incorrect).
|
||||
|
||||
lpBI->biSizeImage = dwBmBitsSize;
|
||||
}
|
||||
|
||||
|
||||
// Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER)
|
||||
|
||||
bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
|
||||
bmfHdr.bfReserved1 = 0;
|
||||
bmfHdr.bfReserved2 = 0;
|
||||
|
||||
/*
|
||||
* Now, calculate the offset the actual bitmap bits will be in
|
||||
* the file -- It's the Bitmap file header plus the DIB header,
|
||||
* plus the size of the color table.
|
||||
*/
|
||||
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize +
|
||||
PaletteSize((LPSTR)lpBI);
|
||||
|
||||
/* Write the file header */
|
||||
_lwrite(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
|
||||
|
||||
/*
|
||||
* Write the DIB header and the bits -- use local version of
|
||||
* MyWrite, so we can write more than 32767 bytes of data
|
||||
*/
|
||||
dwError = MyWrite(fh, (LPSTR)lpBI, dwDIBSize);
|
||||
GlobalUnlock(hDib);
|
||||
_lclose(fh);
|
||||
|
||||
if (dwError == 0)
|
||||
return ERR_OPEN; // oops, something happened in the write
|
||||
else
|
||||
return 0; // Success code
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* DestroyDIB ()
|
||||
*
|
||||
* Purpose: Frees memory associated with a DIB
|
||||
*
|
||||
* Returns: Nothing
|
||||
*
|
||||
* History: Date Author Reason
|
||||
* 9/15/91 Mark Bader Created
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
WORD FAR DestroyDIB(HDIB hDib)
|
||||
{
|
||||
GlobalFree(hDib);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************
|
||||
//
|
||||
// Auxiliary Functions which the above procedures use
|
||||
//
|
||||
//************************************************************************
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: ReadDIBFile (int)
|
||||
*
|
||||
* Purpose: Reads in the specified DIB file into a global chunk of
|
||||
* memory.
|
||||
*
|
||||
* Returns: A handle to a dib (hDIB) if successful.
|
||||
* NULL if an error occurs.
|
||||
*
|
||||
* Comments: BITMAPFILEHEADER is stripped off of the DIB. Everything
|
||||
* from the end of the BITMAPFILEHEADER structure on is
|
||||
* returned in the global memory handle.
|
||||
*
|
||||
*
|
||||
* NOTE: The DIB API were not written to handle OS/2 DIBs, so this
|
||||
* function will reject any file that is not a Windows DIB.
|
||||
*
|
||||
* History: Date Author Reason
|
||||
* 9/15/91 Mark Bader Based on DIBVIEW
|
||||
* 6/25/92 Mark Bader Added check for OS/2 DIB
|
||||
* 7/21/92 Mark Bader Added code to deal with bfOffBits
|
||||
* field in BITMAPFILEHEADER
|
||||
* 9/11/92 Mark Bader Fixed Realloc Code to free original mem
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
HANDLE ReadDIBFile(int hFile)
|
||||
{
|
||||
BITMAPFILEHEADER bmfHeader;
|
||||
DWORD dwBitsSize;
|
||||
UINT nNumColors; // Number of colors in table
|
||||
HANDLE hDIB;
|
||||
HANDLE hDIBtmp; // Used for GlobalRealloc() //MPB
|
||||
LPBITMAPINFOHEADER lpbi;
|
||||
DWORD offBits;
|
||||
|
||||
/*
|
||||
* get length of DIB in bytes for use when reading
|
||||
*/
|
||||
|
||||
dwBitsSize = filelength(hFile);
|
||||
|
||||
// Allocate memory for header & color table. We'll enlarge this
|
||||
// memory as needed.
|
||||
|
||||
hDIB = GlobalAlloc(GMEM_MOVEABLE,
|
||||
(DWORD)(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)));
|
||||
|
||||
if (!hDIB) return NULL;
|
||||
|
||||
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
|
||||
if (!lpbi)
|
||||
{
|
||||
GlobalFree(hDIB);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// read the BITMAPFILEHEADER from our file
|
||||
|
||||
if (sizeof (BITMAPFILEHEADER) != _lread (hFile, (LPSTR)&bmfHeader, sizeof (BITMAPFILEHEADER)))
|
||||
goto ErrExit;
|
||||
|
||||
if (bmfHeader.bfType != 0x4d42) /* 'BM' */
|
||||
goto ErrExit;
|
||||
|
||||
// read the BITMAPINFOHEADER
|
||||
|
||||
if (sizeof(BITMAPINFOHEADER) != _lread (hFile, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER)))
|
||||
goto ErrExit;
|
||||
|
||||
// Check to see that it's a Windows DIB -- an OS/2 DIB would cause
|
||||
// strange problems with the rest of the DIB API since the fields
|
||||
// in the header are different and the color table entries are
|
||||
// smaller.
|
||||
//
|
||||
// If it's not a Windows DIB (e.g. if biSize is wrong), return NULL.
|
||||
|
||||
if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
|
||||
goto ErrExit;
|
||||
|
||||
// Now determine the size of the color table and read it. Since the
|
||||
// bitmap bits are offset in the file by bfOffBits, we need to do some
|
||||
// special processing here to make sure the bits directly follow
|
||||
// the color table (because that's the format we are susposed to pass
|
||||
// back)
|
||||
nNumColors = (UINT)lpbi->biClrUsed;
|
||||
if (!nNumColors)
|
||||
{
|
||||
// no color table for 24-bit, default size otherwise
|
||||
if (lpbi->biBitCount != 24)
|
||||
nNumColors = 1 << lpbi->biBitCount; /* standard size table */
|
||||
}
|
||||
|
||||
// fill in some default values if they are zero
|
||||
if (lpbi->biClrUsed == 0)
|
||||
lpbi->biClrUsed = nNumColors;
|
||||
|
||||
if (lpbi->biSizeImage == 0)
|
||||
{
|
||||
lpbi->biSizeImage = ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 31) & ~31) >> 3)
|
||||
* lpbi->biHeight;
|
||||
}
|
||||
|
||||
// get a proper-sized buffer for header, color table and bits
|
||||
GlobalUnlock(hDIB);
|
||||
hDIBtmp = GlobalReAlloc(hDIB, lpbi->biSize +
|
||||
nNumColors * sizeof(RGBQUAD) +
|
||||
lpbi->biSizeImage, 0);
|
||||
|
||||
if (!hDIBtmp) // can't resize buffer for loading
|
||||
goto ErrExitNoUnlock; //MPB
|
||||
else
|
||||
hDIB = hDIBtmp;
|
||||
|
||||
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
|
||||
|
||||
// read the color table
|
||||
_lread (hFile, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBQUAD));
|
||||
|
||||
// offset to the bits from start of DIB header
|
||||
offBits = lpbi->biSize + nNumColors * sizeof(RGBQUAD);
|
||||
|
||||
// If the bfOffBits field is non-zero, then the bits might *not* be
|
||||
// directly following the color table in the file. Use the value in
|
||||
// bfOffBits to seek the bits.
|
||||
|
||||
if (bmfHeader.bfOffBits != 0L)
|
||||
_llseek(hFile, bmfHeader.bfOffBits, SEEK_SET);
|
||||
|
||||
if (MyRead(hFile, (LPSTR)lpbi + offBits, lpbi->biSizeImage))
|
||||
goto OKExit;
|
||||
|
||||
|
||||
ErrExit:
|
||||
GlobalUnlock(hDIB);
|
||||
ErrExitNoUnlock:
|
||||
GlobalFree(hDIB);
|
||||
return NULL;
|
||||
|
||||
OKExit:
|
||||
GlobalUnlock(hDIB);
|
||||
return hDIB;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
||||
Function: MyRead (int, LPSTR, DWORD)
|
||||
|
||||
Purpose: Routine to read files greater than 64K in size.
|
||||
|
||||
Returns: TRUE if successful.
|
||||
FALSE if an error occurs.
|
||||
|
||||
|
||||
History: Date Author Reason
|
||||
9/15/91 Mark Bader Based on DIBVIEW
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
BOOL MyRead(int hFile, LPSTR lpBuffer, DWORD dwSize)
|
||||
{
|
||||
char huge *lpInBuf = (char huge *)lpBuffer;
|
||||
int nBytes;
|
||||
|
||||
/*
|
||||
* Read in the data in 32767 byte chunks (or a smaller amount if it's
|
||||
* the last chunk of data read)
|
||||
*/
|
||||
|
||||
while (dwSize)
|
||||
{
|
||||
nBytes = (int)(dwSize > (DWORD)32767 ? 32767 : LOWORD (dwSize));
|
||||
if (_lread(hFile, (LPSTR)lpInBuf, nBytes) != (WORD)nBytes)
|
||||
return FALSE;
|
||||
dwSize -= nBytes;
|
||||
lpInBuf += nBytes;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
FUNCTION : MyWrite(int fh, VOID FAR *pv, DWORD ul)
|
||||
|
||||
PURPOSE : Writes data in steps of 32k till all the data is written.
|
||||
Normal _lwrite uses a WORD as 3rd parameter, so it is
|
||||
limited to 32767 bytes, but this procedure is not.
|
||||
|
||||
RETURNS : 0 - If write did not proceed correctly.
|
||||
number of bytes written otherwise.
|
||||
|
||||
History: Date Author Reason
|
||||
9/15/91 Mark Bader Based on DIBVIEW
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
DWORD PASCAL MyWrite(int iFileHandle, VOID FAR *lpBuffer, DWORD dwBytes)
|
||||
{
|
||||
DWORD dwBytesTmp = dwBytes; // Save # of bytes for return value
|
||||
BYTE huge *hpBuffer = (BYTE huge *)lpBuffer; // make a huge pointer to the data
|
||||
|
||||
/*
|
||||
* Write out the data in 32767 byte chunks.
|
||||
*/
|
||||
|
||||
while (dwBytes > 32767)
|
||||
{
|
||||
if (_lwrite(iFileHandle, (LPSTR)hpBuffer, (WORD)32767) != 32767)
|
||||
return 0;
|
||||
dwBytes -= 32767;
|
||||
hpBuffer += 32767;
|
||||
}
|
||||
|
||||
/* Write out the last chunk (which is < 32767 bytes) */
|
||||
if (_lwrite(iFileHandle, (LPSTR)hpBuffer, (WORD)dwBytes) != (WORD)dwBytes)
|
||||
return 0;
|
||||
return dwBytesTmp;
|
||||
}
|
||||
|
||||
// ajw added
|
||||
// Added to allow "loading" from a location in memory.
|
||||
// A modification of ReadDIBFile(), above.
|
||||
//***********************************************************************************************
|
||||
HDIB LoadDIB_FromMemory( const unsigned char* pData, DWORD dwBitsSize )
|
||||
{
|
||||
BITMAPFILEHEADER bmfHeader;
|
||||
UINT nNumColors; // Number of colors in table
|
||||
HANDLE hDIB;
|
||||
HANDLE hDIBtmp; // Used for GlobalRealloc() //MPB
|
||||
LPBITMAPINFOHEADER lpbi;
|
||||
DWORD offBits;
|
||||
|
||||
const unsigned char* const pDataStart = pData;
|
||||
const unsigned char* pDataEnd = pData + dwBitsSize; // One char past end of "file".
|
||||
|
||||
// Allocate memory for header & color table. We'll enlarge this
|
||||
// memory as needed.
|
||||
|
||||
// debugprint( "LoadDIB_FromMemory, GlobalAlloc\n" );
|
||||
hDIB = GlobalAlloc(GMEM_MOVEABLE, (DWORD)(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)));
|
||||
// debugprint( "hDIB from GlobalALloc is %i\n", hDIB );
|
||||
|
||||
if (!hDIB)
|
||||
{
|
||||
// debugprint( "LoadDIB_FromMemory error: failed alloc\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// debugprint( "LoadDIB_FromMemory, lpbi Lock\n" );
|
||||
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
|
||||
// debugprint( "lpbi is %i\n", lpbi );
|
||||
if (!lpbi)
|
||||
{
|
||||
// debugprint( "LoadDIB_FromMemory error: failed lock\n" );
|
||||
GlobalFree(hDIB);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// read the BITMAPFILEHEADER from our file
|
||||
// if (sizeof (BITMAPFILEHEADER) != _lread (hFile, (LPSTR)&bmfHeader, sizeof (BITMAPFILEHEADER)))
|
||||
// goto ErrExit;
|
||||
if( pData + sizeof( BITMAPFILEHEADER ) >= pDataEnd )
|
||||
{
|
||||
// debugprint( "LoadDIB_FromMemory error: bad size\n" );
|
||||
goto ErrExit;
|
||||
}
|
||||
// debugprint( "LoadDIB_FromMemory, memcpy BITMAPFILEHEADER %i bytes\n", sizeof( BITMAPFILEHEADER ) );
|
||||
memcpy( &bmfHeader, pData, sizeof( BITMAPFILEHEADER ) );
|
||||
pData += sizeof( BITMAPFILEHEADER );
|
||||
|
||||
if (bmfHeader.bfType != 0x4d42) /* 'BM' */
|
||||
{
|
||||
// debugprint( "LoadDIB_FromMemory error: no BM\n" );
|
||||
goto ErrExit;
|
||||
}
|
||||
|
||||
// read the BITMAPINFOHEADER
|
||||
// if (sizeof(BITMAPINFOHEADER) != _lread (hFile, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER)))
|
||||
// goto ErrExit;
|
||||
if( pData + sizeof( BITMAPINFOHEADER ) >= pDataEnd )
|
||||
{
|
||||
// debugprint( "LoadDIB_FromMemory error: bad size 2\n" );
|
||||
goto ErrExit;
|
||||
}
|
||||
// debugprint( "LoadDIB_FromMemory, memcpy BITMAPINFOHEADER %i bytes\n", sizeof( BITMAPINFOHEADER ) );
|
||||
memcpy( lpbi, pData, sizeof( BITMAPINFOHEADER ) );
|
||||
pData += sizeof( BITMAPINFOHEADER );
|
||||
|
||||
// Check to see that it's a Windows DIB -- an OS/2 DIB would cause
|
||||
// strange problems with the rest of the DIB API since the fields
|
||||
// in the header are different and the color table entries are
|
||||
// smaller.
|
||||
//
|
||||
// If it's not a Windows DIB (e.g. if biSize is wrong), return NULL.
|
||||
|
||||
if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
|
||||
{
|
||||
// debugprint( "LoadDIB_FromMemory error: lpbi->biSize bad\n" );
|
||||
goto ErrExit;
|
||||
}
|
||||
|
||||
if( lpbi->biCompression != BI_RGB )
|
||||
{
|
||||
// debugprint( "LoadDIB_FromMemory error: Image is compressed\n" );
|
||||
goto ErrExit;
|
||||
}
|
||||
|
||||
// Now determine the size of the color table and read it. Since the
|
||||
// bitmap bits are offset in the file by bfOffBits, we need to do some
|
||||
// special processing here to make sure the bits directly follow
|
||||
// the color table (because that's the format we are susposed to pass
|
||||
// back)
|
||||
nNumColors = (UINT)lpbi->biClrUsed;
|
||||
if (!nNumColors)
|
||||
{
|
||||
// no color table for 24-bit, default size otherwise
|
||||
if (lpbi->biBitCount != 24)
|
||||
nNumColors = 1 << lpbi->biBitCount; /* standard size table */
|
||||
}
|
||||
|
||||
// fill in some default values if they are zero
|
||||
if (lpbi->biClrUsed == 0)
|
||||
lpbi->biClrUsed = nNumColors;
|
||||
|
||||
// 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 );
|
||||
if (lpbi->biSizeImage == 0)
|
||||
{
|
||||
lpbi->biSizeImage = ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 31) & ~31) >> 3) * lpbi->biHeight;
|
||||
}
|
||||
|
||||
// get a proper-sized buffer for header, color table and bits
|
||||
GlobalUnlock(hDIB);
|
||||
// debugprint( "LoadDIB_FromMemory, GlobalReAlloc: lpbi->biSize=%i, nNumColors=%i, lpbi->biSizeImage=%i\n", lpbi->biSize, nNumColors,lpbi->biSizeImage );
|
||||
hDIBtmp = GlobalReAlloc(hDIB, lpbi->biSize + nNumColors * sizeof(RGBQUAD) + lpbi->biSizeImage, 0);
|
||||
|
||||
if (!hDIBtmp) // can't resize buffer for loading
|
||||
{
|
||||
// debugprint( "LoadDIB_FromMemory error: realloc failed\n" );
|
||||
goto ErrExitNoUnlock; //MPB
|
||||
}
|
||||
else
|
||||
hDIB = hDIBtmp;
|
||||
|
||||
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
|
||||
|
||||
// read the color table
|
||||
// _lread (hFile, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBQUAD));
|
||||
// debugprint( "LoadDIB_FromMemory, memcpy color table %i colors, so %i bytes\n", nNumColors, nNumColors * sizeof(RGBQUAD) );
|
||||
memcpy( (LPSTR)(lpbi) + lpbi->biSize, pData, nNumColors * sizeof(RGBQUAD) );
|
||||
pData += nNumColors * sizeof(RGBQUAD);
|
||||
|
||||
// offset to the bits from start of DIB header
|
||||
offBits = lpbi->biSize + nNumColors * sizeof(RGBQUAD);
|
||||
|
||||
// If the bfOffBits field is non-zero, then the bits might *not* be
|
||||
// directly following the color table in the file. Use the value in
|
||||
// bfOffBits to seek the bits.
|
||||
|
||||
if (bmfHeader.bfOffBits != 0L)
|
||||
// _llseek(hFile, bmfHeader.bfOffBits, SEEK_SET);
|
||||
pData = pDataStart + bmfHeader.bfOffBits;
|
||||
|
||||
// debugprint( "bmfHeader.bfOffBits is %i\n", bmfHeader.bfOffBits );
|
||||
|
||||
// if (MyRead(hFile, (LPSTR)lpbi + offBits, lpbi->biSizeImage))
|
||||
// goto OKExit;
|
||||
// debugprint( "Checking that pData(%i) + biSizeImage(%i), which is %i, is equal to pDataEnd(%i)\n",
|
||||
// pData, lpbi->biSizeImage, pData + lpbi->biSizeImage, pDataEnd );
|
||||
// if( pData + lpbi->biSizeImage != pDataEnd ) condition relaxed
|
||||
// {
|
||||
// debugprint( "LoadDIB_FromMemory error: bad size 3\n" );
|
||||
// goto ErrExit;
|
||||
// }
|
||||
|
||||
// debugprint( "LoadDIB_FromMemory, memcpy the bits, %i bytes. Image is w %i, h.%i\n",
|
||||
// lpbi->biSizeImage, lpbi->biWidth, lpbi->biHeight );
|
||||
// debugprint( "Writing to lpbi (%i) + offBits (%i)\n", lpbi, offBits );
|
||||
|
||||
memcpy( (LPSTR)lpbi + offBits, pData, lpbi->biSizeImage );
|
||||
// pData += lpbi->biSizeImage;
|
||||
// if( pData != pDataEnd ) // Should end up one byte past end of data. - condition relaxed
|
||||
// debugprint( "LoadDIB_FromMemory: ERROR! Ended up at %i instead of %i\n", pData, pDataEnd );
|
||||
goto OKExit;
|
||||
|
||||
ErrExit:
|
||||
GlobalUnlock(hDIB);
|
||||
ErrExitNoUnlock:
|
||||
GlobalFree(hDIB);
|
||||
// debugprint( "LoadDIB_FromMemory Error!\n" );
|
||||
return NULL;
|
||||
|
||||
OKExit:
|
||||
GlobalUnlock(hDIB);
|
||||
return hDIB;
|
||||
}
|
||||
#endif
|
Reference in a new issue