Save WriteableBitmap as StorageFile in WinRT App

Introduction

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. WritableBitmap is more often used with a WriteableBitmapEx library which is a collection of extension methods for the WriteableBitmap.

We won't go for manipulating images using WriteableBitmap or WriteableBitmapEx, we will instead proceed to the next step, which is saving it as a file; in other words, a StorageFile. It's obvious that the end-user will definitely want to share or save the modified image or it is better to say WriteableBitmap. So we will need to convert the WriteableBitmap to a StorageFile.

Before going directly to the code, let me explain the API used in that. For image encoding, WinRT offers the BitmapEncoder class. For image encoding, we need to select a BitmapEncoderGuid that is basically formatted of the 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. Let's check out the code.

The following is the Metadata of the method and enum.

// Summary:
//     Specifies the alpha mode of pixel data.
public enum BitmapAlphaMode
{
    // Summary:
    //     The alpha value has been premultiplied. Each color is first scaled by the
    //     alpha value. The alpha value itself is the same in both straight and premultiplied
    //     alpha. Typically, no color channel value is greater than the alpha channel
    //     value. If a color channel value in a premultiplied format is greater than
    //     the alpha channel, the standard source-over blending math results in an additive
    //     blend.
    Premultiplied = 0,
    //
    // Summary:
    //     The alpha value has not been premultiplied. The alpha channel indicates the
    //     transparency of the color.
    Straight = 1,
    //
    // Summary:
    //     The alpha value is ignored.
    Ignore = 2,
}

// Summary:
//     Specifies the pixel format of pixel data. Each enumeration value defines
//     a channel ordering, bit depth, and type.
public enum BitmapPixelFormat
{
    // Summary:
    //     The pixel format is unknown.
    Unknown = 0,
    //
    // Summary:
    //     The pixel format is R16B16G16A16 unsigned integer.
    Rgba16 = 12,
    //
    // Summary:
    //     The pixel format is R8G8B8A8 unsigned integer.
    Rgba8 = 30,
    //
    // Summary:
    //     The pixel format is B8G8R8A8 unsigned integer.
    Bgra8 = 87,
}

// Summary:
//     Sets the frame bitmap pixel data using the parameters specified in the arguments.
//
// Parameters:
//   pixelFormat:
//     The pixel format of the pixel data.
//
//   alphaMode:
//     The alpha mode of the pixel data.
//
//   width:
//     The width, in pixels, of the pixel data.
//
//   height:
//     The height, in pixels, of the pixel data.
//
//   dpiX:
//     The horizontal resolution, in dots per inch, of the pixel data.
//
//   dpiY:
//     The vertical resolution, in dots per inch, of the pixel data.
//
//   pixels:
//     The pixel data.
public void SetPixelData(BitmapPixelFormat pixelFormat, BitmapAlphaMode alphaMode,
    uint width, uint height, double dpiX, double dpiY, byte[] pixels);

Converting a WriteableBitmap object to a StorageFile

The following is the code to convert a WriteableBitmap object to a StorageFile in a WinRT app.

using System.Runtime.InteropServices.WindowsRuntime;

private 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;
}

private enum FileFormat
{
    Jpeg,
    Png,
    Bmp,
    Tiff,
    Gif
}

System.Runtime.InteropServices.WindowsRuntime.

I hope this article will be helpful to you. I request you to share it as much as you can.

Summary

In this article, we learned about Save WriteableBitmap as StorageFile in the WinRT App.


Similar Articles