Converting WritableBitmap to StorageFile in Universal Windows Apps

WriteableBitmap is quite useful when an app requires image processing. It provides a BitmapSource, that can be written and manipulated. Ultimately that bitmap source is supplied to an image control of a Windows Store app. We are going to save the WritableBitmap to a StorageFile in our app.

For image encoding WinRT offers the BitmapEncoder class. For image encoding we need to select a BitmapEncoderGuid that is basically a formatted of image, such as JPEG, PNG, TIFF, and so on. It’s actually a unique identifier for each bitmap encoder.

We will first export WriteableBitmap’s pixel buffer into a byte array. Then we will initialize the bitmap encoder with a GUID and destination file stream. Finally we will set the pixel data to a bitmap encoder. Bitmap encoder’s SetPixelData(...) gets various parameters to write the pixels in various ways. Check out the method metadata given below. At last we will have the file ready.

public class ImageUtils
{
    public static async Task<StorageFile> WriteableBitmapToStorageFile(WriteableBitmap WB, FileFormat fileFormat)
    {
        string FileName = "MyFile.";
        Guid BitmapEncoderGuid = BitmapEncoder.JpegEncoderId;
        switch (fileFormat)
        {
            case FileFormat.Jpeg:
                FileName += "jpeg";
                BitmapEncoderGuid = BitmapEncoder.JpegEncoderId;
                break;
            case FileFormat.Png:
                FileName += "png";
                BitmapEncoderGuid = BitmapEncoder.PngEncoderId;
                break;
            case FileFormat.Bmp:
                FileName += "bmp";
                BitmapEncoderGuid = BitmapEncoder.BmpEncoderId;
                break;
            case FileFormat.Tiff:
                FileName += "tiff";
                BitmapEncoderGuid = BitmapEncoder.TiffEncoderId;
                break;
            case FileFormat.Gif:
                FileName += "gif";
                BitmapEncoderGuid = BitmapEncoder.GifEncoderId;
                break;
        }
        var file = await Windows.Storage.ApplicationData.Current.TemporaryFolder
    .CreateFileAsync(FileName, CreationCollisionOption.GenerateUniqueName);
        using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
        {
            BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoderGuid, stream);
            Stream pixelStream = WB.PixelBuffer.AsStream();
            byte[] pixels = new byte[pixelStream.Length];
            await pixelStream.ReadAsync(pixels, 0, pixels.Length);
            encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore,
                      (uint)WB.PixelWidth,
                      (uint)WB.PixelHeight,
                      96.0,
                      96.0,
                      pixels);
            await encoder.FlushAsync();
        }
        return file;
    }
    public enum FileFormat
    {
        Jpeg,
        Png,
        Bmp,
        Tiff,
        Gif
    }
}

Don’t forget to add the namespace System.Runtime.InteropServices.WindowsRuntime.

To use the converter call it as follows.

StorageFile savedStorageFile= await ImageUtils.WriteableBitmapToStorageFile(ImageCropper.CroppedImage, ImageUtils.FileFormat.Png);