{"id":109052,"date":"2023-11-22T07:00:00","date_gmt":"2023-11-22T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=109052"},"modified":"2023-11-22T09:10:31","modified_gmt":"2023-11-22T17:10:31","slug":"20231122-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20231122-00\/?p=109052","title":{"rendered":"How can I convert a Windows Runtime <CODE>Software&shy;Bitmap<\/CODE> to a WIC bitmap?"},"content":{"rendered":"<p>Some time ago, I concluded a series of articles on <a title=\"How can I convert a WIC bitmap to a Windows Runtime SoftwareBitmap? part 4: Handing it over\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20230414-00\/?p=108051\"> how to convert a WIC bitmap to a Windows Runtime <code>Software\u00adBitmap<\/code><\/a>. What about the reverse?<\/p>\n<p>As I hinted in the Bonus Chatter, you can use the <code>ISoftware\u00adBitmap\u00adNative<\/code> interface to reach inside the <code>Software\u00adBitmap<\/code> and access the <code>IWICBitmap<\/code> hiding inside, if it has one.<\/p>\n<pre>#include &lt;windows.graphics.imaging.interop.h&gt;\r\n#include &lt;winrt\/Windows.Graphics.Imaging.h&gt;\r\n\r\nwinrt::com_ptr&lt;IWICBitmap&gt;\r\n    GetWICBitmap(winrt::Windows::Graphics::Imaging::SoftwareBitmap const&amp; bitmap)\r\n{\r\n    winrt::com_ptr wicBitmap;\r\n    bitmap.as&lt;ISoftwareBitmapNative&gt;()-&gt;GetData(IID_PPV_ARGS(wicBitmap.put()));\r\n    return wicBitmap;\r\n}\r\n<\/pre>\n<p>Alternatively, if you like one-liners:<\/p>\n<pre>winrt::com_ptr&lt;IWICBitmap&gt;\r\n    GetWICBitmap(winrt::Windows::Graphics::Imaging::SoftwareBitmap const&amp; bitmap)\r\n{\r\n    return winrt::try_capture&lt;IWICBitmap&gt;(\r\n        bitmap.as&lt;ISoftwareBitmapNative&gt;(),\r\n        &amp;ISoftwareBitmapNative::GetData);\r\n}\r\n<\/pre>\n<p>The problem is that if the <code>Software\u00adBitmap<\/code> is in a video format, the wrapped bitmap will be a <code>IMF2DBuffer<\/code>, not a <code>IWICBitmap<\/code>, and the call to <code>Get\u00adData<\/code> fails. In that case, we can convert the <code>Software\u00adBitmap<\/code> to a WIC format and try again.<\/p>\n<pre>namespace winrt\r\n{\r\n    using namespace winrt::Windows::Graphics::Imaging;\r\n}\r\n\r\nwinrt::com_ptr&lt;IWICBitmap&gt;\r\n    GetWICBitmap(winrt::SoftwareBitmap const&amp; bitmap)\r\n{\r\n    auto result = winrt::try_capture&lt;IWICBitmap&gt;(\r\n        bitmap.as&lt;ISoftwareBitmapNative&gt;(),\r\n        &amp;ISoftwareBitmapNative::GetData);\r\n    if (!result) {\r\n        auto converted = winrt::SoftwareBitmap::\r\n            Convert(bitmap, BitmapPixelFormat::Rgba8);\r\n\r\n        result = winrt::try_capture&lt;IWICBitmap&gt;(\r\n            converted.as&lt;ISoftwareBitmapNative&gt;(),\r\n            &amp;ISoftwareBitmapNative::GetData);\r\n    }\r\n    return result;\r\n}\r\n<\/pre>\n<p>Note that in this second case, we are returning a copy of the pixels, since we did a conversion from the original format.<\/p>\n<p>Now, maybe you want the <code>IWICBitmap<\/code> to have a specific format. In that case, you could force a conversion if the original <code>Software\u00adBitmap<\/code> is not to your liking.<\/p>\n<pre>winrt::com_ptr&lt;IWICBitmap&gt;\r\n    GetWICBitmapInFormat(\r\n        winrt::SoftwareBitmap const&amp; bitmap,\r\n        winrt::BitmapPixelFormat format,\r\n        winrt::BitmapAlphaMode alphaMode)\r\n{\r\n    winrt::SoftwareBitmap converted{ nullptr };\r\n    if (bitmap.BitmapPixelFormat() == format &amp;&amp;\r\n        bitmap.BitmapAlphaMode() == alphaMode) {\r\n        converted = bitmap;\r\n    } else {\r\n        converted = winrt::SoftwareBitmap::Convert(bitmap, format, alphaMode);\r\n    }\r\n    return winrt::capture&lt;IWICBitmap&gt;(\r\n            converted.as&lt;ISoftwareBitmapNative&gt;(),\r\n            &amp;ISoftwareBitmapNative::GetData);\r\n}\r\n<\/pre>\n<p>If the <code>Software\u00adBitmap<\/code> is already in the desired format, then you will get an <code>IWICBitmap<\/code> that shares pixels with the source. Otherwise, you get a private <code>IWICBitmap<\/code> whose pixels you are free to modify. If you&#8217;d rather get a private one all the time, you could force the conversion unconditionally.<\/p>\n<pre>winrt::com_ptr&lt;IWICBitmap&gt;\r\n    GetCopyAsWICBitmap(\r\n        winrt::SoftwareBitmap const&amp; bitmap,\r\n        winrt::BitmapPixelFormat format,\r\n        winrt::BitmapAlphaMode alphaMode)\r\n{\r\n    auto converted = winrt::SoftwareBitmap::Convert(bitmap, format, alphaMode);\r\n    return winrt::capture&lt;IWICBitmap&gt;(\r\n            converted.as&lt;ISoftwareBitmapNative&gt;(),\r\n            &amp;ISoftwareBitmapNative::GetData);\r\n}\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>The reverse of <CODE>ISoftware&shy;Bitmap&shy;Native&shy;Factory::<WBR>Create&shy;From&shy;WIC&shy;Bitmap<\/CODE>.<\/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-109052","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>The reverse of <CODE>ISoftware&shy;Bitmap&shy;Native&shy;Factory::<WBR>Create&shy;From&shy;WIC&shy;Bitmap<\/CODE>.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109052","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=109052"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109052\/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=109052"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=109052"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=109052"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}