Save WriteableBitmap as StorageFile in WinRT App

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 that is a collection of extension methods for the WriteableBitmap.

We won't go for manipulating images using WriteableBitmap or WriteableBitmapEx, we will insead 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 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. 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
}

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

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

Up Next
    Ebook Download
    View all
    Learn
    View all