3

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.

The Whether Man
  • 362
  • 5
  • 21
  • Why would you even want to use System.Drawing.Bitmap in WPF? It is a WinForms class. Besides that, the error is pretty clear. There is no Create() overload in BitmapFrame that would take a Windows.UI.Xaml.Media.Imaging.WriteableBitmap. – Clemens Jun 28 '18 at 14:40
  • @Clemens I'm using `AForge.Imaging`, which uses Bitmaps from that namespace for a lot of its operations. The code snippet in the question was more to show what I've tried so far, but I'm not sure how to proceed from there – The Whether Man Jun 28 '18 at 14:44

1 Answers1

8

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());
}
David Pine
  • 23,787
  • 10
  • 79
  • 107
Rob Caplan - MSFT
  • 21,714
  • 3
  • 32
  • 54