2602 lines
58 KiB
C++
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
|