raw data to bitmap
-
Hello. I have posted a question about this before but i wrote it bad. So i try again. I'm working with a program that storage BMP and WAV files in one file. I'm almost finished with it but I want to make it show BMP files directly from the packed file without extracting it. I have tried many times but I can't make function to put BITMAPINFOHEADER and BITMAPINFO correct data. /////////////////////////////////////////////////////////////////////////////// LPTSTR szFileName = "C:\\Min Projekt\\MittPixelTest\\3_16.bmp"; CFile test; test.Open(szFileName, CFile::modeRead); DWORD m_nMaxSize = test.GetLength(); void *pBuf = (BYTE *) malloc(sizeof(BYTE) * m_nMaxSize); test.ReadHuge((LPVOID) pBuf, m_nMaxSize); LoadBMPImage(pBuf, m_nMaxSize, myBmp, &myPalette); /////////////////////////////////////////////////////////////////////////////// BOOL CMyArchiveDlg::LoadBMPImage(void* vBits, DWORD len, CBitmap &bitmap, CPalette *pPal) { BITMAPFILEHEADER bmfHeader; // Read file header if (!memcpy((LPSTR)&bmfHeader, vBits, sizeof(bmfHeader))) return FALSE; // File type should be 'BM' if (bmfHeader.bfType != ((WORD) ('M' << 8) | 'B')) return FALSE; // Get length of the remainder of the file and allocate memory DWORD nPackedDIBLen = len - sizeof(BITMAPFILEHEADER); HGLOBAL hDIB = ::GlobalAlloc(GMEM_FIXED, nPackedDIBLen); if (hDIB == 0) return FALSE; // Read the remainder of the bitmap file. if (!memcpy((LPSTR)hDIB, vBits, nPackedDIBLen)) { ::GlobalFree(hDIB); return FALSE; } BITMAPINFOHEADER &bmiHeader = *(LPBITMAPINFOHEADER)hDIB ; // Gets wrong data BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB ; // If bmiHeader.biClrUsed is zero we have to infer the number // of colors from the number of bits used to specify it. int nColors = bmiHeader.biClrUsed ? bmiHeader.biClrUsed : 1 << bmiHeader.biBitCount; // Color value is to high!! LPVOID lpDIBBits; if( bmInfo.bmiHeader.biBitCount > 8 ) lpDIBBits = (LPVOID)((LPDWORD)(bmInfo.bmiColors + bmInfo.bmiHeader.biClrUsed) + ((bmInfo.bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0)); else lpDIBBits = (LPVOID)(bmInfo.bmiColors + nColors); // Create the logical palette if( pPal != NULL ) { // Create the palette if( nColors <= 256 ) { UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors); LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize]; pLP->palVersion = 0x300; pLP->palNumEntries = nColors; for( int i=0; i < nColors; i++) {
-
Hello. I have posted a question about this before but i wrote it bad. So i try again. I'm working with a program that storage BMP and WAV files in one file. I'm almost finished with it but I want to make it show BMP files directly from the packed file without extracting it. I have tried many times but I can't make function to put BITMAPINFOHEADER and BITMAPINFO correct data. /////////////////////////////////////////////////////////////////////////////// LPTSTR szFileName = "C:\\Min Projekt\\MittPixelTest\\3_16.bmp"; CFile test; test.Open(szFileName, CFile::modeRead); DWORD m_nMaxSize = test.GetLength(); void *pBuf = (BYTE *) malloc(sizeof(BYTE) * m_nMaxSize); test.ReadHuge((LPVOID) pBuf, m_nMaxSize); LoadBMPImage(pBuf, m_nMaxSize, myBmp, &myPalette); /////////////////////////////////////////////////////////////////////////////// BOOL CMyArchiveDlg::LoadBMPImage(void* vBits, DWORD len, CBitmap &bitmap, CPalette *pPal) { BITMAPFILEHEADER bmfHeader; // Read file header if (!memcpy((LPSTR)&bmfHeader, vBits, sizeof(bmfHeader))) return FALSE; // File type should be 'BM' if (bmfHeader.bfType != ((WORD) ('M' << 8) | 'B')) return FALSE; // Get length of the remainder of the file and allocate memory DWORD nPackedDIBLen = len - sizeof(BITMAPFILEHEADER); HGLOBAL hDIB = ::GlobalAlloc(GMEM_FIXED, nPackedDIBLen); if (hDIB == 0) return FALSE; // Read the remainder of the bitmap file. if (!memcpy((LPSTR)hDIB, vBits, nPackedDIBLen)) { ::GlobalFree(hDIB); return FALSE; } BITMAPINFOHEADER &bmiHeader = *(LPBITMAPINFOHEADER)hDIB ; // Gets wrong data BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB ; // If bmiHeader.biClrUsed is zero we have to infer the number // of colors from the number of bits used to specify it. int nColors = bmiHeader.biClrUsed ? bmiHeader.biClrUsed : 1 << bmiHeader.biBitCount; // Color value is to high!! LPVOID lpDIBBits; if( bmInfo.bmiHeader.biBitCount > 8 ) lpDIBBits = (LPVOID)((LPDWORD)(bmInfo.bmiColors + bmInfo.bmiHeader.biClrUsed) + ((bmInfo.bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0)); else lpDIBBits = (LPVOID)(bmInfo.bmiColors + nColors); // Create the logical palette if( pPal != NULL ) { // Create the palette if( nColors <= 256 ) { UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors); LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize]; pLP->palVersion = 0x300; pLP->palNumEntries = nColors; for( int i=0; i < nColors; i++) {
First: if (!memcpy((LPSTR)hDIB, vBits, nPackedDIBLen)) well normaly I would have called GlobalLock() to get the pointer, but hDIB is realy a pointer so this should work ( LPSTR should be LPVOID ). The problem with the line is that vBits points to the start of the buffer, where the BITMAPFILEHEADER is stored and you are trying to copy the information following it: if (!memcpy((LPSTR)hDIB, (LPBYTE)vBits + sizeof(BITMAPFILEHEADER), nPackedDIBLen)) That should fix the following: BITMAPINFOHEADER &bmiHeader = *(LPBITMAPINFOHEADER)hDIB ; // Gets wrong data BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB ; (interesting use of references!) Try takeing a look at the CDibData article; I wrote the class so that it could take a handle to a DIB (see CDibData::Attach()) just like the clipboard. INTP