Passing a Win32 HBITMAP to WinRT/UWP SoftwareBitmap
With the advent of machine learning and visual recognition it goes without saying that passing graphical information in memory is a more common scenario. This code snippet hopes to help the many queries that try to accomplish it in the Windows ecosystem. Especially going from Win32 to WinRT/UWP world.
PICTDESC pd; // Capture picture info and plug the HBITMAP LPPICTURE picture; // Holds our picture data LPSTREAM stream; // Staging bridge buffer to WinRT/UWP // WinRT Buffer receiving bitmap data. ComPtr spRandomAccessStream;
We get the bitmap buffer from COM API
bool result = false; pd.cbSizeofstruct = sizeof(PICTDESC); pd.picType = PICTYPE_BITMAP; pd.bmp.hbitmap = hBitmap; pd.bmp.hpal = NULL; HRESULT res = OleCreatePictureIndirect(&pd, IID_IPicture, false, reinterpret_cast<void**>(&picture)); if (!SUCCEEDED(res)) return; res = CreateStreamOnHGlobal(0, true, &stream); if (!SUCCEEDED(res)) { picture->Release(); return; }
Marshaling bitmap buffer from COM API world to WinRT/UWP space.
CreateRandomAccessStreamOverStream(stream, BSOS_DEFAULT, IID_PPV_ARGS(&spRandomAccessStream));
Once we have the RandomAccessStream populated it’s vanilla WinRT walk in the park:
task< BitmapDecoder^ > getDecoderTask(BitmapDecoder::CreateAsync((reinterpret_cast(spRandomAccessStream.Get())))); auto continuation = getDecoderTask.then([](BitmapDecoder ^bitmapDecoder) { task getSoftwareBitmap(bitmapDecoder->GetSoftwareBitmapAsync()); getSoftwareBitmap.then([](SoftwareBitmap ^softwareBitmap) { // softwareBitmap is your bitmap in WinRT/UWP World! }); }); // Wait for the continuation to finish and handle any // error that occurs. try { wcout << L"Waiting for tasks to finish..." << endl; continuation.wait(); // Alternatively, call get() to produce the same result. //continuation.get(); } catch (const exception& e) { wcout << L"Caught exception." << endl; }