How to encode a new image (XAML)
[ This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation ]
We show you how to save a new image to a file using a BitmapEncoder object. If you want to make changes to an existing image, see How to edit an image.
What you need to know
Technologies
Prerequisites
- We assume you know how to create a basic Windows Runtime app using C++, C#, or Visual Basic. For more info, see Create a "Hello, world" app (XAML).
Instructions
Step 1: Use the file picker to pick a destination file
The FileSavePicker lets the user pick a new or existing file from their system. After you get the file from the picker, you can use it as the destination for the BitmapEncoder.
First, create a new file picker object, set the file type options to allow JPEG images, and display the picker to the user.
async void EncodeImage()
{
var picker = new Windows.Storage.Pickers.FileSavePicker();
picker.FileTypeChoices.Add("JPEG image", new string[] { ".jpg" });
picker.DefaultFileExtension = "jpg";
var file = await picker.PickSaveFileAsync();
if (file == null)
{
// The user cancelled.
}
Note You can add more extensions to the file type filter. See Windows.Storage.Pickers for more info.
Note You can get a list of all the supported encoders and file extensions by using Windows.Graphics.Imaging.BitmapEncoder.getEncoderinfoEnumerator.
Step 2: Create an encoder object for a new image
When you have the destination file, get an IRandomAccessStream with ReadWrite access privileges from the file, which you use to instantiate the BitmapEncoder. You also need to determine the correct encoder ID for the file type the user selected. This example allows only JPEG images, so if you allow multiple file types you need to switch based on the file’s FileType parameter.
System.Guid encoderId;
switch (file.FileType)
{
case ".jpg":
default:
encoderId = Windows.Graphics.Imaging.BitmapEncoder.JpegEncoderId;
break;
}
using (var stream = await file.OpenAsync(
Windows.Storage.FileAccessMode.ReadWrite
))
{
stream.Size = 0;
var encoder = await Windows.Graphics.Imaging.BitmapEncoder.CreateAsync(
encoderId,
stream
);
Note The built-in encoder IDs are available as static members of BitmapEncoder.
If the user selects an already existing file to save to, you must set IRandomAccessStream.size to 0 because BitmapEncoder requires the output stream to be empty.
Note The using keyword provides a convenient syntax to guarantee the correct usage of IDisposable objects such as implementations of IRandomAccessStream. If you do not use using, then you need to explicitly call the Dispose method on the stream when are you done with it.
You now have a BitmapEncoder representing an empty JPEG image.
Step 3: Set some data on the encoder
Now that you have the BitmapEncoder object, you can set metadata and pixel data, plus control thumbnails and transforms, like rotation and scaling.
The code here sets a trivial pixel data array. For more info about setting imaging properties and metadata, see How to write image metadata. For more info about transforming the image, see How to edit an image.
// An array representing 2x2 red, opaque pixel data
var pixels = new byte[] {
255, 0, 0, 255,
255, 0, 0, 255,
255, 0, 0, 255,
255, 0, 0, 255
};
encoder.SetPixelData(
Windows.Graphics.Imaging.BitmapPixelFormat.Rgba8,
Windows.Graphics.Imaging.BitmapAlphaMode.Straight,
2, // pixel width
2, // pixel height
96, // horizontal DPI
96, // vertical DPI
pixels
);
Note If you create a BitmapEncoder using the CreateAsync method, the minimum info you must provide to create a valid image is pixel data using the SetPixelData method.
Step 4: Save the changes to the file
When you're done editing the BitmapEncoder, you must flush the encoder and close the underlying stream before using the file. If you don't do this, the image won't be saved and the data is lost.
Finally, handle any errors. If you try to perform an encoding action that isn't supported by the file format or is otherwise invalid, you won't get an error until you call FlushAsync. That is, FlushAsync fails if you try to save a thumbnail by setting IsThumbnailGenerated to True in a format such as BMP (which doesn’t support thumbnails).
try
{
await encoder.FlushAsync();
}
catch (Exception err)
{
// There was an error encoding.
}
}
}
Note When you call the FlushAsync function the encoder saves and you must recreate the encoder to do anything more. If you plan to use the encoder later, don't call FlushAsync until you are finished with the encoder.