CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6
  1. #1
    Join Date
    Dec 2007
    Posts
    4

    Help copying HBITMAP from file to new HBITMAP

    I am trying to load a .bmp into an HBITMAP and then copy a portion of it into a new memory HBITMAP. I am pretty familiar with device contexts, memory bitmaps, and GDI - but I think I am missing something about HBITMAP creation. I've read and reread everything on the net but nothing has a complete code sample for this simple task so my efforts have been futile.

    The following code (simplified) produces black squares on the screen - what am I missing?

    //first load the source bitmap from a file - this works fine and will print to
    // the screen with no problem
    HBITMAP hbmsource = (HBITMAP)LoadImage(NULL,filepath,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);

    //get the screen device context
    CDC* pDC = GetDC();

    //create two memory dcs compatible with the screen
    HDC memDCsource = CreateCompatibleDC(pDC->m_hDC);
    HDC memDCtarget= CreateCompatibleDC(pDC->m_hDC);

    //select the source bitmap into the source DC
    HBITMAP pOldBitmap1 = (HBITMAP)SelectObject(memDCsource,hbmsource);

    //create a new bitmap compatible with the screen dc
    HBITMAP hbmtarget = CreateCompatibleBitmap(pDC->m_hDC,w,h);

    //.....I suspect that I am missing something here required to create the new
    // bitmap... ie bitmap header, CreateDIB, etc. - I thought that CreateCompatibleBitmap
    //covered all that.....

    //select the new bitmap into the target dc
    HBITMAP pOldBitmap2 = (HBITMAP)SelectObject(memDCtarget,hbmtarget);

    //bitblt the source to the target
    BitBlt(memDCtarget,0,0,w,h,memDCsource,0,0,SRCCOPY);

    //cleanup
    SelectObject(memDCsource,pOldBitmap1);
    SelectObject(memDCtarget,pOldBitmap2);
    DeleteDC(memDCsource);
    DeleteDC(memDCtarget);

    ReleaseDC(pDC);

    .......Now when I try and display the new HBITMAP on the screen it is all black.

    thanks for any help

  2. #2
    Join Date
    Aug 2000
    Location
    New York, NY, USA
    Posts
    5,656

    Re: Help copying HBITMAP from file to new HBITMAP

    Quote Originally Posted by jreck2112
    //create a new bitmap compatible with the screen dc
    HBITMAP hbmtarget = CreateCompatibleBitmap(pDC->m_hDC,w,h);

    .......Now when I try and display the new HBITMAP on the screen it is all black.
    Try to create your hbmtarget compatible to memDCsource (after you have selected source bitmap into it).
    Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
    Convenience and productivity tools for Microsoft Visual Studio:
    FeinWindows - replacement windows manager for Visual Studio, and more...

  3. #3
    Join Date
    Feb 2008
    Posts
    10

    Re: Help copying HBITMAP from file to new HBITMAP

    or try to make the loaded bitmap compatible.
    MSDN states that LoadImage makes it compatible but
    you should see what works in action.

    to test/debug try to BitBlt onto the screen ( a display DC ) to
    see if the loaded image does appear correctly ( i.e. it is
    loaded and compatible ).

  4. #4
    Join Date
    Sep 2002
    Location
    Singapore
    Posts
    673

    Re: Help copying HBITMAP from file to new HBITMAP

    Use GDI+. It is much simpler to use than GDI. Below is the code for cropping the image and saving them. If you do not want to save, just commented the Save function in CropImage().

    Code:
    using namespace Gdiplus;
    void Test()
    {
    
    	Bitmap SrcBmp(L"E:\\Hello.jpg", TRUE);
    
    	bool bRet = CropImage(
    		SrcBmp, 
    		160, 
    		35, 
    		510, 
    		490, 
    		L"E:\\Hello2.jpg",
    		L"image/jpeg" );
    
    	if( bRet )
    		MessageBox(L"Successful");
    	else
    		MessageBox(L"Failed");
    }
    
    bool CropImage(
    	Bitmap &SrcBmp, 
    	int x, 
    	int y, 
    	int nWidth, 
    	int nHeight, 
    	const std::wstring& szDestFile,
    	const std::wstring& szEncoderString )
    {
    	Rect rect(x, y, nWidth, nHeight);
    	Bitmap* pDestBmp = SrcBmp.Clone(rect, PixelFormatDontCare);
    
    	if( !pDestBmp )
    		return false;
    
    	CLSID Clsid;
    	int result = GetEncoderClsid(szEncoderString.c_str(), &Clsid);
    
    	if( result < 0 )
    		return false;
    
    	Status status = pDestBmp->Save( szDestFile.c_str(), &Clsid );
    
    	delete pDestBmp;
    	pDestBmp = NULL;
    	
    	return status == Ok;
    }
    
    int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
    {
       UINT  num = 0;          // number of image encoders
       UINT  size = 0;         // size of the image encoder array in bytes
    
       ImageCodecInfo* pImageCodecInfo = NULL;
    
       GetImageEncodersSize(&num, &size);
       if(size == 0)
          return -1;  // Failure
    
       pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
       if(pImageCodecInfo == NULL)
          return -1;  // Failure
    
       GetImageEncoders(num, size, pImageCodecInfo);
    
       for(UINT j = 0; j < num; ++j)
       {
          if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
          {
             *pClsid = pImageCodecInfo[j].Clsid;
             free(pImageCodecInfo);
             return j;  // Success
          }    
       }
    
       free(pImageCodecInfo);
       return -1;  // Failure
    }
    If you want to display the cropped image, just use the code below,

    Code:
    Graphics graphics(hDC);
    graphics.DrawImage(pDestBmp,0,0,nWidth,nHeight);
    Last edited by CBasicNet; February 21st, 2008 at 03:21 AM.

  5. #5
    Join Date
    Sep 2002
    Location
    Singapore
    Posts
    673

    Re: Help copying HBITMAP from file to new HBITMAP

    If the OP only wants to display the cropped image, here is the edited code.

    Code:
    bool CropImage(
    	Bitmap &SrcBmp, 
    	int x, 
    	int y, 
    	int nWidth, 
    	int nHeight, 
    	const std::wstring& szDestFile,
    	const std::wstring& szEncoderString )
    {
    	Rect rect(x, y, nWidth, nHeight);
    	Bitmap* pDestBmp = SrcBmp.Clone(rect, PixelFormatDontCare);
    
    	if( !pDestBmp )
    		return false;
    
    	Graphics graphics(hDC);
    	graphics.DrawImage(pDestBmp,0,0,nWidth,nHeight);
    
    	delete pDestBmp;
    	pDestBmp = NULL;
    	
    	return status == Ok;
    }
    Remember to include the Gdiplus.h and link to Gdiplus.lib

  6. #6
    Join Date
    Dec 2007
    Posts
    4

    Re: Help copying HBITMAP from file to new HBITMAP

    Thanks for the suggestions....

    - I had tried making the CDC compatible with the source DC but that did not make a difference (and in past experiences, had made things worse).

    - The loaded images were working fine standalone (and could be succesfully displayed on the screen).

    - I'd love to switch to GDI+ but haven't explored yet the easiest way to use with C++ (i.e. VC6) - can't bring myself to jump into C# yet.

    BOTTOM LINE - the problem turned out to be quite fundamental... I wasn't allocating any memory for the new target bitmap. It was properly compatible and coded correctly, but without the Alloc - nowhere to put all the pretty pixels.

    Thanks for the help.

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