c++ bitmap to bmp

Started by
1 comment, last by Zahlman 16 years, 7 months ago
Hello. I am having a problem creating and saving an image as bmp in a MFC application. Project is created by VS6 from mfc appication wizard(exe) with standard options. This is the source of the onDraw method. This creates a bitmap and draws to screen. Also creates a bmp file of application size but its just black. What am i doing wrong?

// CDenemeView drawing

void CDenemeView::OnDraw(CDC* pDC)
{
	CDenemeDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here

	// bitmap dimensions

	RECT windowRect;
	GetWindowRect(&windowRect);

	int bitmap_dx = windowRect.right - windowRect.left;
	int bitmap_dy = windowRect.bottom - windowRect.top;
	

	CPaintDC odc(this);

	CBitmap bmp;
	CDC dc;
	dc.CreateCompatibleDC(&odc);
	bmp.CreateCompatibleBitmap( &odc, bitmap_dx, bitmap_dy );
	dc.SelectObject(&bmp);

	//fill the area
	for ( int x = 0; x < bitmap_dy; x ++ ) {
		for ( int y = 0; y < bitmap_dx; y ++ ) {
			dc.SetPixel(x,y, RGB(x%256,y%256,(x*y)%256));
		}
	}

	// create file
	ofstream file("example.bmp", ios::binary);
	if(!file) return;

	// save bitmap file headers
	BITMAPFILEHEADER fileHeader;
	BITMAPINFOHEADER infoHeader;
	fileHeader.bfType      = 0x4d42;
	fileHeader.bfSize      = 0;
	fileHeader.bfReserved1 = 0;
	fileHeader.bfReserved2 = 0;
	fileHeader.bfOffBits   = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
	infoHeader.biSize          = sizeof(infoHeader);
	infoHeader.biWidth         = bitmap_dx;
	infoHeader.biHeight        = bitmap_dy;
	infoHeader.biPlanes        = 1;
	infoHeader.biBitCount      = 24;
	infoHeader.biCompression   = BI_RGB;
	infoHeader.biSizeImage     = 0;
	infoHeader.biXPelsPerMeter = 0;
	infoHeader.biYPelsPerMeter = 0;
	infoHeader.biClrUsed       = 0;
	infoHeader.biClrImportant  = 0;

	file.write((char*)&fileHeader, sizeof(fileHeader));
	file.write((char*)&infoHeader, sizeof(infoHeader));

	// dibsection information
	BITMAPINFO info;
	info.bmiHeader = infoHeader; 

	
	
	//for checking if dc has correct drawing
	pDC->BitBlt( 0,0,bitmap_dx, bitmap_dy, &dc,0,0,SRCCOPY);

	BYTE *memory;
	SelectObject(dc, bmp);

	HBITMAP bitmap = CreateDIBSection(dc, &info, DIB_RGB_COLORS, (void**)&memory, 0, 0);

	
	
	// save dibsection data

	int bytes = (((24*bitmap_dx + 31) & (~31))/8)*bitmap_dy;

	file.write((char*)memory, bytes);
	DeleteObject(bmp);
	DeleteDC(dc);
	DeleteDC(odc);
	file.close();

}

Advertisement
I have played a bit around with the code. First off the HBITMAP i created was not getting the info from CBitmap bmp; so i decided to get pixel directly from it. and changed 24 color depth to 32 which is my desktop resolution. At last i got some output but half the picture is still in black. What could be the reason?

// CDenemeView drawingvoid CDenemeView::OnDraw(CDC* pDC){	CDenemeDoc* pDoc = GetDocument();	ASSERT_VALID(pDoc);	// TODO: add draw code for native data here	// bitmap dimensions	RECT windowRect;	GetWindowRect(&windowRect);	int bitmap_dx = windowRect.right - windowRect.left;	int bitmap_dy = windowRect.bottom - windowRect.top;		CPaintDC odc(this);	CBitmap bmp;	CDC dc;	dc.CreateCompatibleDC(&odc);	bmp.CreateCompatibleBitmap( &odc, bitmap_dx, bitmap_dy );	dc.SelectObject(&bmp);	//fill the area	for ( int x = 0; x < bitmap_dy; x ++ ) {		for ( int y = 0; y < bitmap_dx; y ++ ) {			dc.SetPixel(x,y, RGB(x%256,y%256,(x+y)%256));		}	}	// create file	ofstream file("example.bmp", ios::binary);	if(!file) return;	// save bitmap file headers	BITMAPFILEHEADER fileHeader;	BITMAPINFOHEADER infoHeader;	fileHeader.bfType      = 0x4d42;	fileHeader.bfSize      = 0;	fileHeader.bfReserved1 = 0;	fileHeader.bfReserved2 = 0;	fileHeader.bfOffBits   = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);	infoHeader.biSize          = sizeof(infoHeader);	infoHeader.biWidth         = bitmap_dx;	infoHeader.biHeight        = bitmap_dy;	infoHeader.biPlanes        = 1;	infoHeader.biBitCount      = 32;	infoHeader.biCompression   = BI_RGB;	infoHeader.biSizeImage     = 0;	infoHeader.biXPelsPerMeter = 0;	infoHeader.biYPelsPerMeter = 0;	infoHeader.biClrUsed       = 0;	infoHeader.biClrImportant  = 0;	file.write((char*)&fileHeader, sizeof(fileHeader));	file.write((char*)&infoHeader, sizeof(infoHeader));		// save dibsection data	int bytes = (((32*bitmap_dx + 31) & (~31))/8)*bitmap_dy;	char *memory2= (char*)malloc(sizeof(char)*bytes);	bmp.GetBitmapBits(bytes,memory2);	file.write((char*)memory2, bytes);	DeleteObject(bmp);	DeleteDC(dc);	DeleteDC(odc);	file.close();}
1) Have you examined the actual file contents?

2) CDC, CPaintDC and CBitmap appear to be your own classes. Any chance that the functions you're calling from them don't actually work? (In particular, I don't think you can sanely call the Windows SelectObject with your own classes.)

This topic is closed to new replies.

Advertisement