A survey of the various ways of creating GDI bitmaps with predefined data

Suppose you have a buffer full of pixels and you want to create a GDI bitmap that contains those pixels.

We'll start with the Create­Bitmap function. This creates a device-dependent bitmap with the pixels you provide. The weird thing about this function is that it's a device-dependent bitmap, but there's no parameter that specifies the device! As a result, the bitmap has the format you specify, but you can select it only into device contexts that are compatible with the bitmap format. For example, if you create a 4bpp bitmap, then you can select it only into 4bpp device contexts.¹

Next up is the misleadingly-named Create­DI­Bitmap function. Even though the DI stands for device independent, this function does not create a device-independent bitmap. It creates a device-dependent bitmap that is compatible with the provided device context. The reason it's called DI is that you can provide pixels in a device-independent format, and those pixels will be used to initialize the bitmap. As noted in the documentation, the behavior is functionally equivalent to Create­Compatible­Bitmap followed by Set­DI­Bits.

If it's a device-independent bitmap you want, then the function to use is Create­DIB­Section. The simplest use of this function creates a device-independent bitmap and gives you a pointer to the in-memory pixel buffer. You can then manipulate the pixel buffer directly, say, by memcpying the bytes from your original buffer.

The fancier use of this function creates a device-independent bitmap around existing memory. The memory needs to be in a file mapping object, either a file mapping object created from a file or (more often) a file mapping object created from the page file (in other words, a shared memory block). You can then specify the byte offset within the file mapping at which the pixel buffer starts. In this case, the memory is not copied; the memory in the file mapping object is the backing memory for the bitmap. If you modify the bitmap, then the contents of the file mapping object change; if you modify the contents of the file mapping object, you modify the bitmap.

Here's the table:

Function Type of bitmap Resulting format Source pixels Must format match?
Create­Bitmap Device-dependent As specified Copied Yes
Create­DI­Bitmap Device-dependent Device-compatible Copied No
Create­DIB­Section without hSection Device-independent As specified Uninitialized (copy them yourself) Yes
Create­DIB­Section with hSection Device-independent As specified Shared Yes

In the above table, the Resulting format column describes the pixel format of the returned bitmap. The Source pixels column describes what happens to the pixels you pass as the source pixels: Are they copied into the bitmap, or does the bitmap share the memory with the source pixels? The Must format match? column specifies whether the format of the source pixels must match the pixel format of the returned bitmap. If Must format match? is No, then the system will perform a format conversion.

¹ Monochrome bitmaps are compatible with any device context and have special behavior when selected into color device contexts.

Comments (24)
  1. Azarien says:

    What about Bitmap::GetHBITMAP from GDI+?

    1. A more precise title would be “A survey of the various ways of creating GDI bitmaps with GDI with predefined data”. I’m not going to try to cover every API that happens to spit out GDI bitmaps.

  2. skSdnW says:

    The annoying thing with Create­DIB­Section+hSection is that the offset must be DWORD aligned and that is usually not the case in .bmp files.

    1. Medinoc says:

      Ah, the BITMAPFILEHEADER throws the BITMAPINFO’s alignment out of sync? That’s unfortunate.

  3. Marcel says:

    A somewhat related question for anybody in the know: I’ve written a 68k emulator which includes a frame buffer, so I need constant and fast direct pixel access. When porting it from DOS to Windows 20 years ago I went with the DirectDraw3 interface, which amazingly still works to this day but graphics driver support finally seems to diminish. Now I’m looking for a newer API which fits the criteria a) fast, b) smooth/filtered hardware stretching, c) usable from C and Win7. GDI is fast enough but stretching looked a lot worse here (even with StretchBltMode HALFTONE). SDL uses GDI and does stretching in software (shudder). OpenGL is not designed for direct pixel access or at least makes it sound very slow. Direct2D looks amazingly complicated and also seem to be geared towards vectors and not pixel access. D3D with a USAGE_DYNAMIC texture sounds hopeful, but I shudder at the thought of learning D3D just to draw one flat texture.

    Any suggestions?

    1. Darran Rowe says:

      My suggestion is to try things out because it may surprise you.
      For example, Direct2D can deal with pixel based stuff, but there is no convenient wrapper for it. You will be updating the individual pixels in your process’ address space and then updating the Direct2D bitmap.
      But anyway, the thing to remember is that something that may “seem slow” may not actually be slow. Since you are going to be updating the bitmap pixel by pixel, this is going to have to reside in system memory, not graphics memory, because you need to access it from the CPU. Once it is ready to display, it is then going to be transferred to the graphics memory. I don’t remember DirectDraw’s API, but for it to be accessible by the GPU but editable by the CPU, this is how it must have worked under the surface. (Pun intended :3)
      So just try things out, you may be surprised.

      1. Daniel Newby says:

        If you’re modifying a CPU pixel array and wanting to generate D2D or GDI compatible bitmaps from that on a “frame by frame” basis, then WIC can help. D2D can do this, but modifying the same texture repeatedly through D2D pixel by pixel might actually be slower than creating a new D2D bitmap for your target device from memory via WIC every frame, (and doing so for an accelerated device if you’re not maintaining a CPU side copy already certainly will be).

        Using D3D for this is very easy, and may even be easier than using D2D. You need to create the D3D device and swap chain (D3D11CreateDeviceAndSwapChain), map the correct back buffer view, memcpy your pixels, unmap and present. The same caveats apply as with accelerated D2D.

      2. Marcel says:

        Thanks for the reply Darren. I’ll have a look at Direct2D then, though it seems a pain to use from C. But so was DirectDraw ;)

        1. kantos says:

          Direct2D and DirectWrite cannot be used from C, the interfaces are not exported in a C compatible way.

          It is geared towards vectors because it does the drawing and scaling for you so you can support high DPI displays easily.

          1. poizan42 says:

            What do you mean by that? Right in the introduction of the Direct2D API Overview it says:

            > Direct2D provides an API, similar to Direct3D, for use with C or C++.

            There’s clearly a plain C API in there, you don’t have to use the C++ wrappers.

          2. Darran Rowe says:

            They removed the C interfaces from the Windows SDK starting from 14393, up until then they were there.
            Because Direct2D is COM, it must be possible to access it from C, if the definitions are available. COM provides binary compatibility to access these interfaces from multiple languages, including C after all.
            So, with the 10586 Windows SDK, it will be possible to get the C style definitions and maybe even write your own for those added in newer versions. This obviously wouldn’t be technically supported but it is possible.

          3. Darran Rowe says:

            Also, yes, it is geared towards vectors, but that doesn’t make it unable to access pixels directly.
            ID2D1Bitmap gave you CopyFromMemory, so you could update the bitmap from a block of memory. This bitmap resided in the graphics memory. ID2D1Bitmap1 gave you the ability to create it in a CPU writable way, so you could then map it and write to or read from it.
            There is nothing more that you need really. For the rest of it you would essentially treat the bitmaps as something sprite based.
            So it may be geared towards vectored, but this is only because the sprite based stuff doesn’t need that much work.

          4. kantos says:

            @Darran Rowe, I would say that D2D is “COMLike.” It is not COM by any stretch of the term as it does not require a CoInitializeEx call

          5. Darran Rowe says:

            Of course, that is neither here nor there because Direct2D uses a factory function to create the factory interface. Unless you have reversed engineered this function, how do you know the factory function itself doesn’t call CoInitializeEx?

          6. kantos says:

            Because I did some Direct2D recently and OLE was not loaded

          7. poizan42 says:

            It may be worth pointing out that even a “C++ only” API can actually be called from C if you want to go through some (possible a lot) of hoops. You can get at the decorated function names by either telling the linker to map the C indentifiers to the mangled names, or by using GetProcAddress. You can get __thiscall on x86 by declaring the functions as __fastcall and inserting a second dummy argument (it goes into edx, which isn’t used by __thiscall) – on x64 __thiscall, __stdcall and __cdecl are luckily all the same, so the this pointer just goes into the first argument. You may have to figure details about the layout of stdlib classes out and hope they don’t change (but that would also break binary compatibility, so would probably be avoided)

          8. Darran Rowe says:

            Then if that is the case, if they are following the rules of COM to make it COM like, then again it is still perfectly usable from C. The compiler would still lay out the vtable in the same way regardless. As an example of this, Direct3D and DXGI uses factory functions to start things off, so they have the potential to be COM like, as you describe it. Yet they still have all of the C definitions available and they are still usable through C.

          9. Darran Rowe says:

            And if COM was not initialised on the thread when you used Direct2D, then since Direct2D depends on Direct3D and DXGI, then neither of these are COM, but COM like API.

          10. kantos says:

            @poizan42 despite my pedantry Darren Rowe is right. It is “COMLike” enough you can use COM for parts of it (I nearly did when writing a custom text renderer for DirectWrite until I realized that was dumb).

            @Darran Rowe I suspect they are “COMLike” and not actual COM for performance reasons, given all that Raymond has elucidated on the pitfalls of getting yourself in the wrong apartment for the component you’re loading it makes little sense to do that in an API that is always multi-threaded, performance oriented, and deliberately not designed to be used with automation. If I was to guess they used the COM style classes and idioms because it allowed them many of the benefits of COM: implementation hiding, interface versioning, reference counting, etc. and just dumped what didn’t make sense for their use case.

          11. 640k says:

            Apparently raymond thinks anything using vtables are not just comlike, but actually true COM.

          12. I said the opposite. I said, “I will not get dragged into a game of no true Scotsman.” You are the one who is going on about what is “true” COM.

          13. Klimax says:

            IUnknown says hi.
            DirectX is COM API. Maybe not pure nor using most of it, but it is basic COM and almost always was. For one, early versions required CoInitialize(Ex). (IIRC Up to DirectX 8 or so)
            Second, documentation is unambiguous. In Direct3D 9 it says outright: “The IDirect3DDevice9 interface is obtained by calling the IDirect3D9::CreateDevice method. (https://msdn.microsoft.com/en-us/library/windows/desktop/bb174336)

            This interface, like all COM interfaces, inherits the IUnknown interface methods.”
            And Direct3D 11 has “The ID3D11Device interface inherits from the IUnknown interface.” (https://msdn.microsoft.com/en-us/library/windows/desktop/ff476379) And links to https://msdn.microsoft.com/en-us/library/windows/desktop/ms680509 Which is part of “COM Fundamentals”.

            There you have it. Any questions?

          14. Darran Rowe says:

            I was only really in this because of a silly assumption which made me misunderstand something. That is why I gave up part way through, that and the fact that I noticed how silly things were. In the end, the only important thing is the binary layout, it doesn’t matter if you call it COM or COM like.
            The biggest misunderstanding that I had originally was I felt that there was an implication of it not being a COM compatible layout. This would be a bad thing because of compatibility. The COM binary interface is still the only standard class like interface on Windows, so not using this would be bad for other compilers. But then I realised that I misunderstood this so I made my biggest point and left it there. I will still call it the COM interface though, because it involves less typing and it is descriptive enough to imply the IUnknown base and vtable layout. :P

  4. cSharpFanboy says:

    I mostly use GDI from C#. Does anybody know when the above functions are called from the GDI+ .net code?

Comments are closed.

Skip to main content