JurassicParkTrespasser/jp2_pc/Source/Trespass/Cdib.cpp

2602 lines
58 KiB
C++

//+--------------------------------------------------------------------------
//
// Copyright (C) DreamWorks Interactive, 1996.
//
// File: cdib.cpp
//
// Contents: Dib Reading/Writing/Manipulation Code. This also handles
// Conversions from other formats into DIB format
//
// Classes: CDib
//
// Functions: DetermineFileType
//
// History: SHernd Created
// 13-Jun-96 SHernd Fixed Targa Reading Code (bgr read).
// Fixed PixelRGB (bgr).
// Added Support For Determning Image File
// Type.
//
//---------------------------------------------------------------------------
#include "precomp.h"
#pragma hdrstop
#include "cdib.h"
#define BFT_BITMAP 0x4d42
/* macro to determine if resource is a DIB */
#define ISDIB(bft) ((bft) == BFT_BITMAP)
/* Macro to determine to round off the given value to the closest byte */
#define WIDTHBYTES(i) ((i+31)/32*4)
//#define WIDTHBYTES(i) ((unsigned)((i+31)&(~31))/8)
/* flags for _lseek */
#define SEEK_CUR 1
#define SEEK_END 2
#define SEEK_SET 0
typedef struct tagTARGAHEADER
{
// ID Field Character Length
BYTE bIDLength;
// Color Map Type
BYTE bColorMapType;
// Image Type Code
BYTE bImageType;
// Color Map Specification
WORD wColorMapOrigin;
WORD wColorMapLength;
BYTE bColorMapEntrySize;
// Image Specification
WORD wXOrigin;
WORD wYOrigin;
WORD wWidth;
WORD wHeight;
BYTE bPixelSize;
BYTE bImageDesc;
} TARGAHEADER;
typedef enum tagIMAGETYPE
{
IT_NONE,
IT_BITMAP,
IT_TARGA,
IT_PICT
} IMAGETYPE;
//+--------------------------------------------------------------------------
//
// Function: DetermineFileType
//
// Synopsis: Takes an open file handle and tries to determine what kind
// of image file it is.
//
// Arguments: [hfile] -- open image file handle
// [pimagetype] -- return image file type
//
// Returns: int -- 1 -- if successful
// -2 -- if unable to read from file
// -3 -- if unable to determine file type
//
// History: 13-Jun-96 SHernd Created
//
//---------------------------------------------------------------------------
int DetermineFileType(HANDLE hfile, IMAGETYPE * pimagetype)
{
BYTE ab[512];
BYTE abPICT[512];
DWORD dwRead;
BOOL bRet;
int iRet;
*pimagetype = IT_NONE;
memset(abPICT, 0, sizeof(abPICT));
bRet = ReadFile(hfile, &ab, 512, &dwRead, NULL);
if (!bRet)
{
TraceError(("DetermineFileType() -- Unable to read header info"));
}
// Check for BITMAP
if (ab[0] == 'B' && ab[1] == 'M')
{
*pimagetype = IT_BITMAP;
}
// PICT file has the first 512 bytes of 0
else if (dwRead == 512 && memcmp(ab, abPICT, 512) == 0)
{
*pimagetype = IT_PICT;
}
// we are going to try something different for TARGAs
else
{
#if 0
// The last 26 bytes is the footer information for TARGA
// the byts 8-23 should contain "TRUEVISION-XFILE"
SetFilePointer(hfile, -26, NULL, FILE_END);
bRet = ReadFile(hfile, &ab, 26, &dwRead, NULL);
if (!bRet || (dwRead != 26))
{
TraceError(("DetermineFileType() -- "
"Unable to read last 26 bytes"));
iRet = -2;
goto Error;
}
if (strncmp((char *)&ab[8], "TRUEVISION-XFILE", 16) == 0)
{
*pimagetype = IT_TARGA;
}
else
{
TraceError(("DetermineFileType() -- "
"Unable To Determine file type"));
iRet = -3;
goto Error;
}
#endif
*pimagetype = IT_TARGA;
}
iRet = 1;
SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
return iRet;
}
BOOL PASCAL DibRead(VOID * pv, VOID * pbDst, DWORD dwSize, DWORD * pdwRead)
{
return ReadFile((HANDLE)pv, pbDst, dwSize, pdwRead, NULL);
}
BOOL PASCAL DibWrite(VOID * pv, VOID * pbSrc, DWORD dwSize, DWORD * pdwWritten)
{
return WriteFile((HANDLE)pv, pbSrc, dwSize, pdwWritten, NULL);
}
BOOL PASCAL DibSeek(VOID * pv, DWORD dwMove, DWORD seek, DWORD * pNewOffset)
{
DWORD dwOffset;
dwOffset = SetFilePointer((HANDLE)pv, dwMove, NULL, seek);
if (pNewOffset)
{
*pNewOffset = dwOffset;
}
return TRUE;
}
//+--------------------------------------------------------------------------
//---------------- CDib Member Functions ----------------
//---------------------------------------------------------------------------
CDib::CDib()
{
m_lpbi = NULL;
}
CDib::~CDib()
{
delete [] m_lpbi;
}
BOOL CDib::Create(int cx, int cy, WORD wBitCount, DWORD dwColorsUsed)
{
LPBITMAPINFOHEADER pdib;
DWORD dwSize;
DWORD dwColors;
BITMAPINFOHEADER bi;
BOOL bRet;
// if we have an image that is 16- or 24-bit we won't us the
// incredibly huge number for a palette
dwColors = (wBitCount < 16) ? dwColorsUsed : 0;
switch (wBitCount)
{
case 8:
dwColors = 256;
break;
case 4:
dwColors = 64;
break;
case 2:
dwColors = 2;
}
m_wWidthBytes = ((cx * (wBitCount / 8)) + 3) & ~3;
//
// Assign the values into the Info Header
//
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = cx;
bi.biHeight = cy;
bi.biPlanes = 1;
bi.biBitCount = wBitCount;
bi.biCompression = (wBitCount < 16) ? 0 : BI_RGB;
bi.biSizeImage = m_wWidthBytes * abs(cy);
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = dwColors;
bi.biClrImportant = dwColors;
dwSize = bi.biSize + (dwColors * sizeof(RGBQUAD)) + bi.biSizeImage;
pdib = (LPBITMAPINFOHEADER)new BYTE[dwSize];
if (pdib == NULL)
{
Trace(("ERROR: CDib::Create() -- OUT OF MEMORY -- "
"Unable to create dib"));
goto Error;
}
memset (pdib, 0, dwSize);
*(pdib) = bi;
delete [] m_lpbi;
m_lpbi = pdib;
m_pBits = (LPBYTE)m_lpbi + m_lpbi->biSize + (dwColors * sizeof(RGBQUAD));
// for a 8 bit image create a grey-scale palette
if (wBitCount == 8)
{
RGBQUAD * prgb = GetColor(0);
int i;
for (i = 0; i < 256; i++)
{
prgb[i].rgbRed = i;
prgb[i].rgbGreen = i;
prgb[i].rgbBlue = i;
}
}
bRet = TRUE;
Cleanup:
return bRet;
Error:
Trace(("ERROR: CDib::Create"));
if (pdib != NULL)
{
delete pdib;
}
bRet = FALSE;
goto Cleanup;
}
CDib * CDib::DibFromResource(HINSTANCE hInst, LPCSTR lpName)
{
HRSRC hRes;
HGLOBAL hresDIB;
LPBITMAPINFOHEADER lpbi;
BITMAPFILEHEADER * pbmheader;
CDib * pdib = NULL;
DWORD dwWidthBytes;
DWORD dwSize;
hRes = FindResource (hInst, lpName, (LPCSTR) "DIB");
if (!hRes)
{
goto Error;
}
hresDIB = LoadResource (hInst, hRes);
pbmheader = (LPBITMAPFILEHEADER)LockResource (hresDIB);
dwSize = pbmheader->bfSize - pbmheader->bfOffBits;
if (pbmheader == NULL)
{
goto Error;
}
if (!ISDIB(pbmheader->bfType))
{
goto Error;
}
lpbi = (LPBITMAPINFOHEADER)((LPBYTE)pbmheader + sizeof(BITMAPFILEHEADER));
pdib = new CDib;
if (pdib == NULL)
{
goto Error;
}
if (!pdib->Create(lpbi->biWidth,
lpbi->biHeight,
lpbi->biBitCount,
lpbi->biClrUsed))
{
goto Error;
}
if (lpbi->biBitCount == 8)
{
int iColors;
iColors = lpbi->biClrUsed;
if (iColors == 0)
{
iColors = 256;
}
memcpy(pdib->GetColor(0),
(LPBYTE)lpbi + lpbi->biSize,
sizeof(RGBQUAD) * iColors);
dwWidthBytes = (lpbi->biWidth + 3) & ~3;
memcpy(pdib->GetBits(),
(LPBYTE)lpbi +
sizeof(BITMAPINFOHEADER) +
(sizeof(RGBQUAD) * iColors),
dwWidthBytes * lpbi->biHeight);
(pdib->GetInfoHeader())->biCompression = lpbi->biCompression;
}
else
if (lpbi->biBitCount == 24)
{
dwWidthBytes = ((lpbi->biWidth * 3) + 3) & ~3;
memcpy(pdib->GetBits(),
(LPBYTE)lpbi + sizeof(BITMAPINFOHEADER),
dwWidthBytes * lpbi->biHeight);
(pdib->GetInfoHeader())->biCompression = lpbi->biCompression;
}
else
{
Assert(FALSE);
}
Cleanup:
UnlockResource (hresDIB);
FreeResource (hresDIB);
return pdib;
Error:
delete pdib;
pdib = NULL;
goto Cleanup;
}
//+--------------------------------------------------------------------------
//
// Member: CDib::DibFromFile
//
// Synopsis: Opens the file. Determines what kind of image file that it
// is. Then reads the image file into a dib.
//
// Arguments: [pszFile] -- name of file to load
// [ppdib] -- destination pointer for loaded dib
//
// Returns: int -- 1 -- if successful
// -1 -- if file was not able to be opened
// -2 -- if error reading from file
// -3 -- if unable to determine file type
// -5 -- if Error reading image
//
// History: 13-Jun-96 SHernd Created
//
//---------------------------------------------------------------------------
int CDib::DibFromFile(LPCSTR pszFile, CDib ** ppdib)
{
int iRet;
HANDLE hfile = INVALID_HANDLE_VALUE;
CDib * pdib = NULL;
IMAGETYPE imagetype;
hfile = CreateFile(pszFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hfile == INVALID_HANDLE_VALUE)
{
TraceError(("CDib::DibFromFile() -- "
"Unable to OpenFile"));
iRet = -1;
goto Error;
}
// Try and determine file type
iRet = DetermineFileType(hfile, &imagetype);
if (iRet != 1)
{
TraceError(("CDib::DibFromFile() -- "
"DetermineFileType Failed"));
goto Error;
}
CloseHandle(hfile);
hfile = INVALID_HANDLE_VALUE;
switch (imagetype)
{
case IT_BITMAP:
pdib = CDib::DibFromFile(pszFile);
break;
case IT_TARGA:
pdib = CDib::DibFromTarga(pszFile);
break;
#if 0
case IT_PICT:
pdib = DibFromPICT(pszFile);
break;
#endif
}
if (pdib == NULL)
{
TraceError(("CDib::DibFromFile() -- "
"Error loading image %i",
imagetype));
iRet = -5;
}
iRet = 1;
Cleanup:
if (hfile !=INVALID_HANDLE_VALUE)
{
CloseHandle(hfile);
}
*ppdib = pdib;
return iRet;
Error:
TraceError(("CDib::DibFromFile"));
delete pdib;
pdib = NULL;
goto Cleanup;
}
CDib * CDib::DibFromFile(LPCSTR pszFile)
{
CDib * pdib;
pdib = new CDib();
if (pdib == NULL)
{
Trace(("ERROR: CDib::DibFromFile() -- "
"OOM -- Couldn't create CDib"));
goto Error;
}
if (!pdib->LoadFromFile(pszFile))
{
Trace(("ERROR: CDib::DibFromFile() -- LoadFromFile failed"));
goto Error;
}
Cleanup:
return pdib;
Error:
Trace(("ERROR: CDib::DibFromFile"));
if (pdib != NULL)
{
delete pdib;
pdib = NULL;
}
goto Cleanup;
}
BOOL CDib::LoadFromStream(VOID * pv, PFNDIBREAD pfnDibRead, PFNDIBSEEK pfnDibSeek)
{
LPBITMAPINFOHEADER lpbi = NULL;
DWORD dwLen = 0;
DWORD dwBits;
DWORD dwRead;
LPBITMAPINFOHEADER pbtemp = NULL;
BOOL bRet;
BYTE * pb;
lpbi = ReadDibBitmapInfo(pv, pfnDibRead, pfnDibSeek);
if (lpbi == NULL)
{
TraceError(("CDib::LoadFromStream() - "
"Read dib bitmap info failed"));
goto Error;
}
//
// Calculate the memory needed to hold the DIB
//
dwBits = lpbi->biSizeImage;
dwLen = lpbi->biSize + (DWORD)GetPaletteSize(lpbi) + dwBits;
//
// Try to increase the size of the bitmap info. buffer to hold the DIB
//
pbtemp = (LPBITMAPINFOHEADER) new BYTE[dwLen];
if (pbtemp == NULL)
{
TraceError(("CDib::LoadFromStream() - OOM - "
"Couldn't allocate enough memory for size of bitmap"));
goto Error;
}
memcpy(pbtemp,
lpbi,
lpbi->biSize + (DWORD)GetPaletteSize(lpbi));
delete [] lpbi;
lpbi = (LPBITMAPINFOHEADER)pbtemp;
//
// Read in the bits
//
pb = (BYTE *)lpbi + (WORD)lpbi->biSize + GetPaletteSize(lpbi);
(pfnDibRead)(pv, pb, dwBits, &dwRead);
m_pBits = pb;
m_wWidthBytes = ((lpbi->biWidth * (lpbi->biBitCount / 8)) + 3) & ~3;
bRet = TRUE;
Cleanup:
m_lpbi = lpbi;
return bRet;
Error:
bRet = FALSE;
delete [] lpbi;
lpbi = NULL;
TraceError(("CDib::LoadFromStream"));
goto Cleanup;
}
BOOL CDib::LoadFromFile(LPCSTR pszFile)
{
HANDLE hfile = INVALID_HANDLE_VALUE;
BOOL bRet;
//
// Open the file and read the DIB information
//
hfile = CreateFile(pszFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hfile == INVALID_HANDLE_VALUE)
{
Trace(("ERROR: CDib::LoadFromFile() - Couldn't open file %s", pszFile));
goto Error;
}
bRet = LoadFromStream(hfile, (PFNDIBREAD)DibRead, (PFNDIBSEEK)DibSeek);
Cleanup:
if (hfile != INVALID_HANDLE_VALUE)
{
CloseHandle(hfile);
}
return bRet;
Error:
bRet = FALSE;
Trace(("ERROR: CDib::LoadFromFile"));
goto Cleanup;
}
LPBITMAPINFOHEADER CDib::ReadDibBitmapInfo(VOID * pv,
PFNDIBREAD pfnDibRead,
PFNDIBSEEK pfnDibSeek)
{
DWORD off;
HANDLE hbi = NULL;
INT size;
INT i;
WORD nNumColors;
RGBQUAD FAR * pRgb;
BITMAPINFOHEADER bi;
BITMAPCOREHEADER bc;
LPBITMAPINFOHEADER lpbi;
BITMAPFILEHEADER bf;
DWORD dwWidth = 0;
DWORD dwHeight = 0;
WORD wPlanes, wBitCount;
DWORD dwRead;
//
// Reset file pointer and read file header
//
(pfnDibSeek)(pv, 0L, FILE_CURRENT, &off);
(pfnDibRead)(pv, &bf, sizeof(BITMAPFILEHEADER), &dwRead);
if (sizeof(BITMAPFILEHEADER) != dwRead)
{
return NULL;
}
//
// Do we have a RC HEADER?
//
if (!ISDIB(bf.bfType))
{
bf.bfOffBits = 0L;
(pfnDibSeek)(pv, off, FILE_BEGIN, NULL);
}
(pfnDibRead)(pv, &bi, sizeof(bi), &dwRead);
if (sizeof(bi) != dwRead)
{
return NULL;
}
nNumColors = NumColors((BYTE *)&bi);
//
// Check the nature (BITMAPINFO or BITMAPCORE) of the info. block
// and extract the field information accordingly. If a BITMAPCOREHEADER,
// transfer it's field information to a BITMAPINFOHEADER-style block
//
switch (size = (INT)bi.biSize)
{
case sizeof(BITMAPINFOHEADER):
break;
case sizeof(BITMAPCOREHEADER):
bc = *(BITMAPCOREHEADER*)&bi;
dwWidth = (DWORD)bc.bcWidth;
dwHeight = (DWORD)bc.bcHeight;
wPlanes = bc.bcPlanes;
wBitCount = bc.bcBitCount;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = dwWidth;
bi.biHeight = dwHeight;
bi.biPlanes = wPlanes;
bi.biBitCount = wBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = nNumColors;
bi.biClrImportant = nNumColors;
(pfnDibSeek)(pv,
sizeof(BITMAPCOREHEADER) - sizeof(BITMAPINFOHEADER),
FILE_CURRENT,
NULL);
break;
default:
// Not a DIB!
Trace(("ERROR: CDib::ReadDibBitmapInfo() -- "
"This is not a dib"));
goto Error;
}
//
// Fill in some default values if they are zero
//
if (bi.biSizeImage == 0)
{
bi.biSizeImage = WIDTHBYTES((DWORD)bi.biWidth * bi.biBitCount)
* bi.biHeight;
}
if (bi.biClrUsed == 0)
{
bi.biClrUsed = NumColors((BYTE *)&bi);
}
//
// Allocate for the BITMAPINFO structure and the color table
//
lpbi = (LPBITMAPINFOHEADER)new BYTE[bi.biSize +
nNumColors * sizeof(RGBQUAD)];
if (lpbi == NULL)
{
Trace(("Error: CDib::ReadDibBitmapInfo() -- OOM -- "
"Couldn't allocate new bitmap location"));
goto Error;
}
*lpbi = bi;
//
// Get a pointer to the color table
//
pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + bi.biSize);
if (nNumColors)
{
if (size == sizeof(BITMAPCOREHEADER))
{
//
// Convert a old color table (3 byte RGBTRIPLEs) to a new
// color table (4 byte RGBQUADs)
//
(pfnDibRead)(pv, pRgb, nNumColors * sizeof(RGBTRIPLE), &dwRead);
for (i = nNumColors - 1; i >= 0; i--)
{
RGBQUAD rgb;
rgb.rgbRed = ((RGBTRIPLE FAR *)pRgb)[i].rgbtRed;
rgb.rgbBlue = ((RGBTRIPLE FAR *)pRgb)[i].rgbtBlue;
rgb.rgbGreen = ((RGBTRIPLE FAR *)pRgb)[i].rgbtGreen;
rgb.rgbReserved = (BYTE)0;
pRgb[i] = rgb;
}
}
else
{
(pfnDibRead)(pv, pRgb, nNumColors * sizeof(RGBQUAD), &dwRead);
}
}
if (bf.bfOffBits != 0L)
{
(pfnDibSeek)(pv, off + bf.bfOffBits, FILE_BEGIN, NULL);
}
Cleanup:
return lpbi;
Error:
Trace(("ERROR: CDib::ReadDibBitmapInfo"));
if (lpbi != NULL)
{
delete [] lpbi;
lpbi = NULL;
}
goto Cleanup;
}
LPBITMAPINFOHEADER CDib::ReadDibBitmapInfo(HANDLE hfile)
{
DWORD off;
HANDLE hbi = NULL;
INT size;
INT i;
WORD nNumColors;
RGBQUAD FAR * pRgb;
BITMAPINFOHEADER bi;
BITMAPCOREHEADER bc;
LPBITMAPINFOHEADER lpbi;
BITMAPFILEHEADER bf;
DWORD dwWidth = 0;
DWORD dwHeight = 0;
WORD wPlanes, wBitCount;
DWORD dwRead;
if (hfile == INVALID_HANDLE_VALUE)
{
return NULL;
}
//
// Reset file pointer and read file header
//
off = SetFilePointer(hfile, 0L, NULL, FILE_CURRENT);
ReadFile(hfile, &bf, sizeof(BITMAPFILEHEADER), &dwRead, NULL);
if (sizeof(BITMAPFILEHEADER) != dwRead)
{
return NULL;
}
//
// Do we have a RC HEADER?
//
if (!ISDIB(bf.bfType))
{
bf.bfOffBits = 0L;
SetFilePointer(hfile, off, NULL, FILE_BEGIN);
}
ReadFile(hfile, &bi, sizeof(bi), &dwRead, NULL);
if (sizeof(bi) != dwRead)
{
return NULL;
}
nNumColors = NumColors((BYTE *)&bi);
//
// Check the nature (BITMAPINFO or BITMAPCORE) of the info. block
// and extract the field information accordingly. If a BITMAPCOREHEADER,
// transfer it's field information to a BITMAPINFOHEADER-style block
//
switch (size = (INT)bi.biSize)
{
case sizeof(BITMAPINFOHEADER):
break;
case sizeof(BITMAPCOREHEADER):
bc = *(BITMAPCOREHEADER*)&bi;
dwWidth = (DWORD)bc.bcWidth;
dwHeight = (DWORD)bc.bcHeight;
wPlanes = bc.bcPlanes;
wBitCount = bc.bcBitCount;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = dwWidth;
bi.biHeight = dwHeight;
bi.biPlanes = wPlanes;
bi.biBitCount = wBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = nNumColors;
bi.biClrImportant = nNumColors;
SetFilePointer(hfile,
sizeof(BITMAPCOREHEADER) - sizeof(BITMAPINFOHEADER),
NULL,
FILE_CURRENT);
break;
default:
// Not a DIB!
Trace(("ERROR: CDib::ReadDibBitmapInfo() -- "
"This is not a dib"));
goto Error;
}
//
// Fill in some default values if they are zero
//
if (bi.biSizeImage == 0)
{
bi.biSizeImage = WIDTHBYTES((DWORD)bi.biWidth * bi.biBitCount)
* bi.biHeight;
}
if (bi.biClrUsed == 0)
{
bi.biClrUsed = NumColors((BYTE *)&bi);
}
//
// Allocate for the BITMAPINFO structure and the color table
//
lpbi = (LPBITMAPINFOHEADER)new BYTE[bi.biSize +
nNumColors * sizeof(RGBQUAD)];
if (lpbi == NULL)
{
Trace(("Error: CDib::ReadDibBitmapInfo() -- OOM -- "
"Couldn't allocate new bitmap location"));
goto Error;
}
*lpbi = bi;
//
// Get a pointer to the color table
//
pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + bi.biSize);
if (nNumColors)
{
if (size == sizeof(BITMAPCOREHEADER))
{
//
// Convert a old color table (3 byte RGBTRIPLEs) to a new
// color table (4 byte RGBQUADs)
//
ReadFile(hfile, pRgb, nNumColors * sizeof(RGBTRIPLE), &dwRead, NULL);
for (i = nNumColors - 1; i >= 0; i--)
{
RGBQUAD rgb;
rgb.rgbRed = ((RGBTRIPLE FAR *)pRgb)[i].rgbtRed;
rgb.rgbBlue = ((RGBTRIPLE FAR *)pRgb)[i].rgbtBlue;
rgb.rgbGreen = ((RGBTRIPLE FAR *)pRgb)[i].rgbtGreen;
rgb.rgbReserved = (BYTE)0;
pRgb[i] = rgb;
}
}
else
{
ReadFile(hfile, pRgb, nNumColors * sizeof(RGBQUAD), &dwRead, NULL);
}
}
if (bf.bfOffBits != 0L)
{
SetFilePointer(hfile, off + bf.bfOffBits, NULL, FILE_BEGIN);
}
Cleanup:
return lpbi;
Error:
Trace(("ERROR: CDib::ReadDibBitmapInfo"));
if (lpbi != NULL)
{
delete [] lpbi;
lpbi = NULL;
}
goto Cleanup;
}
WORD CDib::NumColors()
{
return NumColors((BYTE *)m_lpbi);
}
WORD CDib::NumColors(BYTE * pv)
{
int bits;
LPBITMAPINFOHEADER lpbi;
LPBITMAPCOREHEADER lpbc;
WORD wRet;
lpbi = ((LPBITMAPINFOHEADER)pv);
lpbc = ((LPBITMAPCOREHEADER)pv);
//
// With the BITMAPINFO format headers, the size of the palette
// is in biClrUsed, whereas in the BITMAPCORE - style headers, it
// is dependent on the bits per pixel ( = 2 raised to the power of
// bits/pixel).
//
if (lpbi->biSize != sizeof(BITMAPCOREHEADER))
{
if (lpbi->biClrUsed != 0)
{
return (WORD)lpbi->biClrUsed;
}
bits = lpbi->biBitCount;
}
else
{
bits = lpbc->bcBitCount;
}
switch (bits)
{
case 1:
wRet = 2;
break;
case 4:
wRet = 16;
break;
case 8:
wRet = 256;
break;
default:
// A 24 bitcount DIB has no color table
wRet = 0;
break;
}
return wRet;
}
RGBQUAD * CDib::GetColor(int i)
{
RGBQUAD * prgb;
if ((NumColors() <= i) || (i < 0))
{
return NULL;
}
prgb = ((RGBQUAD *)((LPBYTE)(m_lpbi) + (int)(m_lpbi)->biSize));
return &prgb[i];
}
WORD CDib::GetPaletteSize(LPBITMAPINFOHEADER lpbi)
{
WORD wNumColors;
WORD wSize;
wNumColors = NumColors((BYTE *)lpbi);
if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
{
wSize = wNumColors * sizeof(RGBTRIPLE);
}
else
{
wSize = wNumColors * sizeof(RGBQUAD);
}
return wSize;
}
HBITMAP CDib::GetBitmap(HPALETTE * pPal)
{
HPALETTE hpalT;
HDC hdc;
HBITMAP hbm;
HPALETTE hpal;
if (pPal == NULL)
{
hpal = CreatePalette();
}
else
{
hpal = *pPal;
}
hdc = GetDC(NULL);
if (hpal)
{
hpalT = SelectPalette(hdc,hpal,FALSE);
RealizePalette(hdc); // GDI Bug...????
}
hbm = CreateDIBitmap(hdc,
m_lpbi,
CBM_INIT,
(BYTE *)m_lpbi + (WORD)m_lpbi->biSize + GetPaletteSize(m_lpbi),
(LPBITMAPINFO)m_lpbi,
DIB_RGB_COLORS );
if (hpal)
SelectPalette(hdc,hpalT,FALSE);
ReleaseDC(NULL,hdc);
return hbm;
}
DWORD CDib::GetSize()
{
if (m_lpbi != NULL)
{
return m_lpbi->biSize;
}
return 0;
}
LONG CDib::GetWidth()
{
if (m_lpbi != NULL)
{
return m_lpbi->biWidth;
}
return 0;
}
WORD CDib::GetWidthBytes()
{
if (m_lpbi == NULL)
{
return (WORD)-1;
}
return m_wWidthBytes;
}
LONG CDib::GetHeight()
{
if (m_lpbi != NULL)
{
return abs(m_lpbi->biHeight);
}
return 0;
}
int CDib::GetOrientation()
{
if (m_lpbi != NULL)
{
return (m_lpbi->biHeight < 0) ? -1 : 0;
}
return 0;
}
WORD CDib::GetPlanes()
{
if (m_lpbi != NULL)
{
return m_lpbi->biPlanes;
}
return 0;
}
WORD CDib::GetBitCount()
{
if (m_lpbi != NULL)
{
return m_lpbi->biBitCount;
}
return 0;
}
DWORD CDib::GetCompression()
{
if (m_lpbi != NULL)
{
return m_lpbi->biCompression;
}
return 0;
}
BOOL CDib::Uncompress()
{
BOOL bRet;
BYTE * pb;
BYTE * pbDest;
int x;
int y;
int i;
BYTE byte;
int iCount;
BOOL bEnd = FALSE;
CDib * pdib;
BYTE bClr;
int iWidth;
int iHeight;
LPBITMAPINFOHEADER lpbi;
LPBYTE pBits;
WORD wWidthBytes;
//
// create our destination dib
//
pdib = new CDib();
if (pdib == NULL)
{
goto Error;
}
pdib->Create(GetWidth(),
GetHeight(),
8,
256);
if (pdib == NULL)
{
goto Error;
}
//
// Copy the bitmap color table information
//
memcpy(pdib->GetColor(0), GetColor(0), 256 * sizeof(RGBQUAD));
pb = GetBits();
x = 0;
y = 0;
iWidth = pdib->GetWidth();
iHeight = pdib->GetHeight();
pbDest = pdib->GetPixelPointer(x, y);
while (!bEnd)
{
byte = *pb;
if (byte == 0)
{
byte = *++pb;
switch (byte)
{
case 0:
//
// End of line in bitmap
//
y++;
x = 0;
pbDest = pdib->GetPixelPointer(x, y);
pb++;
break;
case 1:
//
// End of Bitmap
//
bEnd = TRUE;
break;
case 2:
//
// Move to a new X, Y coordinate
//
byte = *pb++;
x += (int)byte;
byte = *pb++;
y += (int)byte;
pbDest = pdib->GetPixelPointer(x, y);
break;
default:
//
// Absolute Mode (must align on word boundries)
//
pb++;
iCount = 0;
for (i = 0; i < (int)byte; i++)
{
iCount++;
bClr = *pb++;
*pbDest++ = bClr;
x++;
}
// Assuring word alignment
if ((iCount % 2) != 0)
{
pb++;
}
break;
}
}
else
{
//
// Here would be where the main optimizations would occure
//
bClr = *++pb;
for (i = 0; i < (int)byte; i++)
{
*pbDest++ = bClr;
x++;
Assert(x < pdib->GetWidth());
}
pb++;
}
}
lpbi = pdib->m_lpbi;
pBits = pdib->m_pBits;
wWidthBytes = pdib->m_wWidthBytes;
pdib->m_lpbi = m_lpbi;
pdib->m_pBits = m_pBits;
pdib->m_wWidthBytes = m_wWidthBytes;
m_lpbi = lpbi;
m_pBits = pBits;
m_wWidthBytes = wWidthBytes;
Cleanup:
delete pdib;
return bRet;
Error:
Trace(("ERROR: RLEDibToDib\r\n"));
bRet = FALSE;
goto Cleanup;
}
DWORD CDib::GetSizeImage()
{
if (m_lpbi != NULL)
{
return m_lpbi->biSizeImage;
}
return 0;
}
DWORD CDib::GetColorsUsed()
{
if (m_lpbi != NULL)
{
return m_lpbi->biClrUsed;
}
return 0;
}
DWORD CDib::GetColorsImportant()
{
if (m_lpbi != NULL)
{
return m_lpbi->biClrImportant;
}
return 0;
}
HPALETTE CDib::CreatePalette()
{
LOGPALETTE * pLogPal = NULL;
HPALETTE hpal = NULL;
RGBQUAD * pRgb;
WORD nNumColors;
WORD i;
BYTE red;
BYTE green;
BYTE blue;
BOOL fCoreHeader;
BYTE * pb;
if (m_lpbi == NULL)
{
return NULL;
}
fCoreHeader = (m_lpbi->biSize == sizeof(BITMAPCOREHEADER));
pRgb = (RGBQUAD *)((BYTE *)m_lpbi + (WORD)m_lpbi->biSize);
nNumColors = NumColors();
if (nNumColors)
{
pLogPal = (LOGPALETTE *)new BYTE[sizeof(LOGPALETTE) +
(nNumColors * sizeof(PALETTEENTRY))];
if (!pLogPal)
{
Trace(("ERROR: CreatePalette() -- OUT OF MEMORY -- "
"Couldn't create log Palette"));
goto Error;
}
pLogPal->palNumEntries = nNumColors;
pLogPal->palVersion = PALVERSION;
for( i = 0; i < nNumColors; i++ )
{
pLogPal->palPalEntry[i].peRed = pRgb->rgbRed;
pLogPal->palPalEntry[i].peGreen = pRgb->rgbGreen;
pLogPal->palPalEntry[i].peBlue = pRgb->rgbBlue;
pLogPal->palPalEntry[i].peFlags = (BYTE)0;
// If this was an old style bitmap advance only
if (fCoreHeader)
{
pb = (BYTE *)pRgb;
pb += sizeof(RGBTRIPLE);
pRgb = (RGBQUAD *)pb;
}
else
{
pRgb++;
}
}
}
else if (GetBitCount() == 24)
{
nNumColors = MAXPALETTE;
pLogPal = (LOGPALETTE *) new BYTE[sizeof (LOGPALETTE) +
(nNumColors * sizeof (PALETTEENTRY))];
if (!pLogPal)
{
Trace(("ERROR: CreatePalette() -- OUT OF MEMORY -- "
"Couldn't create log Palette (24-bit)"));
goto Error;
}
pLogPal->palNumEntries = nNumColors;
pLogPal->palVersion = PALVERSION;
red = green = blue = 0;
for( i = 0; i < pLogPal->palNumEntries; i++ )
{
pLogPal->palPalEntry[i].peRed = red;
pLogPal->palPalEntry[i].peGreen = green;
pLogPal->palPalEntry[i].peBlue = blue;
pLogPal->palPalEntry[i].peFlags = (BYTE)0;
if (!(red += 32))
{
if (!(green += 32))
{
blue += 64;
}
}
}
}
hpal = ::CreatePalette(pLogPal);
Cleanup:
if (pLogPal != NULL)
{
delete [] pLogPal;
}
return hpal;
Error:
Trace(("ERROR: CDib::CreatePalette"));
if (hpal != NULL)
{
DeleteObject(hpal);
hpal = NULL;
}
goto Cleanup;
}
LOGPALETTE * CDib::CreateLogPalette()
{
LOGPALETTE * pLogPal = NULL;
HPALETTE hpal = NULL;
RGBQUAD * pRgb;
WORD nNumColors;
WORD i;
BYTE red;
BYTE green;
BYTE blue;
BOOL fCoreHeader;
BYTE * pb;
if (m_lpbi == NULL)
{
return NULL;
}
fCoreHeader = (m_lpbi->biSize == sizeof(BITMAPCOREHEADER));
pRgb = (RGBQUAD *)((BYTE *)m_lpbi + (WORD)m_lpbi->biSize);
nNumColors = NumColors();
if (nNumColors)
{
pLogPal = (LOGPALETTE *)new BYTE[sizeof(LOGPALETTE) +
(nNumColors * sizeof(PALETTEENTRY))];
if (!pLogPal)
{
Trace(("ERROR: CreateLogPalette() -- OUT OF MEMORY -- "
"Couldn't create log Palette"));
goto Error;
}
pLogPal->palNumEntries = nNumColors;
pLogPal->palVersion = PALVERSION;
for( i = 0; i < nNumColors; i++ )
{
pLogPal->palPalEntry[i].peRed = pRgb->rgbRed;
pLogPal->palPalEntry[i].peGreen = pRgb->rgbGreen;
pLogPal->palPalEntry[i].peBlue = pRgb->rgbBlue;
pLogPal->palPalEntry[i].peFlags = (BYTE)0;
// If this was an old style bitmap advance only
if (fCoreHeader)
{
pb = (BYTE *)pRgb;
pb += sizeof(RGBTRIPLE);
pRgb = (RGBQUAD *)pb;
}
else
{
pRgb++;
}
}
}
else if (GetBitCount() == 24)
{
nNumColors = MAXPALETTE;
pLogPal = (LOGPALETTE *) new BYTE[sizeof (LOGPALETTE) +
(nNumColors * sizeof (PALETTEENTRY))];
if (!pLogPal)
{
Trace(("ERROR: CreateLogPalette() -- OUT OF MEMORY -- "
"Couldn't create log Palette (24-bit)"));
goto Error;
}
pLogPal->palNumEntries = nNumColors;
pLogPal->palVersion = PALVERSION;
red = green = blue = 0;
for( i = 0; i < pLogPal->palNumEntries; i++ )
{
pLogPal->palPalEntry[i].peRed = red;
pLogPal->palPalEntry[i].peGreen = green;
pLogPal->palPalEntry[i].peBlue = blue;
pLogPal->palPalEntry[i].peFlags = (BYTE)0;
if (!(red += 32))
{
if (!(green += 32))
{
blue += 64;
}
}
}
}
Cleanup:
return pLogPal;
Error:
Trace(("ERROR: CDib::CreateLogPalette"));
goto Cleanup;
}
RGBQUAD * CDib::GetPalettePtr()
{
if (m_lpbi)
{
return (RGBQUAD *)((BYTE *)m_lpbi + m_lpbi->biSize);
}
return NULL;
}
BOOL DecompressTarga (HANDLE hfile, LPBYTE pbBits, TARGAHEADER * pth)
{
long lSize;
BYTE bLength;
DWORD dwRead;
int iPixelSize;
iPixelSize = (pth->bPixelSize / 8);
lSize = pth->wWidth * pth->wHeight;
while (lSize > 0)
{
ReadFile (hfile, &bLength, sizeof(BYTE), &dwRead, NULL);
if (dwRead==0) return FALSE;
if (bLength & 0x80)
{
bLength &= ~0x80;
bLength = (BYTE)__min (lSize, bLength+1);
lSize -= bLength;
// read the RLE color
ReadFile (hfile, pbBits, iPixelSize, &dwRead, NULL);
// we already read one.
bLength--;
// copy it
while (bLength--)
{
memcpy (pbBits+iPixelSize, pbBits, iPixelSize);
pbBits += iPixelSize;
}
pbBits += iPixelSize;
}
else
{
bLength++;
bLength = (BYTE)__min (lSize, bLength);
lSize -= bLength;
// read the raw colors
ReadFile (hfile, pbBits, iPixelSize*bLength, &dwRead, NULL);
pbBits += iPixelSize*bLength;
}
}
return TRUE;
}
BOOL ReadTargaHeader(HANDLE hfile, TARGAHEADER * pth)
{
DWORD dwRead;
BYTE bIDLength = 0;
char sz[200];
BOOL bRet;
//
// Read Targa file header into global variables
//
ReadFile(hfile, &(pth->bIDLength), sizeof(pth->bIDLength), &dwRead, NULL);
// we can handle this, right?
#if 0
if (pth->bIDLength != 0)
{
wsprintf(sz, "Non-empty identification field");
goto Failure;
}
#endif
// Read color map type
ReadFile(hfile,
&(pth->bColorMapType),
sizeof(pth->bColorMapType),
&dwRead,
NULL);
if (pth->bColorMapType != 0)
{
wsprintf(sz, "unexpected color map type (%ld)", pth->bColorMapType);
goto Failure;
}
// Read Image type
ReadFile(hfile,
&(pth->bImageType),
sizeof(pth->bImageType),
&dwRead, NULL);
if (pth->bImageType != 2 && pth->bImageType != 10)
{
wsprintf(sz, "Unexpected image type (%ld)", pth->bImageType);
goto Failure;
}
//
// Skip color map specification
//
ReadFile(hfile,
&(pth->wColorMapOrigin),
sizeof(pth->wColorMapOrigin),
&dwRead,
NULL);
ReadFile(hfile,
&(pth->wColorMapLength),
sizeof(pth->wColorMapLength),
&dwRead,
NULL);
ReadFile(hfile,
&(pth->bColorMapEntrySize),
sizeof(pth->bColorMapEntrySize),
&dwRead, NULL);
//
// Read image origin
//
ReadFile(hfile, &(pth->wXOrigin), sizeof(pth->wXOrigin), &dwRead, NULL);
ReadFile(hfile, &(pth->wYOrigin), sizeof(pth->wYOrigin), &dwRead, NULL);
//
// Read image dimensions
//
ReadFile(hfile, &(pth->wWidth), sizeof(pth->wWidth), &dwRead, NULL);
ReadFile(hfile, &(pth->wHeight), sizeof(pth->wHeight), &dwRead, NULL);
//
// Read color depth
//
ReadFile(hfile,
&(pth->bPixelSize),
sizeof(pth->bPixelSize),
&dwRead, NULL);
//
// Read image descriptor
//
ReadFile(hfile,
&(pth->bImageDesc),
sizeof(pth->bImageDesc),
&dwRead, NULL);
// These bits indicate alpha channel, which
// we will ignore, but we allow to be here.
#if 0
if ((pth->bImageDesc & 15) != 0)
{
wsprintf(sz,
"Unexpected attribute bits (%ld)\n",
pth->bImageDesc & 15);
goto Failure;
}
#endif
//
// Skip the identification field (it will be lost)
//
SetFilePointer(hfile, pth->bIDLength, 0, FILE_CURRENT);
// NOTE: We assume that the color map is empty
bRet = TRUE;
Cleanup:
return bRet;
Failure:
bRet = FALSE;
TraceError((sz));
goto Cleanup;
}
#if 0
#define DibWidthBytesN(lpbi, n) (UINT)WIDTHBYTES((UINT)(lpbi)->biWidth * (UINT)(n))
#define DibWidthBytes(lpbi) DibWidthBytesN(lpbi, (lpbi)->biBitCount)
#define DibColors(lpbi) ((RGBQUAD FAR *)((LPBYTE)(lpbi) + (int)(lpbi)->biSize))
#ifdef WIN32
#define DibPtr(lpbi) ((lpbi)->biCompression == BI_BITFIELDS \
? (LPVOID)(DibColors(lpbi) + 3) \
: (LPVOID)(DibColors(lpbi) + (UINT)(lpbi)->biClrUsed))
#else
#define DibPtr(lpbi) (LPVOID)(DibColors(lpbi) + (UINT)(lpbi)->biClrUsed)
#endif
#define DibXYN(lpbi,pb,x,y,n) (LPVOID)( \
(BYTE *)(pb) + \
(UINT)((UINT)(x) * (UINT)(n) / 8u) + \
((DWORD)DibWidthBytesN(lpbi,n) * (DWORD)(UINT)(y)))
#define DibXY(lpbi,x,y) DibXYN(lpbi,DibPtr(lpbi),x,y,(lpbi)->biBitCount)
#endif
BYTE * CDib::GetPixelPointer(int x, int y)
{
return (BYTE *)(m_pBits + (x * GetBitCount() / 8) + (y * m_wWidthBytes));
}
BOOL CDib::GetPixelRGB(int x,
int y,
BYTE * pbRed,
BYTE * pbGreen,
BYTE * pbBlue)
{
BYTE * pb;
pb = (BYTE *)(m_pBits + (x * GetBitCount() / 8) + (y * m_wWidthBytes));
*pbBlue = *pb;
pb++;
*pbGreen = *pb;
pb++;
*pbRed = *pb;
return TRUE;
}
BOOL CDib::SetPixelRGB(int x, int y, BYTE bRed, BYTE bGreen, BYTE bBlue)
{
BYTE * pb;
pb = (BYTE *)(m_pBits + (x * GetBitCount() / 8) + (y * m_wWidthBytes));
switch (m_lpbi->biBitCount)
{
case 8:
case 16:
break;
case 24:
*pb = bBlue;
pb++;
*pb = bGreen;
pb++;
*pb = bRed;
break;
case 32: // BUGBUG: This isn't how it works???
*pb = bBlue;
pb++;
*pb = 0;
pb++;
*pb = bGreen;
pb++;
*pb = bRed;
break;
}
return TRUE;
}
BOOL CDib::SetPixel(int x, int y, BYTE bColorIndex)
{
BYTE * pb;
pb = (BYTE *)(m_pBits + (x * GetBitCount() / 8) + (y * m_wWidthBytes));
*pb = bColorIndex;
return TRUE;
}
CDib * CDib::DibFromTarga(LPCSTR pszFile)
{
CDib * pdib = NULL;
HANDLE hfile = INVALID_HANDLE_VALUE;
TARGAHEADER th;
int x;
int y;
DWORD dwRead;
BYTE bRed;
BYTE bGreen;
BYTE bBlue;
DWORD dwSize;
BYTE * pbTargaBits = NULL;
BYTE * pBits;
hfile = CreateFile(pszFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hfile == INVALID_HANDLE_VALUE)
{
Trace(("Couldn't open file %s", pszFile));
goto Error;
}
if (!ReadTargaHeader(hfile, &th))
{
Trace(("Couldn't read targa header for %s", pszFile));
goto Error;
}
pdib = new CDib();
if (pdib == NULL)
{
Trace(("Couldn't Create Dib for Targa - OOM"));
goto Error;
}
if (pdib->Create(th.wWidth, th.wHeight, 24, 0) == FALSE)
{
Trace(("Couldnt' create destinaton dib for Targa %s", pszFile));
goto Error;
}
dwSize = th.wWidth * th.wHeight * (th.bPixelSize / 8);
pbTargaBits = new BYTE[dwSize];
if (pbTargaBits == NULL)
{
Trace(("ERROR: Insufficent memory to decompress Targa."));
}
if (th.bImageType==10)
{
DecompressTarga (hfile, pbTargaBits, &th);
}
else
{
ReadFile(hfile, pbTargaBits, dwSize, &dwRead, NULL);
}
pBits = pbTargaBits;
if (!(th.bImageDesc & 32))
{
for (y = 0; y < th.wHeight; y++)
{
for (x = 0; x < th.wWidth; x++)
{
switch (th.bPixelSize)
{
case 32:
{
bBlue = *pBits++;
bGreen = *pBits++;
bRed = *pBits++;
pBits++;
}
break;
case 24:
{
bBlue = *pBits++;
bGreen = *pBits++;
bRed = *pBits++;
}
break;
case 16:
{
bRed = (((*(WORD*)pBits) & 0x7C00) >> 10) * 8;
bGreen = (((*(WORD*)pBits) & 0x03E0) >> 5) * 8;
bBlue = ((*(WORD*)pBits) & 0x001F) * 8;
pBits += sizeof(WORD);
}
break;
}
pdib->SetPixelRGB(x, y, bRed, bGreen, bBlue);
}
}
}
else
{
for (y = th.wHeight - 1; y >= 0; y--)
{
for (x = 0; x < th.wWidth; x++)
{
switch (th.bPixelSize)
{
case 32:
{
bBlue = *pBits++;
bGreen = *pBits++;
bRed = *pBits++;
pBits++;
}
break;
case 24:
{
bBlue = *pBits++;
bGreen = *pBits++;
bRed = *pBits++;
}
break;
case 16:
{
bRed = (((*(WORD*)pBits) & 0x7C00) >> 10) * 8;
bGreen = (((*(WORD*)pBits) & 0x03E0) >> 5) * 8;
bBlue = ((*(WORD*)pBits) & 0x001F) * 8;
pBits += sizeof(WORD);
}
break;
}
pdib->SetPixelRGB(x, y, bRed, bGreen, bBlue);
}
}
}
Cleanup:
if (hfile != INVALID_HANDLE_VALUE)
{
CloseHandle(hfile);
}
if (pbTargaBits != NULL)
{
delete [] pbTargaBits;
}
return pdib;
Error:
Trace(("ERROR: DibFromTarga"));
if (pdib != NULL)
{
GlobalFreePtr(pdib);
pdib = NULL;
}
goto Cleanup;
}
DWORD CDib::CalculateWriteSize()
{
DWORD dwRet;
dwRet = sizeof(BITMAPFILEHEADER);
dwRet += GetSize() + GetPaletteSize(m_lpbi) + GetSizeImage();
return dwRet;
}
BOOL CDib::WriteToStream(VOID * pv, PFNDIBWRITE pfnDibWrite)
{
BITMAPFILEHEADER bf;
DWORD dwSize;
DWORD dwWritten;
//
// Write out bitmap file header
//
dwSize = sizeof(bf) + GetSize() + GetPaletteSize(m_lpbi) + GetSizeImage();
bf.bfType = BFT_BITMAP;
bf.bfSize = dwSize;
bf.bfReserved1 = 0;
bf.bfReserved2 = 0;
bf.bfOffBits = GetSize() + GetPaletteSize(m_lpbi) + sizeof(bf);
(pfnDibWrite)(pv, &bf, sizeof(bf), &dwWritten);
dwSize = GetSize() + GetPaletteSize(m_lpbi) + GetSizeImage();
(pfnDibWrite)(pv, m_lpbi, dwSize, &dwWritten);
return TRUE;
}
BOOL CDib::Write(LPSTR psz)
{
HANDLE hfile;
hfile = CreateFile(psz,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
Write(hfile);
CloseHandle(hfile);
return TRUE;
}
BOOL CDib::Write(HANDLE hfile)
{
return WriteToStream(hfile, (PFNDIBWRITE)DibWrite);
}
CDib * CDib::DibFromBitmap(HBITMAP hbm,
DWORD biStyle,
WORD biBits,
HPALETTE hpal,
WORD wUsage)
{
BITMAP bm;
CDib * pdib = NULL;
BITMAPINFOHEADER bi;
BITMAPINFOHEADER * lpbi = NULL;
DWORD dwLen;
int nColors;
HDC hdc;
if (wUsage == 0)
{
wUsage = DIB_RGB_COLORS;
}
if (!hbm)
{
return NULL;
}
if (hpal == NULL)
{
hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
}
GetObject(hbm,sizeof(bm),(LPSTR)&bm);
GetObject(hpal,sizeof(nColors),(LPSTR)&nColors);
if (biBits == 0)
{
biBits = bm.bmPlanes * bm.bmBitsPixel;
}
nColors = (biBits < 16) ? nColors : 0;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bm.bmWidth;
bi.biHeight = bm.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = biBits;
bi.biCompression = biStyle;
bi.biSizeImage = bm.bmWidth * bm.bmHeight * (biBits / 8);
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = nColors;
bi.biClrImportant = nColors;
hdc = CreateCompatibleDC(NULL);
hpal = SelectPalette(hdc, hpal, FALSE);
RealizePalette(hdc); // why is this needed on a MEMORY DC? GDI bug??
pdib = new CDib();
if (pdib == NULL)
{
Trace(("ERROR: CDib::DibFromBitmap -- OOM -- "
"Couldn't create dib"));
goto Error;
}
dwLen = bi.biSize + pdib->GetPaletteSize(&bi) + bi.biSizeImage;
pdib->m_lpbi = (LPBITMAPINFOHEADER) new BYTE[dwLen];
if (pdib->m_lpbi)
{
Trace(("ERROR: CDib::DibFromBitmap -- OOM -- "
"Couldn't create bitmap info headr"));
goto Error;
}
*(pdib->m_lpbi) = bi;
/*
* call GetDIBits with a NON-NULL lpBits param, and actualy get the
* bits this time
*/
GetDIBits(hdc,
hbm,
0,
(WORD)bi.biHeight,
(LPSTR)pdib->m_lpbi +
(WORD)pdib->m_lpbi->biSize +
pdib->GetPaletteSize(pdib->m_lpbi),
(LPBITMAPINFO)(pdib->m_lpbi),
wUsage);
bi = *lpbi;
Cleanup:
SelectPalette(hdc,hpal,FALSE);
DeleteDC(hdc);
return pdib;
Error:
Trace(("ERROR: CDib::DibFromBitmap"));
if (pdib != NULL)
{
delete pdib;
pdib = NULL;
}
goto Cleanup;
}
BOOL CDib::SetColorRect(int x, int y, int iWidth, int iHeight, COLORREF cr)
{
int iy;
int ix;
BYTE bRed;
BYTE bGreen;
BYTE bBlue;
if (GetBitCount() < 24)
return FALSE;
if (x < 0)
{
x = 0;
}
if (x + iWidth > GetWidth())
{
iWidth = GetWidth() - x;
}
if (y < 0)
{
y = 0;
}
if (y + iHeight > GetHeight())
{
iHeight = GetHeight() - y;
}
bRed = GetRValue(cr);
bGreen = GetGValue(cr);
bBlue = GetBValue(cr);
for (iy = y; iy < y + iHeight; iy++)
{
for (ix = x; ix < x + iWidth; ix++)
{
SetPixelRGB(ix, iy, bRed, bGreen, bBlue);
}
}
return TRUE;
}
BOOL CDib::CopyDibInto(int x, int y, int iWidth, int iHeight, CDib * pdib)
{
int iy;
if (GetBitCount() != pdib->GetBitCount())
return FALSE;
if (x < 0)
{
x = 0;
}
if (x + iWidth > GetWidth())
{
iWidth = GetWidth() - x;
}
if (y < 0)
{
y = 0;
}
if (y + iHeight > GetHeight())
{
iHeight = GetHeight() - y;
}
// convert to width in bytes.
iWidth *= (GetBitCount() / 8);
for (iy = y; iy < y + iHeight; iy++)
{
memcpy (GetPixelPointer (x, iy),
pdib->GetPixelPointer (0, iy-y),
iWidth);
#if 0
// this doesn't work for 8bit images
for (ix = x; ix < x + iWidth; ix++)
{
pdib->GetPixelRGB(ix - x, iy - y, &bRed, &bGreen, &bBlue);
SetPixelRGB(ix, iy, bRed, bGreen, bBlue);
}
#endif
}
return TRUE;
}
BOOL CDib::CopyDibFrom (int x, int y, int iWidth, int iHeight, CDib * pdib)
{
int iy;
int ixDest;
int iyDest;
if (GetBitCount() != pdib->GetBitCount() ||
pdib->GetColorsUsed() > GetColorsUsed())
return FALSE;
// get the color table.
memcpy (GetColor(0), pdib->GetColor(0), pdib->GetColorsUsed()*sizeof(RGBQUAD));
ixDest = 0;
if (x < 0)
{
ixDest = -x;
x = 0;
}
if (x + iWidth > pdib->GetWidth())
{
iWidth = pdib->GetWidth() - x;
}
iyDest = 0;
if (y < 0)
{
iyDest = -y;
y = 0;
}
if (y + iHeight > pdib->GetHeight())
{
iHeight = pdib->GetHeight() - y;
}
// convert to width in bytes.
iWidth *= (GetBitCount() / 8);
for (iy = y; iy < y + iHeight; iy++)
{
memcpy (GetPixelPointer (ixDest, iyDest+iy-y),
pdib->GetPixelPointer (x, iy),
iWidth);
#if 0
// this doesn't work for 8bit images
for (ix = x; ix < x + iWidth; ix++)
{
pdib->GetPixelRGB(ix - x, iy - y, &bRed, &bGreen, &bBlue);
SetPixelRGB(ix, iy, bRed, bGreen, bBlue);
}
#endif
}
return TRUE;
}
LPBYTE CDib::GetBits()
{
return (LPBYTE)m_lpbi + (WORD)m_lpbi->biSize + GetPaletteSize(m_lpbi);
}
#if 0
BOOL CDib::IndexToLogPalette(LOGPALETTE * pLogPal)
{
BOOL bRet;
if ((GetBitCount() == 8) &&
!ChangeBitDepth(24, NULL))
{
TraceError(("CDib::IndexToLogPalette() -- "
"Changing bit depth from 8 to 24 bit failed"));
goto Error;
}
bRet = TRUE;
Cleanup:
return bRet;
Error:
TraceError(("CDib::ChangeBitDepth"));
bRet = FALSE;
goto Cleanup;
}
BOOL CDib::ChangeBitDepth(int iBitDepth, LOGPALETTE * pLogPal)
{
BOOL bRet;
CDib * pdib;
HPALETTE hpal = NULL;
LPBITMAPINFOHEADER lpbi;
LPBYTE pb;
WORD w;
if (pLogPal)
{
hpal = ::CreatePalette(pLogPal);
}
pdib = ReduceColor(this,
hpal,
NULL,
FALSE,
iBitDepth,
GetWidth(),
GetHeight());
if (pdib == NULL)
{
TraceError(("CDib::ChangeBitDepth() -- Unable to reduce color"));
goto Error;
}
// flip-flop values
lpbi = m_lpbi;
pb = m_pBits;
w = m_wWidthBytes;
m_lpbi = pdib->m_lpbi;
m_pBits = pdib->m_pBits;
m_wWidthBytes = pdib->m_wWidthBytes;
pdib->m_lpbi = lpbi;
pdib->m_pBits = pb;
pdib->m_wWidthBytes = w;
// deleting the "old bitdepth"
delete pdib;
bRet = TRUE;
Cleanup:
if (hpal != NULL)
{
DeleteObject(hpal);
}
return bRet;
Error:
TraceError(("CDib::ChangeBitDepth"));
bRet = FALSE;
goto Cleanup;
}
//
// This method uses GDI to speed up the conversion
// to 8bit.
//
//
CDib * ReduceColor(CDib *pSrc,
HPALETTE hPal,
RGBQUAD *pRGBSource,
BOOL fDither,
int nBitDepth,
int nWidth,
int nHeight)
{
CDib * pdib;
HDC hdc;
HBITMAP hbitmap;
HBITMAP hbmpold;
LPBYTE pBits;
HDRAWDIB hdd;
PALETTEENTRY palentry;
RGBQUAD * rgb;
int i;
//
// create our destination dib
//
pdib = new CDib();
if (pdib == NULL)
{
TraceError(("ReduceColor() -- OOM "));
return NULL;
}
if (nHeight == -1) nHeight = pSrc->GetHeight();
if (nWidth == -1) nWidth = pSrc->GetWidth();
pdib->Create(nWidth,
nHeight,
nBitDepth,
pRGBSource ? 256 : pSrc->GetColorsUsed());
if (nBitDepth < 16)
{
if (pRGBSource)
{
memcpy (pdib->GetColor(0), pRGBSource, sizeof(RGBQUAD)*256);
}
else if (pSrc->GetBitCount() < 16)
{
memcpy (pdib->GetColor(0), pSrc->GetColor(0), sizeof (RGBQUAD)*pSrc->GetColorsUsed());
}
else
{
// based off of the destination hpal create the destination
rgb = pdib->GetColor(0);
for (i = 0; i < (int)pdib->GetColorsUsed(); i ++)
{
GetPaletteEntries(hPal, i, 1, &palentry);
rgb[i].rgbBlue = palentry.peBlue;
rgb[i].rgbGreen = palentry.peGreen;
rgb[i].rgbRed = palentry.peRed;
rgb[i].rgbReserved = 0;
}
}
}
hdc = CreateCompatibleDC(NULL);
if (hPal) SelectPalette (hdc, hPal, FALSE);
RealizePalette (hdc);
hbitmap = CreateDIBSection (hdc,
(LPBITMAPINFO)pdib->GetInfoHeader(),
DIB_RGB_COLORS,
(void **)&pBits,
NULL,0);
hbmpold = (HBITMAP)SelectObject (hdc, hbitmap);
if (hPal) SelectPalette (hdc, hPal, FALSE);
RealizePalette (hdc);
if (fDither)
{
hdd = DrawDibOpen();
if (hPal) DrawDibSetPalette (hdd, hPal);
DrawDibDraw (hdd, hdc,
0,0,pdib->GetWidth(),pdib->GetHeight(),
pSrc->GetInfoHeader(),pSrc->GetBits(),
0,0,pSrc->GetWidth(),pSrc->GetHeight(),
0);
DrawDibClose (hdd);
}
else
{
StretchDIBits (hdc,
0,0,pdib->GetWidth(),pdib->GetHeight(),
0,0,pSrc->GetWidth(),pSrc->GetHeight(),
pSrc->GetBits(),
(LPBITMAPINFO)pSrc->GetInfoHeader(),
DIB_RGB_COLORS,
SRCCOPY);
}
memcpy (pdib->GetBits(), pBits, pdib->GetSizeImage());
SelectObject (hdc, hbmpold);
DeleteObject (hbitmap);
SelectObject (hdc, GetStockObject (DEFAULT_PALETTE));
DeleteDC (hdc);
return pdib;
}
#endif