The WhetherMan
The WhetherMan

Reputation: 361

How to convert UWP SoftwareBitmap to WPF Bitmap?

I'm trying to get a SoftwareBitmap to be usable by stuff in WPF as a Bitmap. Approaches like this question shows look promising, but they seem to be using objects from different namespaces that don't quite work in my case. For context, I'm using MediaCapture from UWP land for webcam streaming in my app which is WPF.

public static WriteableBitmap WriteableBitmapFromSoftwareBitmap(SoftwareBitmap soft)
{
    WriteableBitmap writeable = new 
    WriteableBitmap(soft.PixelWidth, soft.PixelHeight);
    soft.CopyToBuffer(writeable.PixelBuffer);

    return writeable;
}

public static Bitmap BitmapFromWriteableBitmap(WriteableBitmap writeBmp)
{
    Bitmap bmp;
    using (MemoryStream outStream = new MemoryStream())
    {
        System.Windows.Media.Imaging.BitmapEncoder enc = new 
            BmpBitmapEncoder();

        enc.Frames.Add(BitmapFrame.Create(writeBmp)); // Error here
        enc.Save(outStream);
        bmp = new Bitmap(outStream);
    }

    return bmp;
}

Unfortunately, in BitmapFromWriteableBitmap, the call to BitmapFrame.Create is complaining that it can't create a URI from that kind of WriteableBitmap.

Note that the WriteableBitmap is a Windows.UI.Xaml.Media.Imaging.WriteableBitmap, the SoftwareBitmap is a Windows.Graphics.Imaging.SoftwareBitmap, and the desired Bitmap is a System.Drawing.Bitmap.

Upvotes: 3

Views: 4837

Answers (1)

Rob Caplan - MSFT
Rob Caplan - MSFT

Reputation: 21919

There is no direct conversion. You'll need to extract the image data from the SoftwareBitmap and then create the new Bitmap from that data.

This is essentially what the linked question does: it encodes the data from the WriteableBitmap into a .BMP stream and then loads the System.Drawing.Bitmap from that stream.

You can do the same from the SoftwareBitmap by using Windows.Graphics.Imaging.BitmapEncoder.SetSoftwareBitmap to convert its contents to an image stream and then create a new System.Drawing.Bitmap from that stream.

See Save a SoftwareBitmap to a file with BitmapEncoder for sample code. You can render to an InMemoryRandomAccessStream instead of a StorageFile's stream to avoid saving to disk, and can use AsStream to convert it to a .Net System.IO.Stream to read into the System.Drawing.Bitmap something like the following (untested) snippet:

using (var stream = new Windows.Storage.Streams.InMemoryRandomAccessStream())
{
    BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
    encoder.SetSoftwareBitmap(softwareBitmap);
    await encoder.FlushAsync();
    bmp = new System.Drawing.Bitmap(stream.AsStream());
}

Upvotes: 9

Related Questions