GetDIBits() function call fails
-
Anybody see what the problem is with this code? GetDIBits fails, and when I call GetLastError(), it tells me that Windows "ERROR_FILE_NOT_FOUND".
GetClientRect(hDlg, &rc); // Get the rectangle dimensions of the Dialog Box hdc = GetDC(hDlg); // Get a handle to the Drawing Context of the Dialog Box rc.bottom -= (GetSystemMetrics(SM_CYHSCROLL)+GetSystemMetrics(SM_CYEDGE)); hSavedXYContext = CreateCompatibleDC(hdc); // Create a drawing context that is compatiable to // the drawing context on the screen hSavedXYBitmap = CreateCompatibleBitmap(hdc, rc.right-rc.left,rc.bottom-rc.top); hTheDCsOriginalBitmap = (HBITMAP)SelectObject(hSavedXYContext, hSavedXYBitmap); BitBlt(hSavedXYContext,0,0,rc.right-rc.left, rc.bottom-rc.top,hdc,0,0,SRCCOPY); hSavedXYBitmap = (HBITMAP)SelectObject(hSavedXYContext, hTheDCsOriginalBitmap); // As far as I can tell above code does exactly what it should. It grabs a handle to the drawing // context, along with the rectangular coordinates of the drawing context. Then after creating // a compatible bitmap, and selecting it into the saved drawing context, before blting it in. // Now we have the DC saved to hSavedContext, so we need to take it and create a // bitmap file that we can open in Paint. // This involves creating a bmp structure then writing it to a file. GetObject(hSavedXYBitmap,sizeof(BITMAP),(LPSTR)(&bmp)); cClrBits = (WORD)(bmp.bmPlanes*bmp.bmBitsPixel); cClrBits = 4; pbmi = (PBITMAPINFO) LocalAlloc(LPTR,sizeof(BITMAPINFOHEADER)); // Initialize the fields in the BITMAPINFO structure. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); pbmi->bmiHeader.biWidth = bmp.bmWidth; pbmi->bmiHeader.biHeight = bmp.bmHeight; pbmi->bmiHeader.biPlanes = bmp.bmPlanes; pbmi->bmiHeader.biBitCount =4; pbmi->bmiHeader.biCompression = BI_RGB; pbmi->bmiHeader.biSizeImage = (pbmi->bmiHeader.biWidth + 15)/16 * pbmi->bmiHeader.biHeight * 4; pbmi->bmiHeader.biClrImportant = 0; // Make sure to fill in the rest of the BITMAP info in the header. pBitmapInfoHeader = (PBITMAPINFOHEADER)pbmi; lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED,pbmi->bmiHeader.biSizeImage); test = GetDIBits(hdc
-
Anybody see what the problem is with this code? GetDIBits fails, and when I call GetLastError(), it tells me that Windows "ERROR_FILE_NOT_FOUND".
GetClientRect(hDlg, &rc); // Get the rectangle dimensions of the Dialog Box hdc = GetDC(hDlg); // Get a handle to the Drawing Context of the Dialog Box rc.bottom -= (GetSystemMetrics(SM_CYHSCROLL)+GetSystemMetrics(SM_CYEDGE)); hSavedXYContext = CreateCompatibleDC(hdc); // Create a drawing context that is compatiable to // the drawing context on the screen hSavedXYBitmap = CreateCompatibleBitmap(hdc, rc.right-rc.left,rc.bottom-rc.top); hTheDCsOriginalBitmap = (HBITMAP)SelectObject(hSavedXYContext, hSavedXYBitmap); BitBlt(hSavedXYContext,0,0,rc.right-rc.left, rc.bottom-rc.top,hdc,0,0,SRCCOPY); hSavedXYBitmap = (HBITMAP)SelectObject(hSavedXYContext, hTheDCsOriginalBitmap); // As far as I can tell above code does exactly what it should. It grabs a handle to the drawing // context, along with the rectangular coordinates of the drawing context. Then after creating // a compatible bitmap, and selecting it into the saved drawing context, before blting it in. // Now we have the DC saved to hSavedContext, so we need to take it and create a // bitmap file that we can open in Paint. // This involves creating a bmp structure then writing it to a file. GetObject(hSavedXYBitmap,sizeof(BITMAP),(LPSTR)(&bmp)); cClrBits = (WORD)(bmp.bmPlanes*bmp.bmBitsPixel); cClrBits = 4; pbmi = (PBITMAPINFO) LocalAlloc(LPTR,sizeof(BITMAPINFOHEADER)); // Initialize the fields in the BITMAPINFO structure. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); pbmi->bmiHeader.biWidth = bmp.bmWidth; pbmi->bmiHeader.biHeight = bmp.bmHeight; pbmi->bmiHeader.biPlanes = bmp.bmPlanes; pbmi->bmiHeader.biBitCount =4; pbmi->bmiHeader.biCompression = BI_RGB; pbmi->bmiHeader.biSizeImage = (pbmi->bmiHeader.biWidth + 15)/16 * pbmi->bmiHeader.biHeight * 4; pbmi->bmiHeader.biClrImportant = 0; // Make sure to fill in the rest of the BITMAP info in the header. pBitmapInfoHeader = (PBITMAPINFOHEADER)pbmi; lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED,pbmi->bmiHeader.biSizeImage); test = GetDIBits(hdc
You have to check all the values passed to
GetDIBits
very carefully. That functions is very touchy and will fail if a single bit is not correct. I do not think the error message has anything to do with the code you are showing, asGeDIBits
will often fail without generating any error at all. See CDibData[^], it might help. Note:CDibData
has a minor bug that I still have not updated, but it has been a while since I played with graphics.INTP "Program testing can be used to show the presence of bugs, but never to show their absence."Edsger Dijkstra
-
Anybody see what the problem is with this code? GetDIBits fails, and when I call GetLastError(), it tells me that Windows "ERROR_FILE_NOT_FOUND".
GetClientRect(hDlg, &rc); // Get the rectangle dimensions of the Dialog Box hdc = GetDC(hDlg); // Get a handle to the Drawing Context of the Dialog Box rc.bottom -= (GetSystemMetrics(SM_CYHSCROLL)+GetSystemMetrics(SM_CYEDGE)); hSavedXYContext = CreateCompatibleDC(hdc); // Create a drawing context that is compatiable to // the drawing context on the screen hSavedXYBitmap = CreateCompatibleBitmap(hdc, rc.right-rc.left,rc.bottom-rc.top); hTheDCsOriginalBitmap = (HBITMAP)SelectObject(hSavedXYContext, hSavedXYBitmap); BitBlt(hSavedXYContext,0,0,rc.right-rc.left, rc.bottom-rc.top,hdc,0,0,SRCCOPY); hSavedXYBitmap = (HBITMAP)SelectObject(hSavedXYContext, hTheDCsOriginalBitmap); // As far as I can tell above code does exactly what it should. It grabs a handle to the drawing // context, along with the rectangular coordinates of the drawing context. Then after creating // a compatible bitmap, and selecting it into the saved drawing context, before blting it in. // Now we have the DC saved to hSavedContext, so we need to take it and create a // bitmap file that we can open in Paint. // This involves creating a bmp structure then writing it to a file. GetObject(hSavedXYBitmap,sizeof(BITMAP),(LPSTR)(&bmp)); cClrBits = (WORD)(bmp.bmPlanes*bmp.bmBitsPixel); cClrBits = 4; pbmi = (PBITMAPINFO) LocalAlloc(LPTR,sizeof(BITMAPINFOHEADER)); // Initialize the fields in the BITMAPINFO structure. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); pbmi->bmiHeader.biWidth = bmp.bmWidth; pbmi->bmiHeader.biHeight = bmp.bmHeight; pbmi->bmiHeader.biPlanes = bmp.bmPlanes; pbmi->bmiHeader.biBitCount =4; pbmi->bmiHeader.biCompression = BI_RGB; pbmi->bmiHeader.biSizeImage = (pbmi->bmiHeader.biWidth + 15)/16 * pbmi->bmiHeader.biHeight * 4; pbmi->bmiHeader.biClrImportant = 0; // Make sure to fill in the rest of the BITMAP info in the header. pBitmapInfoHeader = (PBITMAPINFOHEADER)pbmi; lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED,pbmi->bmiHeader.biSizeImage); test = GetDIBits(hdc
I see a few problems -
TheDelChop wrote:
GetObject(hSavedXYBitmap,sizeof(BITMAP),(LPSTR)(&bmp));
Irrelevent, but cast to a LPSTR?? No cast to a void pointer is necessary ;) Problems: Creating a BITMAPINFO the size of a BITMAPINFOHEADER. Using the planes value from the DDB when it HAS to be 1 in a DIB. bmiHeader.biSizeImage is calculated wrong - rows of pixel data in a DIB need to be DWORD aligned. You've provided no color table (16-colors) for your destination 4-bit DIB The resulting GetDIBits call should fail based on the above. Something like this maybe will get you closer:
...
int nNumColors = 1 << cClrBits;LONG lBytesPerRow = (((bmp.bmWidth * (long)cClrBits + 31L) & (~31L)) / 8L);
BYTE* pBitmapBits;
LONG SizeOfBitmapInfo = sizeof(BITMAPINFO) + ((nNumColors - 1) * sizeof(RGBQUAD));
BITMAPINFO *pbmi = (PBITMAPINFO) LocalAlloc(LPTR, SizeOfBitmapInfo);
memset(pbmi, 0, SizeOfBitmapInfo);
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = bmp.bmWidth;
pbmi->bmiHeader.biHeight = bmp.bmHeight;
pbmi->bmiHeader.biPlanes = 1;
pbmi->bmiHeader.biBitCount = cClrBits;
pbmi->bmiHeader.biCompression = BI_RGB;
pbmi->bmiHeader.biSizeImage = lBytesPerRow * bmp.bmHeight;
//pbmi->bmiHeader.biXPelsPerMeter = 0;
//pbmi->bmiHeader.biYPelsPerMeter = 0;
//pbmi->bmiHeader.biClrUsed = 0;
//pbmi->bmiHeader.biClrImportant = 0;// I forget if you need to do this before GetDIBits() :doh:
//// Initialize color table
//for (int i = 0; i < nNumColors; i++)
//{
// pbmi->bmiColors[i].rgbBlue = ;
// pbmi->bmiColors[i].rgbGreen = ;
// pbmi->bmiColors[i].rgbRed = ;
// pbmi->bmiColors[i].rgbReserved = 0;
//}pBitmapInfoHeader = (PBITMAPINFOHEADER)pbmi;
lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED,pbmi->bmiHeader.biSizeImage);
test = ::GetDIBits(hdc, hSavedXYBitmap, 0, (WORD) pbmi->bmiHeader.biHeight, lpBits, pbmi, DIB_RGB_COLORS);
if (test == 0)
test = GetLastError();"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder