windows-phone-8.1pngwindows-8.1win-universal-applumia-imaging-sdk

How to encode IImageProvider as a PNG image?


Assuming I have a LumiaImagingSDK rendering chain setup, with a final IImageProvider object that I want to render, how do I encode that into a PNG image?


Solution

  • Lumia Imaging SDK supports PNG images as input, however there isn't a "PNG Renderer" avaliable in the SDK.

    Luckily if you are developing for Windows 8.1 (StoreApplication / universal application / Windows phone 8.1 project) there is a Windows encoder (Windows.Graphics.Imaging.BitmapEncoder) you can use.

    Assuming the IImageProvider you want to render is called "source" this is a code snippet you can use to encode the resulting image as PNG:

    using Lumia.Imaging;
    using Windows.Graphics.Imaging;
    using System.IO;
    
    ...
    
    using (var renderer = new BitmapRenderer(source, ColorMode.Bgra8888))
    {
        var bitmap = await renderer.RenderAsync();
        byte[] pixelBuffer = bitmap.Buffers[0].Buffer.ToArray();
    
    
        using (var stream = new InMemoryRandomAccessStream())
        {
            var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream).AsTask().ConfigureAwait(false);
            encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, (uint)bitmap.Dimensions.Width, (uint)bitmap.Dimensions.Height, 96, 96, pixelBuffer);
            await encoder.FlushAsync().AsTask().ConfigureAwait(false);
    
           //If InMemoryRandomAccessStream (IRandomAccessStream) works for you, end here.
           //If you need an IBuffer, here is how you get one:
    
            using (var memoryStream = new MemoryStream())
            {
                memoryStream.Capacity = (int)stream.Size;
                var ibuffer = memoryStream.GetWindowsRuntimeBuffer();
                await stream.ReadAsync(ibuffer, (uint)stream.Size, InputStreamOptions.None).AsTask().ConfigureAwait(false);
            }
        }
    }
    

    This will give you bytes in memory as either InMemoryRandomAccessStream (IRandomAccessStream) or an IBuffer depending on what you need. You can then save the buffer to disk or pass it to other parts of your application.