362 lines
9.6 KiB
C++
362 lines
9.6 KiB
C++
#ifndef _DATADUMP
|
|
#define _DATADUMP
|
|
|
|
#define MAX_PAD_DATA 1048576 // 1 meg of padding
|
|
|
|
typedef struct _DATA_DESCRIPTION {
|
|
|
|
DWORD dwDataSize;
|
|
DWORD dwbpp;
|
|
DWORD dwWidth;
|
|
DWORD dwHeight;
|
|
PBYTE pRawData;
|
|
|
|
}DATA_DESCRIPTION,*PDATA_DESCRIPTION;
|
|
|
|
class CDATADUMP {
|
|
public:
|
|
CDATADUMP()
|
|
{
|
|
m_pDIB = NULL;
|
|
m_pDIBHeader = NULL;
|
|
}
|
|
~CDATADUMP()
|
|
{
|
|
FreeDIBMemory();
|
|
}
|
|
|
|
BOOL DumpDataToBitmap(LPTSTR szBitmapFileName,
|
|
PDATA_DESCRIPTION pDataDesc)
|
|
{
|
|
if(!AllocateDIBMemory(pDataDesc))
|
|
return FALSE;
|
|
|
|
if(!WriteDIBHeader(pDataDesc))
|
|
return FALSE;
|
|
|
|
if(!WriteRawDataToDIB(pDataDesc))
|
|
return FALSE;
|
|
|
|
if(!WriteDIBToDisk(szBitmapFileName))
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL DumpDataToDIB(PDATA_DESCRIPTION pDataDesc)
|
|
{
|
|
if(!AllocateDIBMemory(pDataDesc))
|
|
return FALSE;
|
|
|
|
if(!WriteDIBHeader(pDataDesc))
|
|
return FALSE;
|
|
|
|
if(!WriteRawDataToDIB(pDataDesc))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
PBYTE GetDIBPtr()
|
|
{
|
|
return m_pDIB;
|
|
}
|
|
|
|
BOOL OwnDIBPtr(PBYTE *ppOUTDIB)
|
|
{
|
|
if(NULL != m_pDIB){
|
|
|
|
//
|
|
// assign the DIB pointer to new owner's pointer
|
|
// new owner must free allocated DIB
|
|
//
|
|
|
|
*ppOUTDIB = m_pDIB;
|
|
|
|
//
|
|
// set our pointer to NULL, so we don't try to
|
|
// free the new owner's memory.
|
|
//
|
|
|
|
m_pDIB = NULL;
|
|
m_pDIBHeader = NULL;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
private:
|
|
|
|
PBYTE m_pDIB;
|
|
BITMAPINFOHEADER *m_pDIBHeader;
|
|
|
|
VOID FreeDIBMemory(){
|
|
if (NULL != m_pDIB){
|
|
LocalFree(m_pDIB);
|
|
m_pDIB = NULL;
|
|
m_pDIBHeader = NULL;
|
|
}
|
|
}
|
|
|
|
BOOL AllocateDIBMemory(PDATA_DESCRIPTION pDataDesc)
|
|
{
|
|
m_pDIB = (PBYTE)LocalAlloc(LPTR,sizeof(BITMAPINFOHEADER) +
|
|
(sizeof(RGBQUAD) * 256) +
|
|
pDataDesc->dwDataSize +
|
|
MAX_PAD_DATA);
|
|
if (NULL == m_pDIB)
|
|
return FALSE;
|
|
|
|
m_pDIBHeader = (BITMAPINFOHEADER*)m_pDIB;
|
|
return TRUE;
|
|
}
|
|
|
|
LONG RawWidthBytes()
|
|
{
|
|
switch(m_pDIBHeader->biBitCount){
|
|
case 1:
|
|
return (LONG)((m_pDIBHeader->biWidth + 7) / 8);
|
|
break;
|
|
case 8:
|
|
return (LONG)(m_pDIBHeader->biWidth);
|
|
break;
|
|
case 24:
|
|
return (LONG)(m_pDIBHeader->biWidth * 3);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
BOOL WriteDIBHeader(PDATA_DESCRIPTION pDataDesc)
|
|
{
|
|
if(NULL == m_pDIB)
|
|
return FALSE;
|
|
|
|
m_pDIBHeader->biSize = sizeof(BITMAPINFOHEADER);
|
|
m_pDIBHeader->biBitCount = (WORD)pDataDesc->dwbpp;
|
|
m_pDIBHeader->biCompression = BI_RGB;
|
|
m_pDIBHeader->biHeight = pDataDesc->dwHeight;
|
|
m_pDIBHeader->biWidth = pDataDesc->dwWidth;
|
|
m_pDIBHeader->biSizeImage = pDataDesc->dwDataSize;
|
|
m_pDIBHeader->biPlanes = 1;
|
|
m_pDIBHeader->biXPelsPerMeter = 0;
|
|
m_pDIBHeader->biYPelsPerMeter = 0;
|
|
|
|
switch(pDataDesc->dwbpp){
|
|
case 1:
|
|
m_pDIBHeader->biClrImportant= 2;
|
|
m_pDIBHeader->biClrUsed = 2;
|
|
break;
|
|
case 8:
|
|
m_pDIBHeader->biClrImportant= 256;
|
|
m_pDIBHeader->biClrUsed = 256;
|
|
break;
|
|
case 24:
|
|
m_pDIBHeader->biClrImportant= 0;
|
|
m_pDIBHeader->biClrUsed = 0;
|
|
break;
|
|
default:
|
|
FreeDIBMemory();
|
|
return FALSE;
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL BuildPalette(RGBQUAD *pPalette)
|
|
{
|
|
BYTE i = 0;
|
|
switch(m_pDIBHeader->biBitCount){
|
|
case 1: // black and white palette
|
|
{
|
|
pPalette[0].rgbBlue = 0;
|
|
pPalette[0].rgbGreen = 0;
|
|
pPalette[0].rgbRed = 0;
|
|
pPalette[0].rgbReserved = 0;
|
|
|
|
pPalette[1].rgbBlue = 255;
|
|
pPalette[1].rgbGreen = 255;
|
|
pPalette[1].rgbRed = 255;
|
|
pPalette[1].rgbReserved = 0;
|
|
}
|
|
break;
|
|
case 8: // grayscale palette
|
|
{
|
|
for (i = 0; i < 255;i++) {
|
|
pPalette[i].rgbBlue = i;
|
|
pPalette[i].rgbGreen = i;
|
|
pPalette[i].rgbRed = i;
|
|
pPalette[i].rgbReserved = 0;
|
|
}
|
|
}
|
|
break;
|
|
case 24:
|
|
default:
|
|
break;
|
|
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL WriteRawDataToDIB(PDATA_DESCRIPTION pDataDesc)
|
|
{
|
|
//
|
|
// create a palette (for 1-bit, and 8-bit images)
|
|
//
|
|
|
|
RGBQUAD *pPalette = (RGBQUAD*)LocalAlloc(LPTR,(sizeof(RGBQUAD) * m_pDIBHeader->biClrUsed));
|
|
BuildPalette(pPalette);
|
|
|
|
//
|
|
// insert palette into DIB memory block, past BITMAPINFOHEADER
|
|
//
|
|
|
|
PBYTE pDest = m_pDIB + sizeof(BITMAPINFOHEADER);
|
|
memcpy(pDest,
|
|
pPalette,
|
|
(sizeof(RGBQUAD) * m_pDIBHeader->biClrUsed));
|
|
|
|
if(NULL != pPalette)
|
|
LocalFree(pPalette);
|
|
|
|
//
|
|
// insert raw bits to DIB memory block
|
|
// (DWORD alignment will happen here too)
|
|
//
|
|
|
|
pDest = m_pDIB + sizeof(BITMAPINFOHEADER) + (m_pDIBHeader->biClrUsed * sizeof(RGBQUAD));
|
|
PBYTE pRawData = pDataDesc->pRawData;
|
|
LONG lRawWidthBytes = RawWidthBytes();
|
|
LONG PadWidthBytes = ((((m_pDIBHeader->biWidth * m_pDIBHeader->biBitCount) + 31) / 8) & 0xfffffffc) - (lRawWidthBytes);
|
|
|
|
//
|
|
// update image size in BITMAPINFOHEADER, padding will increase total image size
|
|
//
|
|
|
|
m_pDIBHeader->biSizeImage += (PadWidthBytes * m_pDIBHeader->biHeight);
|
|
PBYTE pPadData = new BYTE[PadWidthBytes]; //(PBYTE)LocalAlloc(LPTR, PadWidthBytes);
|
|
if(NULL != pPadData) {
|
|
memset(pPadData,0,PadWidthBytes); // clear padded byte memory...
|
|
Trace(TEXT("Copying Line data (%d total lines)"),m_pDIBHeader->biHeight);
|
|
for(LONG Line = 1; Line <= m_pDIBHeader->biHeight; Line++) {
|
|
// Trace(TEXT("Copy Line %d of %d"),Line,m_pDIBHeader->biHeight);
|
|
|
|
//
|
|
// copy a raw data line to DIB
|
|
//
|
|
|
|
memcpy(pDest,pRawData,lRawWidthBytes);
|
|
|
|
//
|
|
// move destination pointer (RawWidthBytes)
|
|
//
|
|
|
|
pDest += lRawWidthBytes;
|
|
|
|
//
|
|
// copy a padded buffer to DIB
|
|
//
|
|
|
|
memcpy(pDest,pPadData,PadWidthBytes);
|
|
|
|
//
|
|
// move destination pointer (PadWidthBytes)
|
|
//
|
|
|
|
pDest += PadWidthBytes;
|
|
|
|
//
|
|
// move src pointer RawWidthBytes only
|
|
//
|
|
|
|
pRawData += lRawWidthBytes;
|
|
}
|
|
Trace(TEXT("Done... data copy complete..for %d lines"),(Line - 1));
|
|
|
|
//
|
|
// free padded bytes memory
|
|
//
|
|
|
|
delete pPadData; //LocalFree(pPadData);
|
|
|
|
} else
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
VOID Trace(LPCTSTR format,...)
|
|
{
|
|
TCHAR Buffer[1024];
|
|
va_list arglist;
|
|
va_start(arglist, format);
|
|
wvsprintf(Buffer, format, arglist);
|
|
va_end(arglist);
|
|
OutputDebugString(Buffer);
|
|
OutputDebugString(TEXT("\n"));
|
|
}
|
|
|
|
BOOL WriteDIBToDisk(LPTSTR szBitmapFileName)
|
|
{
|
|
//
|
|
// create bitmap file on disk
|
|
//
|
|
|
|
HANDLE hBitmapFile = CreateFile(szBitmapFileName,
|
|
GENERIC_READ | GENERIC_WRITE, // Access mask
|
|
0, // Share mode
|
|
NULL, // SA
|
|
CREATE_ALWAYS, // Create disposition
|
|
FILE_ATTRIBUTE_NORMAL, // Attributes
|
|
NULL );
|
|
if(NULL == hBitmapFile)
|
|
return FALSE;
|
|
|
|
//
|
|
// create bitmap file header
|
|
//
|
|
|
|
BITMAPFILEHEADER BitmapFileHeader;
|
|
BitmapFileHeader.bfOffBits = (sizeof(BITMAPFILEHEADER) +
|
|
sizeof(BITMAPINFOHEADER) +
|
|
(m_pDIBHeader->biClrUsed * sizeof(RGBQUAD)));
|
|
|
|
BitmapFileHeader.bfReserved1 = 0;
|
|
BitmapFileHeader.bfReserved2 = 0;
|
|
BitmapFileHeader.bfSize = (BitmapFileHeader.bfOffBits +
|
|
m_pDIBHeader->biSizeImage);
|
|
|
|
BitmapFileHeader.bfType = MAKEWORD('B','M');
|
|
|
|
DWORD dwWritten = 0;
|
|
|
|
//
|
|
// write bitmap file header to open bitmap file
|
|
//
|
|
|
|
WriteFile(hBitmapFile,&BitmapFileHeader,sizeof(BITMAPFILEHEADER),&dwWritten,NULL);
|
|
|
|
//
|
|
// write DIB memory to opend bitmap file
|
|
//
|
|
|
|
WriteFile(hBitmapFile,
|
|
m_pDIB,
|
|
(sizeof(BITMAPINFOHEADER) + m_pDIBHeader->biSizeImage + (sizeof(RGBQUAD) * m_pDIBHeader->biClrUsed)),
|
|
&dwWritten,
|
|
NULL);
|
|
|
|
|
|
|
|
CloseHandle(hBitmapFile);
|
|
|
|
return TRUE;
|
|
}
|
|
protected:
|
|
|
|
};
|
|
|
|
|
|
#endif
|