Passing a Win32 HBITMAP to WinRT/UWP SoftwareBitmap

Categories Computer Science, Microsoft, Software, Uncategorized, Windows0 Comments

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;
    }