Hey guys,
I've been reading up on working with bitmaps and getting a good feel for it.
Using the Win32 API, I can create a bitmap, load a bitmap from file and I can even save to file a previously loaded bitmap.
Unfortunately, I am unable to save to file a bitmap which I create in memory. Now, I have searched and read thru the archives here and have not yet found the solution.
Below is my code for creating a bitmap, which I bitblt to my double-buffer and display on my main screen. This works great.
It creates a 150 X 100 pixel rectangle with an ellipse drawn in the center of it.
Near the bottom, I call two functions taken from the SDK (Storing an Image) which does not seem to work in this case.Code:void MakeBitmap(HWND hwnd) { char bmpFile[BUFSIZE]; int bpp = 1; SIZE SBitmap = {150, 100}; HDC hDC = HdcBuffer; // handle to double buffer HBITMAP hBmp, hBmpOld; HDC hMemDC; COLORREF clrZeros, clrOnes; PBITMAPINFO pbmpi; hBmp = CreateBitmap(SBitmap.cx, SBitmap.cy, 1, bpp, NULL); hMemDC = CreateCompatibleDC(hDC); hBmpOld = (HBITMAP) SelectObject(hMemDC, hBmp); clrZeros = PALETTERGB(0,0,255); SetTextColor(hDC, clrZeros); PatBlt(hMemDC, 0, 0, SBitmap.cx, SBitmap.cy, BLACKNESS); clrOnes = PALETTERGB(255,0,0); SetBkColor(hDC, clrOnes); Ellipse(hMemDC, 0, 0, SBitmap.cx, SBitmap.cy); BitBlt(hDC, 10, 10, SBitmap.cx, SBitmap.cy, hMemDC, 0, 0, SRCCOPY); InvalidateRect(hwnd, &glrect, FALSE); UpdateWindow(hwnd); //..............HERE: is the BITMAP save to file section: strcpy(bmpFile, "test.bmp"); pbmpi = CreateBitmapInfoStruct(hwnd, hBmp); CreateBMPFile(hwnd, bmpFile, pbmpi, hBmp, hMemDC); //...................................................... DeleteObject(SelectObject(hMemDC, hBmpOld)); DeleteDC(hMemDC); DeleteDC(hBmp); ReleaseDC(hwnd, hDC); }
Here is the code for Storing an Image:
Code:PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp) { BITMAP bmp; PBITMAPINFO pbmi; WORD cClrBits; // Retrieve the bitmap color format, width, and height. if(!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp)) { printf("error:GetObject\n"); exit(0); } // Convert the color format to a count of bits. cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); if(cClrBits == 1) { cClrBits = 1; } else if(cClrBits <= 4) { cClrBits = 4; } else if(cClrBits <= 8) { cClrBits = 8; } else if(cClrBits <= 16) { cClrBits = 16; } else if(cClrBits <= 24) { cClrBits = 24; } else { cClrBits = 32; } if(cClrBits != 24) { pbmi = (PBITMAPINFO) LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1<< cClrBits)); } else { pbmi = (PBITMAPINFO) LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER)); } pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); pbmi->bmiHeader.biWidth = bmp.bmWidth; pbmi->bmiHeader.biHeight = bmp.bmHeight; pbmi->bmiHeader.biPlanes = bmp.bmPlanes; pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel; if(cClrBits < 24) { pbmi->bmiHeader.biClrUsed = (1<<cClrBits); } pbmi->bmiHeader.biCompression = BI_RGB; pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8 * pbmi->bmiHeader.biHeight; pbmi->bmiHeader.biClrImportant = 0; return pbmi; }*Re: the printf statements: I use a console window for error messages.Code:void CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC) { HANDLE hf; // file handle BITMAPFILEHEADER hdr; // bitmap file-header PBITMAPINFOHEADER pbih; // bitmap info-header LPBYTE lpBits; // memory pointer DWORD dwTotal; // total count of bytes DWORD cb; // incremental count of bytes BYTE *hp; // byte pointer DWORD dwTmp; pbih = (PBITMAPINFOHEADER) pbi; lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage); if(!lpBits) { printf("error:GlobalAlloc\n"); exit(0); } if(!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi, DIB_RGB_COLORS)) { printf("error:GetDIBits\n"); exit(0); } hf = CreateFile(pszFile, GENERIC_READ | GENERIC_WRITE, (DWORD) 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL); if(hf == INVALID_HANDLE_VALUE) { printf("error:CreateFile\n"); exit(0); } hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M" hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + pbih->biSize + pbih->biClrUsed * sizeof(RGBQUAD) + pbih->biSizeImage); hdr.bfReserved1 = 0; hdr.bfReserved2 = 0; hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + pbih->biSize + pbih->biClrUsed * sizeof(RGBQUAD); // Copy the BITMAPFILEHEADER into the .BMP file. if(!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), (LPDWORD) &dwTmp, NULL)) { printf("error:WriteFile-1\n"); exit(0); } // Copy the BITMAPINFOHEADER and RGBQUAD array into the file. if(!WriteFile(hf, (LPVOID) pbih, (sizeof(BITMAPINFOHEADER) + pbih->biClrUsed * sizeof(RGBQUAD)), (LPDWORD) &dwTmp, NULL)) { printf("error:WriteFile-2\n"); exit(0); } // Copy the array of color indices into the .BMP file. dwTotal = cb = pbih->biSizeImage; hp = lpBits; if(!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL)) { printf("error:WriteFile-3\n"); exit(0); } if(!CloseHandle(hf)) { printf("error:CloseHandle\n"); exit(0); } GlobalFree((HGLOBAL)lpBits); }
The Storing an Image code works when I load an image from a disk-file, so I know it does work. Just not when I create the bitmap in memory.
What I end up with is a BLACK rectangle saved to file, instead of my bitmap.
I have read of this exact same problem in the archives. However, I cannot figure out a solution.
Any ideas ?
Am I missing something obvious ?



1Likes
LinkBack URL
About LinkBacks



