CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 11 of 11
  1. #1
    Join Date
    Oct 2001
    Location
    Dublin, Eire
    Posts
    880

    [RESOLVED] Why does my bitmap become all black when saved to file?

    I am trying to create a bitmap. This works well as I can obtain the correct result on the screen. But when I am trying to save the bitmap to a file, it become just a black rectangle.

    I have tried a lot of things, multiple functions to save bitmap taken from different places, and always obtain the same result.

    Here is a simplified version of the code, which produces the same result. It can simply be called in the simplest project that uses MFC. If I put a break point just before calling the write function, I can see my picture on the screen, as expected. But the bitmap is black in the file.

    Code:
    void CreateDrawing()
    {
    	CWnd wnd;
    	CRect rect (0, 0, 100, 100);
    	wnd.CreateEx(NULL, NULL, NULL,WS_POPUP |  WS_CHILD | WS_CLIPSIBLINGS, rect, NULL, NULL, NULL);
    
    	CClientDC paintdc(&wnd);
    	paintdc.SetBkMode(TRANSPARENT);
    
    	CRect rectWnd = rect;
    	CPoint ptToolTipLeft = rectWnd.TopLeft();
    	SetWindowPos(wnd.m_hWnd, HWND_TOPMOST,ptToolTipLeft.x+1, ptToolTipLeft.y+1, rectWnd.Width(), rectWnd.Height(),SWP_SHOWWINDOW|SWP_NOOWNERZORDER|SWP_NOACTIVATE);
    
    	CBrush m_brush(RGB(255,255,255));
    	CPen m_pen(PS_SOLID, 0, COLORREF(RGB(0, 0, 0)));
    	CBrush* pOldBrush = paintdc.SelectObject(&m_brush);
    	CPen* pOldPen = paintdc.SelectObject(&m_pen);
    	paintdc.Rectangle(0,0,rect.Width(),rect.Height());
    	paintdc.MoveTo(0, 0);
    	paintdc.LineTo(100, 100);
    
    
    	HBITMAP hbmp = CreateCompatibleBitmap(paintdc.m_hDC, rect.Width(),rect.Height());
    	CBitmap bmp;
    	bmp.Attach(hbmp);
    
    	WriteToFile(paintdc, hbmp);
    
    	paintdc.SelectObject(pOldBrush);
    	paintdc.SelectObject(pOldPen);
    }
    
    
    bool WriteToFile(CDC& hMemDC, HBITMAP hBitmap)
    {
    	CString strFileName = "c:\\test\\test.bmp";
    	int   wBitCount = 32;
    
    	BITMAP   Bitmap;  
    
    	CPalette pal;
    	pal.Attach(::GetStockObject(DEFAULT_PALETTE));	
    	hMemDC.SelectPalette(&pal, TRUE);
    
    	GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap); 
    
    	BITMAPINFOHEADER   bi;
    	bi.biSize = sizeof(BITMAPINFOHEADER);    
    	bi.biWidth = Bitmap.bmWidth;    
    	bi.biHeight = Bitmap.bmHeight;  
    	bi.biPlanes = 1;    
    	bi.biBitCount = wBitCount;    
    	bi.biCompression = BI_RGB;    
    	bi.biSizeImage = 0;  
    	bi.biXPelsPerMeter = 0;    
    	bi.biYPelsPerMeter = 0;    
    	bi.biClrUsed = 0;    
    	bi.biClrImportant = 0; 
    
    	DWORD dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight; 
    
    	HANDLE hDib = GlobalAlloc(GHND, dwBmBitsSize+sizeof(BITMAPINFOHEADER)); 
    	LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);    
    	*lpbi = bi;
    
    	GetDIBits(hMemDC.m_hDC, hBitmap, 0, (UINT)Bitmap.bmHeight,  
    		(LPSTR)lpbi + sizeof(BITMAPINFOHEADER), (BITMAPINFO *)lpbi, DIB_RGB_COLORS);    
    
    
    	DWORD dwDIBSize   =   sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwBmBitsSize;
    
    	BITMAPFILEHEADER   bmfHdr;    
    	bmfHdr.bfType = 'B'+('M' << 8);
    	bmfHdr.bfSize = dwDIBSize;
    	bmfHdr.bfReserved1 = 0;
    	bmfHdr.bfReserved2 = 0;
    	bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);    
    
    	DWORD dwWritten;
    
    	HANDLE fh = CreateFile(strFileName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
    			FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN,NULL);   
    	ASSERT(fh != INVALID_HANDLE_VALUE);
    	WriteFile(fh,   (LPSTR)&bmfHdr,   sizeof(BITMAPFILEHEADER),   &dwWritten,   NULL);    
    	WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL);    
    	GlobalUnlock(hDib);    
    	GlobalFree(hDib);    
    	CloseHandle(fh);
    	return true;
    }
    I am probably missing something simple, but could not figure what.
    Last edited by Elrond; June 28th, 2010 at 06:23 AM. Reason: Added resolved tag
    Elrond
    A chess genius is a human being who focuses vast, little-understood mental gifts and labors on an ultimately trivial human enterprise.
    -- George Steiner

  2. #2
    Join Date
    Apr 2009
    Posts
    598

    Re: Why does my bitmap become all black when saved to file?

    Instead of:
    Code:
    bi.biSizeImage = 0
    Have:
    Code:
    bi.biSizeImage = bi.biWidth * 4 * bi.biHeight * sizeof(unsigned char);

  3. #3
    Join Date
    Oct 2001
    Location
    Dublin, Eire
    Posts
    880

    Re: Why does my bitmap become all black when saved to file?

    Tried it, but my bitmap is still black...
    Elrond
    A chess genius is a human being who focuses vast, little-understood mental gifts and labors on an ultimately trivial human enterprise.
    -- George Steiner

  4. #4
    Join Date
    Oct 2001
    Location
    Dublin, Eire
    Posts
    880

    Re: Why does my bitmap become all black when saved to file?

    After so many attempts, I have finally solved my problem. I had tried already using memory DC without success, creating the bitmap object at the beginning or the end... The only thing I failed to do was attaching the bitmap to the device context:

    Code:
    	CDC memDC;
    	memDC.CreateCompatibleDC(&paintdc);
    	CBitmap bmp;
    	bmp.CreateCompatibleBitmap(&memDC, rect.Width(),rect.Height());
    	memDC.SelectObject(&bmp);
    Now, the bitmap I create is in black and white (even if I use a coloured pen) so I just have to figure out how to put colour in the bitmap...
    Elrond
    A chess genius is a human being who focuses vast, little-understood mental gifts and labors on an ultimately trivial human enterprise.
    -- George Steiner

  5. #5
    Join Date
    Feb 2005
    Posts
    2,160

    Re: Why does my bitmap become all black when saved to file?

    I'm not sure what you're doing with the palette. You've got a 32 bit DIB so you don't need a palette. That might be causing some weirdness with your colors.

  6. #6
    Join Date
    Oct 2001
    Location
    Dublin, Eire
    Posts
    880

    Re: Why does my bitmap become all black when saved to file?

    This palette thing is a "left over" from the number of attempts I have made to get all this to work. But removing it does not solve the "colour" problem. I still be a black and with bitmap.

    Well, in the posted code that makes sense because I am writing in Black on a white background, but I have changed the colour of the pen:
    Code:
    CPen m_pen(PS_SOLID, 0, COLORREF(RGB(255, 0, 0)));
    It draws the colour fine on the screen if I display it, but the bitmap in the file does not have anycolour.
    Elrond
    A chess genius is a human being who focuses vast, little-understood mental gifts and labors on an ultimately trivial human enterprise.
    -- George Steiner

  7. #7
    Join Date
    Feb 2005
    Posts
    2,160

    Re: Why does my bitmap become all black when saved to file?

    Could you post an amended code snippit. You've apparently done some changes since your first post.

  8. #8
    Join Date
    Oct 2001
    Location
    Dublin, Eire
    Posts
    880

    Re: Why does my bitmap become all black when saved to file?

    I have put in bold what I believe are all the changes from the beginning. They do produce a usable bitmap file, but in bloack and white only.

    Code:
    void CreateDrawing()
    {
    	CWnd wnd;
    	CRect rect (0, 0, 100, 100);
    	wnd.CreateEx(NULL, NULL, NULL,WS_POPUP |  WS_CHILD | WS_CLIPSIBLINGS, rect, NULL, NULL, NULL);
    
    	CClientDC paintdc(&wnd);
    	CDC memDC;
    	memDC.CreateCompatibleDC(&paintdc);
    
    	CBitmap bmp;
    	bmp.CreateCompatibleBitmap(&memDC, rect.Width(),rect.Height());
    	memDC.SelectObject(&bmp);
    
    	CBrush m_brush(RGB(255,255,255));
    	CPen m_pen(PS_SOLID, 1, COLORREF(RGB(0, 255, 0)));
    	CBrush* pOldBrush = memDC.SelectObject(&m_brush);
    	CPen* pOldPen = memDC.SelectObject(&m_pen);
    
    	memDC.SetBkMode(TRANSPARENT);
    	memDC.Rectangle(0,0,rect.Width(),rect.Height());
    	memDC.MoveTo(0, 0);
    	memDC.LineTo(100, 100);
    
    	WriteToFile(memDC, (HBITMAP)bmp.m_hObject);
    
    	memDC.SelectObject(pOldBrush);
    	memDC.SelectObject(pOldPen);
    }
    
    
    bool WriteToFile(CDC& hMemDC, HBITMAP hBitmap)
    {
    	CString strFileName = "c:\\test\\test.bmp";
    	int   wBitCount = 32;
    
    	BITMAP   Bitmap;  
    
    	GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap); 
    
    	BITMAPINFOHEADER   bi;
    	bi.biSize = sizeof(BITMAPINFOHEADER);    
    	bi.biWidth = Bitmap.bmWidth;    
    	bi.biHeight = Bitmap.bmHeight;  
    	bi.biPlanes = 1;    
    	bi.biBitCount = wBitCount;    
    	bi.biCompression = BI_RGB;    
    	bi.biSizeImage = bi.biWidth * 4 * bi.biHeight * sizeof(unsigned char);	
    	bi.biXPelsPerMeter = 0;    
    	bi.biYPelsPerMeter = 0;    
    	bi.biClrUsed = 0;    
    	bi.biClrImportant = 0; 
    
    	DWORD dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight; 
    
    	HANDLE hDib = GlobalAlloc(GHND, dwBmBitsSize+sizeof(BITMAPINFOHEADER)); 
    	LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);    
    	*lpbi = bi;
    
    	GetDIBits(hMemDC.m_hDC, hBitmap, 0, (UINT)Bitmap.bmHeight,  
    		(LPSTR)lpbi + sizeof(BITMAPINFOHEADER), (BITMAPINFO *)lpbi, DIB_RGB_COLORS);    
    
    
    	DWORD dwDIBSize   =   sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwBmBitsSize;
    
    	BITMAPFILEHEADER   bmfHdr;    
    	bmfHdr.bfType = 'B'+('M' << 8);
    	bmfHdr.bfSize = dwDIBSize;
    	bmfHdr.bfReserved1 = 0;
    	bmfHdr.bfReserved2 = 0;
    	bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);    
    
    	DWORD dwWritten;
    
    	HANDLE fh = CreateFile(strFileName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
    			FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN,NULL);   
    	ASSERT(fh != INVALID_HANDLE_VALUE);
    	WriteFile(fh,   (LPSTR)&bmfHdr,   sizeof(BITMAPFILEHEADER),   &dwWritten,   NULL);    
    	WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL);    
    	GlobalUnlock(hDib);    
    	GlobalFree(hDib);    
    	CloseHandle(fh);
    	return true;
    }
    Elrond
    A chess genius is a human being who focuses vast, little-understood mental gifts and labors on an ultimately trivial human enterprise.
    -- George Steiner

  9. #9
    Join Date
    Feb 2005
    Posts
    2,160

    Re: Why does my bitmap become all black when saved to file?

    Change this line:

    Code:
    bmp.CreateCompatibleBitmap(&memDC, rect.Width(),rect.Height());
    to this:

    Code:
    bmp.CreateCompatibleBitmap(&paintdc, rect.Width(),rect.Height());

  10. #10
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: Why does my bitmap become all black when saved to file?

    A tiny mistake:
    Code:
    bmp.CreateCompatibleBitmap(&memDC, rect.Width(),rect.Height());
    There must be paintdc instead.

    Newly created DC (like your memDC) contains B&W bitmap. Been creating compatible bitmap you create same B&W bitmap.

    [Edit]Oops, hoxsiew appeared more swift.
    Best regards,
    Igor

  11. #11
    Join Date
    Oct 2001
    Location
    Dublin, Eire
    Posts
    880

    Re: Why does my bitmap become all black when saved to file?

    Sorry for the late answer as the week end got me going.

    Thanks for the answers, that are correct and working.
    Elrond
    A chess genius is a human being who focuses vast, little-understood mental gifts and labors on an ultimately trivial human enterprise.
    -- George Steiner

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured