Saving bitmaps

closed account (jwkNwA7f)
Hi, I am following a tutorial on saving bitmaps. It has gone well, but I am having a problem now. The program does compile successfully. It can save the file, but when I open the file it says:
Windows Live Photo Gallery wrote:
Photo Gallery can't open this photo or video. The file may be unsupported, damaged or corrupt.

Here are some pieces of the code:
Call to the functions in WndProc():
1
2
3
4
5
6
7
8
9
10
11
case SAVE_BM:
			{
				BOOL result = SaveFileDlg(hwnd, filePath, "Save Bitmap");
				if (result)
				{
					PBITMAPINFO pbi = CreateBmpInfoStruct(hwnd, hBitmap);
					hdc = GetDC(hwnd);
					SaveBmpFile(hwnd, filePath, pbi, hBitmap, hdc);
				}
				return 0;
			}

SaveBmpFile():
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
void SaveBmpFile(HWND hwnd, LPSTR file, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC)
{
	std::ofstream hF;
	BITMAPFILEHEADER bmfh;
	PBITMAPINFOHEADER pbmih;
	LPBYTE bits;
	DWORD total;
	DWORD cB;
	BYTE *hP;
	pbmih = (PBITMAPINFOHEADER) pbi;
	bits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbmih->biSizeImage);
	if (!bits)
		MessageBox(hwnd, "GlobalAlloc()", "Error", MB_OK);
	if (!GetDIBits(hDC, hBMP, 0, (WORD) pbmih->biHeight, bits, pbi, DIB_RGB_COLORS))
		MessageBox(hwnd, "GetDIBits()", "Error", MB_OK);
	hF.open(file, std::ios::binary);
	if (hF.fail())
		MessageBox(hwnd, "open()", "Error", MB_OK);
	bmfh.bfType = 0x4d42;
	bmfh.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + pbmih->biSize + pbmih->biClrUsed * sizeof(RGBQUAD) + pbmih->biSizeImage);
	bmfh.bfReserved1 = 0;
	bmfh.bfReserved2 = 0;
	bmfh.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + pbmih->biSize + pbmih->biClrUsed * sizeof(RGBQUAD);
	hF.write((char*) &bmfh, sizeof(BITMAPFILEHEADER));
	if (hF.fail())
		MessageBox(hwnd, "write() file header", "Error", MB_OK);
	hF.write((char*) pbmih, sizeof(BITMAPINFOHEADER) + pbmih->biClrUsed * sizeof(RGBQUAD));
	if (hF.fail())
		MessageBox(hwnd, "write() info header", "Error", MB_OK);
	total = cB = pbmih->biSizeImage;
	hP = bits;
	hF.write((char*) hP, (int) cB);
	if (hF.fail())
		MessageBox(hwnd, "write() data", "Error", MB_OK);
	hF.close();
	if (hF.fail())
		MessageBox(hwnd, "close()", "Error", MB_OK);
	GlobalFree((HGLOBAL) bits);
}

SaveBmpInfoStruct():
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
PBITMAPINFO CreateBmpInfoStruct(HWND hwnd, HBITMAP hBMP)
{
	BITMAP BMP;
	PBITMAPINFO pbmi;
	WORD clrBits;
	if (!GetObject(hBMP, sizeof(BITMAP), (LPSTR) &BMP))
		MessageBox(hwnd, "GetObject()", "Error", MB_OK);
	clrBits = (WORD) (BMP.bmPlanes * BMP.bmBitsPixel);
	if (clrBits == 1)
		clrBits = 1;
	else if (clrBits <= 4)
		clrBits = 4;
	else if (clrBits <= 8)
		clrBits = 8;
	else if (clrBits <= 16)
		clrBits = 16;
	else if (clrBits <= 24)
		clrBits = 24;
	else
		clrBits = 32;
	if (clrBits != 24)
		pbmi = (PBITMAPINFO) LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1<< clrBits));
	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 (clrBits < 24)
		pbmi->bmiHeader.biClrUsed = (1<< clrBits);
	pbmi->bmiHeader.biCompression = BI_RGB;
	pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * clrBits + 31) & ~31) / 8 * pbmi->bmiHeader.biHeight;
	pbmi->bmiHeader.biClrImportant = 0;
	return pbmi;
}

SaveFileDlg():
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
BOOL SaveFileDlg(HWND hwnd, LPSTR fileName, LPSTR titleName)
{
	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.hInstance = GetModuleHandle(NULL);
	ofn.lpstrCustomFilter = NULL;
	ofn.nMaxCustFilter = 0;
	ofn.nFilterIndex = 0;
	ofn.hwndOwner = hwnd;
	ofn.lpstrFile = fileName;
	ofn.lpstrFileTitle = NULL;
	ofn.lpstrTitle = titleName;
	ofn.Flags = OFN_EXPLORER | OFN_OVERWRITEPROMPT;
	ofn.lpstrFilter = "Bitmap Files (*.bmp)\0*.bmp\0\0";
	ofn.lpstrTitle = titleName;
	return GetSaveFileName(&ofn);
}


Let me know if you need to see more code.

Thanks for your help!
Sorry, but your code is a bit dense to wade though.

I have just built (with a few tweaks...) and run the code in this thread:

Save a bitmap without GetDiBits
http://www.cplusplus.com/forum/beginner/25138/

from a few years ago and it just worked for me; I loaded the resultant .bmp file into Paint.exe fine. (It's about how to eliminate the dependency on GetDIBits call; the code does use it.)

So, if it also works for you, you could compare what it's doing against your own code.

Andy
Last edited on
closed account (jwkNwA7f)
Okay, thank you for replying! I have actually fixed it. It was in a part of the code that I did not post.
Topic archived. No new replies allowed.