none
Copying from HBITMAP to IImage

    Question

  • I have a program that has rendered a scene (for lack of a better word) to a bitmap.  I need to render that bitmap to the screen and I figured the Imaging API would be best for rotating the image by 90-degrees and resizing it.  Problem is I don't know of the best way to get the HBITMAP data into an IImage instance.  I considered taking the raw data from the bitmap, building a BitmapData structure, and using IImageFactory::CreateBitmapFromBuffer.  But I get the feeling that is unnecessarily complex.  Can any one suggest a better method?
    Joel Ivory Johnson
    Tuesday, May 05, 2009 3:25 PM

Answers

  • That is the right way.. I guess... ( as far as I know )
    I am not sure how that is complex...

    all you have to do is ... GetObject call... fill the BitmapData structure... pass it to the CreateBitmapFromBuffer  and gat a IBitmapImage from it !!!

    I am sure this is the simplest way.
    Tuesday, May 05, 2009 9:07 PM

All replies

  • That is the right way.. I guess... ( as far as I know )
    I am not sure how that is complex...

    all you have to do is ... GetObject call... fill the BitmapData structure... pass it to the CreateBitmapFromBuffer  and gat a IBitmapImage from it !!!

    I am sure this is the simplest way.
    Tuesday, May 05, 2009 9:07 PM
  • Well, Joel?

    Have you succeded, I have the same problem and I would be very grateful if you answer!
    Friday, May 22, 2009 12:45 PM
  • It was never the issue that I didn't have success in doing this, but that I wasn't sure that this was the best way to do it.  It works and performance is good (though not so fast that one would be able to do animation with it).  What problem did you run into in trying to do this?
    Joel Ivory Johnson
    Saturday, May 23, 2009 11:34 PM
  • HRESULT HBitmapToBitmapImage(HBITMAP hbmp, IImagingFactory* pIF, IBitmapImage** pBitmapImage)
    {
        BITMAP bm = {0};
        GetObject( hbmp, &bm, sizeof(bm));
    
    	
    	int nStride = bm.bmWidth * bm.bmBitsPixel;
    	if( (nStride % 32) != 0)
    		nStride += 32;
    
    	BitmapData bmData = {0};
    
    	bmData.Width = bm.bmWidth;
    	bmData.Height = bm.bmHeight;
    	bmData.Stride = nStride/8;
    	switch (bm.bmBitsPixel)
    	{
    	case 1: 
    		pixelFormat = PixelFormat1bppIndexed;
    		break;
    		
    	case 4: 
    		pixelFormat = PixelFormat4bppIndexed;
    		break;
    	
    	case 8: 
    		pixelFormat = PixelFormat8bppIndexed;
    		break;
    	
    	case 24: 
    		pixelFormat = PixelFormat24bppRGB;
    		break;
    	
    	default: 
    		pixelFormat = PixelFormat32bppARGB;
    	}
    	
    	bmData.Scan0 = bm.bmBits;
    
    	HRESULT hres = S_OK;
    
    	hres = pIF->CreateBitmapFromBuffer(&bmData, pBitmapImage);
    
    	return hres;
    }
    The should be like this for simple conversion, I haven't tested the code.. just hand written...

    Joel,
          I didn't know that you are going to animate the resulting image with using this method. first of all there is issues with DIB vs DDB, I am not sure what kind of bitmap you have in hand. You should have DDB rather than DIB. DIB's are slow to render, and here the pixels are more attached to the HBITMAP handle. In your case I would have made a copy of the pixels by detaching it( getting rid of dependencies ) Just to be safe. I think there were other ways to achieve this in DirectX. I can't comment more because I am not quiet sure about your scenario. Actually you asked for a best way to do the conversion, and I am sure this is the one(AFAIK).
    Sunday, May 24, 2009 4:55 AM
  • My problem, from the start, was getting IImage instance out of HICON.

    So I took the two HBITMAPs (image and mask) out of HICON and tried to get IImage. I did that somehow, but I still have problems with transparency and that is most important to me.

    What ever way I try, the image - icon is not transparent at the end.
    Sunday, May 24, 2009 1:12 PM
  • ICON format is something that usually contains multiple images and it has got a different format than bitmap format. You should be able to load the icon from file and draw it using imaging api, if you still want to go with HICON, I think it would be hard, but doable. You have to know the ICON format and how to manipulate it. I dont think the GetIconInfo would help you with that...

    Monday, May 25, 2009 2:00 PM

  • When I use CreateImageFromFile(...) or CreateImageFromBuffer(...) to get IImage

    and later draw it with:
                        pImage->Draw(...)

    the entire image is opaque.

    I made buffer for the image with CreateDIBSection() then BitBlt(), with those two headers (BITMAPFILEHEADER and BITMAPINFOHEADER). And before all that I set HBITMAP pixels with SetBitmapBits(...) hoping that way i'll affect alpha pixels (since SetPixel(...) fail when i set something like 0xFFFFFFFF or 0xFF000000).

    So...

    Now, when I call
                       pImage->GetImageInfo(& imageInfo);

    PixelFormat is
                       PixelFormat32bppRGB
    instead of
                       PixelFormat32bppARGB.

    I hope that's the only thing that keep me away from drawing transparent IImage. (On the other hand, if I load .png image from file to obtain IImage, it draws transparent picture fine).

    Now I dont know how to set PixelFormat to PixelFormat32bppARGB (pImage->SetImageFlags(ImageFlagsHasAlpha); is not supported).

    If I would try with BitmapData structure (bmData.PixelFormat = PixelFormat32bppARGB), I would get to IBitmapImage, but that is not IImage.

    Maybe I should go that way... Get IImage out of IBitmapImage...

    So, ImageInfo's PixelFormat is, if I am right, set by the system, and there is no way I can affect it (No way I can set it in image buffer or file...).

    So, I dont know what to do
    Wednesday, May 27, 2009 10:52 AM
  • Because of all this, I now use IImageEncoder to accomplish the goal by saving new .png image to file or stream.

    And now tried to obtain IImage pointer out of HICON's HBITMAPs in the simplest way, without encoding...

    I did it with
                      pBitmapImage->QueryInterface(IID_IImage, (void **)pImage)

    and I still have to see when to release IBitmapImage with pImage->Release();  I need as soon as posible because my IImage pointer  pImage   is out parameter
    Thursday, May 28, 2009 4:44 PM