How to encode a new image (HTML)
[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
- Building your first Windows Windows Runtime app using JavaScript
- Windows.Storage.Pickers
- Windows.Graphics.Imaging
Prerequisites
- We assume that you can create a basic Windows Runtime app using JavaScript. For more info, see Building your first Windows Windows Runtime app using JavaScript.
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.
// variables to store objects across multiple async operations
var encoder;
var fileType;
var stream;
var picker = new Windows.Storage.Pickers.FileSavePicker();
picker.fileTypeChoices.insert("JPEG file", [".jpg"]);
picker.defaultFileExtension = "jpg";
picker.suggestedFileName = "untitled";
picker.pickSaveFileAsync().then(function (file) {
if (!file) {
// The user did not select a file.
return;
}
fileType = file. fileType;
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.
return file.openAsync(Windows.Storage.FileAccessMode.readWrite);
}).then(function (_stream) {
stream = _stream;
stream.size = 0;
var encoderId;
switch (fileType) {
case ".jpg":
encoderId = Windows.Graphics.Imaging.BitmapEncoder.jpegEncoderId;
break;
}
return Windows.Graphics.Imaging.BitmapEncoder.createAsync(encoderId, stream);
}).then(function (encoder) {
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.
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.
// An array representing 2x2 red, opaque pixel data
var pixels = [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).
return encoder.flushAsync();
}).then(function () {
// This means the encoder saved successfully.
}, function (error) {
// There was an error encoding, error.message has the error string.
}).done(null, function () {
// Close the stream regardless of whether encoding was successful. Otherwise it will continue to be locked for Read/Write access.
stream && stream.close();
});
}
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.