{"id":108037,"date":"2023-04-11T07:00:00","date_gmt":"2023-04-11T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=108037"},"modified":"2023-04-11T10:58:19","modified_gmt":"2023-04-11T17:58:19","slug":"20230411-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20230411-00\/?p=108037","title":{"rendered":"How can I convert a WIC bitmap to a Windows Runtime SoftwareBitmap? part 1: Via an encoded stream"},"content":{"rendered":"<p>Say you have produced a bitmap with the Windows Imaging Component, also known as WIC, and you want to convert it to a Windows Runtime <code>Software\u00adBitmap<\/code>, say, because you want to use it as a XAML <code>Software\u00adBitmap\u00adSource<\/code> so you can display it in a XAML <code>BitmapImage<\/code>.<\/p>\n<p>We&#8217;ll be trying to solve this problem over the next few days, coming up with simpler and simpler solutions, until we get down to a one-liner. But let&#8217;s not get ahead of ourselves.<\/p>\n<p>Well, let&#8217;s see. There are only a few Windows Runtime methods that produce a <code>Software\u00adBitmap<\/code>. There are some conversion methods on <code>Software\u00adBitmap<\/code> itself, but they assume you already have a <code>Software\u00adBitmap<\/code>. Fortunately, there&#8217;s also <code>Bitmap\u00adDecoder<\/code>.<\/p>\n<p>So you might come up with this:<\/p>\n<pre>namespace winrt\r\n{\r\n    using namespace winrt::Windows::Foundation;\r\n    using namespace winrt::Windows::Graphics::Imaging;\r\n    using namespace winrt::Windows::Storage::Streams;\r\n}\r\n\r\nwinrt::IAsyncOperation&lt;winrt::SoftwareBitmap&gt;\r\n    ToSoftwareBitmap(IWICBitmapSource* wicBitmap)\r\n{\r\n    \/\/ Boilerplate code to <a href=\"https:\/\/docs.microsoft.com\/en-us\/archive\/msdn-magazine\/2008\/april\/windows-with-c-windows-imaging-component-basics\">save the bitmap as a PNG stream<\/a>\r\n    winrt::com_ptr&lt;::IStream&gt; stream;\r\n    winrt::check_hresult(\r\n        CreateStreamOnHGlobal(nullptr, TRUE, stream.put()));\r\n    auto bitmapEncoder = winrt::create_instance&lt;\r\n        IWICBitmapEncoder&gt;(CLSID_WICPngEncoder);\r\n    winrt::check_hresult(bitmapEncoder-&gt;Initialize(\r\n        stream.get(), WICBitmapEncoderNoCache));\r\n    winrt::com_ptr&lt;IWICBitmapFrameEncode&gt; frameEncoder;\r\n    winrt::check_hresult(bitmapEncoder-&gt;CreateNewFrame(\r\n        frameEncoder.put(), nullptr));\r\n    winrt::check_hresult(frameEncoder-&gt;Initialize(nullptr));\r\n    winrt::check_hresult(frameEncoder-&gt;WriteSource(\r\n        wicBitmap, nullptr));\r\n    winrt::check_hresult(frameEncoder-&gt;Commit());\r\n    winrt::check_hresult(bitmapEncoder-&gt;Commit());\r\n\r\n    \/\/ Rewind the stream so we can load it into a BitmapDecoder\r\n    winrt::check_hresult(stream-&gt;Seek(\r\n        { 0, 0 }, STREAM_SEEK_SET, nullptr));\r\n\r\n    \/\/ Convert to a Windows Runtime RandomAccessStream.\r\n    auto randomAccessStream = winrt::capture&lt;\r\n        winrt::IRandomAccessStream&gt;(\r\n        CreateRandomAccessStreamOverStream, stream.get(),\r\n        BSOS_DEFAULT);\r\n\r\n    \/\/ Convert the stream to a SoftwareBitmap.\r\n    auto decoder = co_await winrt::BitmapDecoder::CreateAsync(\r\n        randomAccessStream);\r\n    co_return co_await decoder.GetSoftwareBitmapAsync();\r\n}\r\n<\/pre>\n<p>This is very straightforward, but quite cumbersome. And you might feel a littly icky that you&#8217;re encoding the bitmap as a PNG, only to immediately decode it back into a bitmap. Plus there&#8217;s the complication that the Windows Runtime <code>BitmapDecoder<\/code> decodes asynchronously, so you have to do coroutine stuff to get the answer out.<\/p>\n<p>Fortunately, there&#8217;s a better way. We&#8217;ll look at it next time.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We&#8217;ll start with the hard way, but it gets easier.<\/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-108037","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>We&#8217;ll start with the hard way, but it gets easier.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/108037","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=108037"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/108037\/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=108037"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=108037"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=108037"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}