[ 本文适用于编写 Windows 运行时应用的 Windows 8.x 和 Windows Phone 8.x 开发人员。如果你要针对 Windows 10 进行开发,请参阅 最新文档 ]
本主题向你展示如何使用 BitmapEncoder 编辑现有图像。你可以使用 BitmapEncoder 在保留所有未编辑的数据同时应用转换(例如缩放和裁剪),设置元数据和属性以及编辑像素。我们向你展示如何使用原始图像数据初始化 BitmapEncoder,向其应用一个或多个编辑操作,然后将其保存以便它更新原始文件。
你还可以使用 BitmapEncoder 从头开始创建新图像,我们将在如何对新图像进行编码中对此过程做出介绍。
你需要了解的内容
技术
先决条件
- 我们假设你能够创建使用 JavaScript 的基本 Windows 运行时应用。有关详细信息,请参阅构建你的第一个使用 JavaScript 的 Windows 运行时应用。
- 你已具有一个 BitmapDecoder 对象。如何解码图像指导你完成此过程。
说明
步骤 1: 从原始图像中获取解码器对象
写入接收 BitmapEncoder 对象的函数的开头,该对象从要编辑的图像文件初始化,和从该文件打开的 IRandomAccessStream。此示例覆盖原始图像,因此必须使用通过 ReadWrite 权限打开的数据流。
function (decoder, fileStream) {
注意 有关如何获取解码器和流对象的说明,请参阅如何解码图像。
在调用 OpenAsync 时,确保将 FileAccessMode 参数更改为 ReadWrite。
步骤 2: 初始化编码器对象以供编辑
将 InMemoryRandomAccessStream 作为编码目标进行创建并使用 CreateForTranscodingAsync 方法创建转码 BitmapEncoder。
将 InMemoryRandomAccessStream 用作临时位置以存储编码的文件。否则,解码器和编码器将同时读取和写入同一流,这是行不通的。
// Keep variables in-scope across multiple async
var memStream = new Windows.Storage.Streams.InMemoryRandomAccessStream();
var encoder;
Windows.Graphics.Imaging.BitmapEncoder
.createForTranscodingAsync(memStream, decoder).then(function (_encoder) {
encoder = _encoder;
注意 CreateForTranscodingAsync 仅支持采用与原始文件相同的格式将数据复制到图像。不允许将图像格式从一种格式转变为另一种格式。
现在,你已经具有使用来自源 BitmapDecoder 的数据初始化的 BitmapEncoder 了。
步骤 3: 转换图像
由于你已经拥有编码器,因此可以执行包括设置元数据和像素数据在内的各种操作。此示例使用 BitmapTransform 方法缩放和旋转图像。有关设置元数据的详细信息,请参阅如何写入图像元数据。有关设置像素数据的详细信息,请参阅如何对新图像进行编码。
// Scaling occurs before flip/rotation.
encoder.bitmapTransform.scaledWidth = 640;
encoder.bitmapTransform.scaledHeight = 480;
// Fant is a relatively high quality interpolation algorithm.
encoder.bitmapTransform.interpolationMode =
Windows.Graphics.Imaging.BitmapInterpolationMode.fant;
// Generate a new thumbnail from the updated pixel data.
// Note: Only JPEG, TIFF and JPEG-XR images support encoding thumbnails.
encoder.isThumbnailGenerated = true;
encoder.bitmapTransform.rotation =
Windows.Graphics.Imaging.BitmapRotation.clockwise90Degrees;
注意 如果使用 CreateForTranscodingAsync 创建 BitmapEncoder,则编码器将尝试以无损方式复制所有原始数据。例如,如果转码 JPEG 并编辑某些图像属性,但不应用任何转换或编辑像素数据,则图像将会被无损地复制。但是,如果你通过从解码器获取像素数据然后在编码器上设置这些数据来执行图像处理,则这一定是一种有损过程,因为像素数据必须重新编码。
步骤 4: 刷新编码器并处理错误
在结束使用编码器后,刷新该编码器以完成编码操作。你还需要处理图像格式不支持编码缩略图的情况。如果你知道你始终编辑支持缩略图的图像格式,例如 JPEG,则可以跳过此错误处理。
return encoder.flushAsync();
}).then(null, function (error) {
switch (error.number) {
// If the encoder doesn't support writing a thumbnail, then try again
// but disable thumbnail generation.
case -2003292287: // WINCODEC_ERR_UNSUPPORTEDOPERATION
encoder.isThumbnailGenerated = false;
return encoder.flushAsync();
default:
throw error;
}
步骤 5: 将编码图像保存到文件中并清除
最后,从内存内流中将内容复制到原始文件的流中,并关闭所有流。
}).then(function () {
// Overwrite the contents of the file with the updated image stream.
memStream.seek(0);
fileStream.seek(0);
fileStream.size = 0;
return Windows.Storage.Streams.RandomAccessStream.copyAsync(memStream, fileStream);
}).done(function () {
memStream.close();
fileStream.close();
});