0

I have been trying to convert a captured VideoFrame object to a byte array with little success. It is clear from the documentation that each frame can be saved to a SoftwareBitmap object, e.g.

SoftwareBitmap bitmap = frame.SoftwareBitmap;

I have been able to save this bitmap as an image but I would like to obtain it's data and store it in a byte array. Many SO questions already deal with this but the SoftwareBitmap belongs to the Windows.Graphics.Imaging namespace (not the more typical Xaml.Controls.Image which the other SO posts address, such as this one) so traditional methods like image.Save() are unavailable.

It seems that each SoftwareBitmap has a CopyToBuffer() method but the documentation on this is very terse with regards to how to actually use this. And I'm also not sure if that's the right way to go?

Edit:

Using Alan's recommendation below I've managed to get this working. I'm not sure if it's useful but here's the code I used if anyone else comes across this:

private void convertFrameToByteArray(SoftwareBitmap bitmap)
    {
        byte[] bytes;
        WriteableBitmap newBitmap = new WriteableBitmap(bitmap.PixelWidth, bitmap.PixelHeight);
        bitmap.CopyToBuffer(newBitmap.PixelBuffer);
        using (Stream stream = newBitmap.PixelBuffer.AsStream())
        using (MemoryStream memoryStream = new MemoryStream())
        {
            stream.CopyTo(memoryStream);
            bytes = memoryStream.ToArray();
        }

        // do what you want with the acquired bytes
        this.videoFramesAsBytes.Add(bytes);
    }
Community
  • 1
  • 1
Gordonium
  • 3,389
  • 23
  • 39

2 Answers2

2

By using the CopyToBuffer() method, you can copy pixel data to the PixelBuffer of a WriteableBitmap.

Then I think you can refer to the answer in this question to convert it to byte array.

Community
  • 1
  • 1
Alan Yao - MSFT
  • 3,284
  • 1
  • 17
  • 16
0

For anyone looking to access an encoded byte[] array from the SoftwareBitmap (e.g. jpeg):

private async void PlayWithData(SoftwareBitmap softwareBitmap)
{
    var data = await EncodedBytes(softwareBitmap, BitmapEncoder.JpegEncoderId);

    // todo: save the bytes to a DB, etc
}

private async Task<byte[]> EncodedBytes(SoftwareBitmap soft, Guid encoderId)
{
    byte[] array = null;

    // First: Use an encoder to copy from SoftwareBitmap to an in-mem stream (FlushAsync)
    // Next:  Use ReadAsync on the in-mem stream to get byte[] array

    using (var ms = new InMemoryRandomAccessStream())
    {
        BitmapEncoder encoder = await BitmapEncoder.CreateAsync(encoderId, ms);
        encoder.SetSoftwareBitmap(soft);

        try
        {
            await encoder.FlushAsync();
        }
        catch ( Exception ex ){ return new byte[0]; }

        array = new byte[ms.Size];
        await ms.ReadAsync(array.AsBuffer(), (uint)ms.Size, InputStreamOptions.None);
    }
    return array;
}
bunkerdive
  • 2,031
  • 1
  • 25
  • 28