{"id":111225,"date":"2025-05-28T07:00:00","date_gmt":"2025-05-28T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=111225"},"modified":"2025-07-10T06:45:25","modified_gmt":"2025-07-10T13:45:25","slug":"20250528-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20250528-00\/?p=111225","title":{"rendered":"How do I convert a WIC bitmap back to a GDI <CODE>HBITMAP<\/CODE>?"},"content":{"rendered":"<p>The Windows Imaging Component (WIC) has a function for creating an <code>IWICBitmap<\/code> from a GDI <code>HBITMAP<\/code>. But how do you go the other way?<\/p>\n<p>One way is to lock the bitmap bits and then use <code>SetDIBits<\/code> to place them into a DIB section. We saw this trick when we were <a title=\"The case of the image that came out horribly slanted: Negative stride\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20240906-00\/?p=110228\"> debugging code that converts a Direct2D bitmap to a GDI <code>HBITMAP<\/code><\/a>. The downside of this is that it may result in a double-copy if the <code>IWICBitmapSource<\/code> has to generate the pixels on the fly (due to being the end of a chain of transforms).<\/p>\n<p>Instead, we can ask <code>CopyPixels<\/code> to generate the pixels directly into our DIB section.<\/p>\n<pre>HRESULT ConvertWICBitmapSourceToHBITMAP(\r\n    IWICBitmapSource* source,\r\n    HBITMAP* bitmap)\r\n{\r\n    *bitmap = nullptr;\r\n\r\n    \/\/ Convert to 32bpp if necessary.\r\n    wil::com_ptr&lt;IWICBitmapSource&gt; source32bpp;\r\n    RETURN_IF_FAILED(\r\n        WICConvertBitmapSource(GUID_WICPixelFormat32bppBGR, source,\r\n            source32bpp.put()));\r\n\r\n    \/\/ Create a 32bpp DIB section of matching size\r\n    UINT width, height;\r\n    RETURN_IF_FAILED(source32bpp-&gt;GetSize(&amp;width, &amp;height));\r\n\r\n    \/\/ Make sure the size won't create integer overflow.\r\n    RETURN_HR_IF(HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW),\r\n                 width &gt; (MAXDWORD \/ 4 \/ height));\r\n\r\n    BITMAPINFO bi{};\r\n    bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);\r\n    bi.bmiHeader.biWidth = width;\r\n    bi.bmiHeader.biHeight = -static_cast&lt;LONG&gt;(height); \/\/ top-down\r\n    bi.bmiHeader.biPlanes = 1;\r\n    bi.bmiHeader.biBitCount = 32;\r\n    bi.bmiHeader.biCompression = BI_RGB;\r\n    bi.bmiHeader.biSizeImage = width * height * 4;\r\n\r\n    void* bits;\r\n    wil::unique_hbitmap result(CreateDIBSection(nullptr, &amp;bi,\r\n            DIB_RGB_COLORS, &amp;bits, nullptr, 0));\r\n    RETURN_LAST_ERROR_IF_NULL(result);\r\n\r\n    <span style=\"border: solid 1px currentcolor; border-bottom: none;\">\/\/ Copy the pixels into the bitmap                            <\/span>\r\n    <span style=\"border: 1px currentcolor; border-style: none solid;\">RETURN_IF_FAILED(source32bpp-&gt;CopyPixels(nullptr, width * 4,  <\/span>\r\n    <span style=\"border: solid 1px currentcolor; border-top: none;\">    bi.bmiHeader.biSizeImage, reinterpret_cast&lt;BYTE*&gt;(bits)));<\/span>\r\n\r\n    \/\/ All done\r\n    *bitmap = result.release();\r\n    return S_OK;\r\n}\r\n<\/pre>\n<p>We convert the WIC bitmap to 32-bit BGR format, since that&#8217;s the format that GDI uses for 32-bit DIBs. Then we create a 32-bit DIB section with the same dimensions as the WIC bitmap and use <code>CopyPixels<\/code> to tell the WIC bitmap to generate pixels into the DIB section buffer.<\/p>\n<p>This code always creates a 32-bit DIB section. You could extend the function to query the WIC bitmap for its pixel format and create a matching GDI bitmap, but in practice almost nobody uses any GDI color formats besides 32-bit DIB and 32-bit DIB with premultiplied alpha. (32-bit DIB with straight alpha is also popular, but that&#8217;s not a GDI color format.)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>You can copy the bits into a DIB section.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-111225","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>You can copy the bits into a DIB section.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/111225","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=111225"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/111225\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=111225"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=111225"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=111225"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}