4

(This is related to the question on How would I load a PNG image using Win32/GDI (no GDI+ if possible)?.)

Hi all,

I was wondering, given that you have a PNG resource embedded in a binary file with the ID IDB_PNG1, and an LPDRAWITEMSTRUCT to draw into (so that means you have the HDC and the rectangle for your target), how do you draw that image onto the screen using StretchDIBits? I've worked with BitBlt and TransparentBlt before, but StretchDIBits seems to work differently, and LoadImage doesn't seem to work with PNG's.

Thank you!

(Note: The language I put is C++, but that's not too important... C, C#, Visual Basic, etc. would be fine; I'm just trying to figure out the steps, not the exact code needed.)

1
  • If you can save your resource as an icon in PNG format, can you load it that way?
    – Gabe
    Commented Dec 31, 2010 at 13:52

2 Answers 2

9

I wrote a blog post (on displaying a splash screen with C++) that contains a full code sample that loads a PNG from a resource and converts it to an HBITMAP (using WIC). You could then use CreateCompatibleDC, SelectObject, and BitBlt to display it in the target HDC.

While I haven't ever tried it, you should be able to use StretchDIBits to display the PNG directly if you load the raw bytes from the resource into memory, and set up a BITMAPINFOHEADER struct with the width, height, etc. as demonstrated in this MSDN sample.

C# and VB.NET solutions would be quite different because you could use System.Drawing (a wrapper for GDI+) or System.Windows.Media.Imaging (in a WPF app) to handle the image loading and drawing.

2
  • 1
    This is very interesting, it seems to be exactly what I'm looking for. A question regarding trying to set up the BITMAPINFOHEADER: how would I know what the dimensions of the image are? Would I be still forced to use WIC? (Edit: It seems like this wouldn't work; see my comment on Greg's post. But thank you very much for the link to the blog post, it'll most definitely be helpful... I wish I could mark two posts as an answer. :) )
    – user541686
    Commented Dec 31, 2010 at 6:24
  • 1
    To know the dimensions of the image, you'd either have to write a png decoder (or use libpng or WIC) to read them from the PNG file, or store them as a separate resource that's kept in sync with your PNG resource. (That's partly why I've never tried the StretchDIBits approach; I've always used libpng or WIC to handle all the PNG reading.) Commented Dec 31, 2010 at 8:01
1

I think the PNG support inside bitmaps is only really for use by printer drivers. For screen display, you will probably have to decompress the PNG data yourself using some code such as libpng.

6
  • Huh... I certainly didn't see that coming. What's the difference between a display and a printer that would cause this?
    – user541686
    Commented Dec 31, 2010 at 4:38
  • 1
    Printers typically (well, at least historically) have substantially more capability than display adapters. Printers are also across lower bandwidth connections, so economy of bits is important in sending data to a printer (it's better to send a compressed PNG to a printer that has the capability to decode it, than to send all the raw bits). This also allows the printer to choose the most appropriate fidelity options when it does the decompression itself. However, display hardware and drivers typically want to be more deterministic and avoid doing decompression themselves. Commented Dec 31, 2010 at 4:45
  • 2
    How does the function know whether it's being used for a printer rather than a display?
    – Gabe
    Commented Dec 31, 2010 at 5:22
  • 1
    The function passes your data to the driver. The driver can either display it, or say "sorry, don't know how to do that". Commented Dec 31, 2010 at 5:36
  • 1
    Yes... According to MSDN: "On certain versions of Microsoft Windows, the StretchDIBits and SetDIBitsToDevice functions allow JPEG and PNG images to be passed as the source image to printer devices." Thank you for the response!
    – user541686
    Commented Dec 31, 2010 at 6:28

Not the answer you're looking for? Browse other questions tagged or ask your own question.