2012-09-08 31 views
1

我試圖將內存DC保存到位圖文件。但我不能爲以下獲得關於大小合適的值:無法將hdc正確保存到位圖

infoHeader.biSizeImage 

fileHeader.bfSize 


fileHeader.bfOffBits 

WriteFile(hFile, &fileHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL); 

WriteFile(hFile, &infoHeader, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL); 

WriteFile(hFile, pPixels, info.bmiHeader.biSizeImage, &dwBytesWritten, NULL); 

我可以得到一個文件,但我不能打開它,因爲它抱怨壞了,或者不再受支持。

大約有保存爲BMP許多來源,但其中許多人有大小不同的值。有些還包含調色板信息。我十分困惑。

可能有人指出如何填寫正確的信息?

static void SaveAsBmp(TCHAR *fileName) 
{ 
HDC hdcView = GetDC(hwndView); 
HDC memDC = CreateCompatibleDC(hdcView); 

RECT rcView; 
GetClientRect(hwndView, &rcView); 

int rcView_dx = rcView.right - rcView.left; 
int rcView_dy = rcView.bottom - rcView.top; 

HBITMAP hMemBmp = CreateCompatibleBitmap(hdcView, rcView_dx, rcView_dy); 
HBITMAP hOldBmp = (HBITMAP)SelectObject(memDC, hMemBmp); 

BitBlt(memDC, 0, 0, rcView_dx, rcView_dy, hdcView, 0, 0, SRCCOPY); 

//---------- 

BITMAP bmp; 
GetObject(hMemBmp, sizeof(BITMAP), &bmp); 

//---------- 

WORD wBits = (WORD)(bmp.bmBitsPixel * bmp.bmPlanes); 

if(wBits <= 1)             
    wBits = 1;    
else if(wBits <= 4)        
    wBits = 4;    
else if(wBits <= 8)        
    wBits = 8;    
else if (wBits <= 16) 
    wBits = 16; 
else if (wBits <= 24) 
    wBits = 24; 
else wBits = 32; 

//---------- 

BITMAPINFOHEADER infoHeader; 
BITMAPINFO info; 
info.bmiHeader = infoHeader; 

infoHeader.biSize = sizeof(BITMAPINFOHEADER);  
infoHeader.biWidth = bmp.bmWidth; 
infoHeader.biHeight = bmp.bmHeight;  
infoHeader.biPlanes = bmp.bmPlanes;  
infoHeader.biBitCount = bmp.bmBitsPixel;  
infoHeader.biCompression = BI_RGB; 

infoHeader.biSizeImage = 2 * ((bmp.bmWidth * bmp.bmBitsPixel + 15)/16) * bmp.bmPlanes * bmp.bmHeight; 
infoHeader.biXPelsPerMeter = 0; 
infoHeader.biYPelsPerMeter = 0; 
infoHeader.biClrUsed = 0; 
infoHeader.biClrImportant = 0; 

RGBQUAD *pPixels = new RGBQUAD[bmp.bmWidth * bmp.bmWidth]; 
GetDIBits(memDC, hMemBmp, 0, bmp.bmWidth, pPixels, &info, DIB_RGB_COLORS); 

BITMAPFILEHEADER fileHeader; 
fileHeader.bfType = 0x4d42; 
fileHeader.bfSize = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + info.bmiHeader.biSizeImage); 
fileHeader.bfReserved1 = 0; 
fileHeader.bfReserved2 = 0; 
fileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + info.bmiHeader.biSize); 

HANDLE hFile = CreateFile(fileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 

DWORD dwBytesWritten; 

WriteFile(hFile, &fileHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL); 
WriteFile(hFile, &infoHeader, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL); 
WriteFile(hFile, pPixels, info.bmiHeader.biSizeImage, &dwBytesWritten, NULL); 

CloseHandle(hFile); 

delete pPixels; 

SelectObject(memDC, hOldBmp); 
DeleteObject(hMemBmp); 
DeleteDC(memDC); 

回答

0

infoHeader.biSizeImage = 2 *((* bmp.bmWidth bmp.bmBitsPixel + 15)/ 16)* * bmp.bmPlanes bmp.bmHeight;

不看這裏,應該是bmp.bmBitsPixel >> 3,假設它是24或32。也就是說,它的每個像素的位數和你正在使用它,就好像它是每像素字節。

一般的代碼看起來不錯,你應該檢查而使用調試器變量找錯配(或粘貼在這裏他們,ESP。BITMAPINFOHEADER)。

請注意,您可能以一種不同的方式完成它:您可以使用CreateDIBSection以及您感興趣的格式(例如24 bpp RGB),您可以立即接收原始指針。然後將數據分塊到這個位圖中,因爲你已經擁有了你需要的所有東西,所以你不需要調用GetObject。而且,GetObject可能會返回DIBSECTION格式,並已準備好使用BITMAPINFOHEADER。它們都是一樣的,只是更簡單。

+0

最後,使用http://msdn.microsoft.com/en-us/library/windows/desktop/dd145119%28v=vs.85%29.aspx,它的工作原理 – user565739