Search code examples
c#windows-runtimewinui-3

Rotating image captured from Webcam in WinUI3


I'm trying to capture images from a Webcam in a WinUI3 app. After some trial and error, I finally managed to do so via MediaFrameReader. Now I've got the captured images as SoftwareBitmap and as I'd like to feed these images to OCR, I need to rotate them.

I've already tried several ways to rotate the images:

  1. MediaCapture.SetPreviewRotation does not seem to work with MediaFrameReader (and I haven't found any way to use the VideoPreview stream to capture images without having a CameraPreview control attached as sink)
  2. Setting it via MediaCapture.SetEncodingPropertiesAsync also doesn't seem to work (might also only work when you're using the VideoPreview stream)
  3. Rotating the SoftwareBitmap itself, by converting it to a PNG or BMP stream with BitmapEncoder and a BitmapTransform.Rotation set and decoding it with BitmapDecoder. This results in a correctly rotated image with the right dimension, but completely black

Note: I don't want to display the image rotated, so RenderTransform/LayoutTransform in my apps Xaml are not what I'm looking for here.


Solution

  • Here is a sample code that will perform a clockwise rotation of 180 degrees on a WinRT's SoftwareBitmap:

    // prepare a memory buffer
    using var ms = new MemoryStream();
    
    // create an encoder
    // set a bitmap transform, here a 180 degrees rotation
    var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, ms.AsRandomAccessStream());
    encoder.BitmapTransform.Rotation = BitmapRotation.Clockwise180Degrees;
    
    // write the software bitmap to the memory buffer
    encoder.SetSoftwareBitmap(softwareBitmap);
    await encoder.FlushAsync();
    
    // create a decoder to get the rotated result
    var decoder = await BitmapDecoder.CreateAsync(ms.AsRandomAccessStream());
    
    // get the new software bitmap
    // Bgra8, Premultiplied are optional
    // but mandatory if you want to use it in a SoftwareBitmapSource for example
    var rotated = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
    

    Note this is in fact unrelated to WinUI3.