#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