以下是我在大量搜索和试错编码后提出的解决方案:
这里的目标是找出如何在WinRT中操作图像,特别是在
后台任务中。 后台任务甚至比普通的WinRT项目更受限制,因为它们必须是
Windows Runtime Component类型。 NuGet上99%针对WinRT的可用库仅针对默认的WinRT项目,因此它们不能用于Windows Runtime Component项目。
起初我尝试使用
众所周知的WriteableBitmapEx库 - 将必要的代码移植到我的winmd项目中。甚至有
WBE项目的分支针对winmd, 但它还没有完成。 我添加了[ReadOnlyArray],[WriteOnlyArray]属性到类型数组的方法参数,并将项目命名空间更改为不以“Windows”开头的名称,才使其编译成功 - 这是winmd项目的限制。
即使我能在后台任务项目中使用此库,但它无法工作,因为如我发现的那样,WriteableBitmap必须在UI线程中实例化,而据我所知,在后台任务中这是不可能的。
与此同时,我还发现了这篇有关WinRT中图像处理的MSDN文章。其中大部分示例都只在JavaScript部分,所以我首先需要将其转换为C#。我还发现了这篇有用的StackOverflow文章,它是关于WinRT中图像处理的。
internal static async Task LoadTileImageInternalAsync(string imagePath)
{
string tileName = imagePath.GetHashedTileName();
StorageFile origFile = await ApplicationData.Current.LocalFolder.GetFileAsync(imagePath);
StorageFile tileFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(tileName, CreationCollisionOption.ReplaceExisting);
using (IRandomAccessStream tileStream = await tileFile.OpenAsync(FileAccessMode.ReadWrite))
{
IRandomAccessStreamWithContentType stream = await origFile.OpenReadAsync();
ImageProperties properties = await origFile.Properties.GetImagePropertiesAsync();
uint width = properties.Width;
uint height = properties.Height;
BitmapDecoder decoder = await GetProperDecoder(stream, imagePath);
if (decoder == null) return;
PixelDataProvider data = await decoder.GetPixelDataAsync();
byte[] bytes = data.DetachPixelData();
BitmapPropertySet propertySet = new BitmapPropertySet();
BitmapTypedValue qualityValue = new BitmapTypedValue(TargetJpegQuality, PropertyType.Single);
propertySet.Add("ImageQuality", qualityValue);
BitmapEncoder be = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, tileStream, propertySet);
be.SetPixelData(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Straight, width, height, 96.0, 96.0, bytes);
if (width > MaxImageWidth || height > MaxImageHeight)
{
BitmapBounds bounds = new BitmapBounds();
if (width > MaxImageWidth)
{
bounds.Width = MaxImageWidth;
bounds.X = (width - MaxImageWidth) / 2;
}
else bounds.Width = width;
if (height > MaxImageHeight)
{
bounds.Height = MaxImageHeight;
bounds.Y = (height - MaxImageHeight) / 2;
}
else bounds.Height = height;
be.BitmapTransform.Bounds = bounds;
}
await be.FlushAsync();
}
}
private static async Task<BitmapDecoder> GetProperDecoder(IRandomAccessStreamWithContentType stream, string imagePath)
{
string ext = Path.GetExtension(imagePath);
switch (ext)
{
case ".jpg":
case ".jpeg":
return await BitmapDecoder.CreateAsync(BitmapDecoder.JpegDecoderId, stream);
case ".png":
return await BitmapDecoder.CreateAsync(BitmapDecoder.PngDecoderId, stream);
case ".gif":
return await BitmapDecoder.CreateAsync(BitmapDecoder.GifDecoderId, stream);
}
return null;
}
在这个示例中,我们打开一个文件,将其解码为字节数组,然后使用不同的大小/格式/质量对其进行编码到新文件中。
结果是完全可用的图像处理,即使在 Windows Runtime 组件类中也是如此,而且无需使用 WriteableBitmapEx 库。