我正在开发一个Windows 8 Metro应用程序,该应用程序将过滤器应用于图像。我有一个网页版本的应用程序,并想移植它。但是我们都知道WinRT并没有。net提供的所有好东西:/
目前我在一个字节数组上应用过滤器,我想保持这种方式,因为它超级快!因此,在过去的几天里,我一直在寻找将StorageFile转换为byte[],然后将byte[]转换为BitmapImage的方法。
到目前为止,我已经设法做了第一个(StorageFile到byte[])。我是这样做的:
public async Task<Byte[]> ImageFileToByteArray(StorageFile file)
{
IRandomAccessStream stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
PixelDataProvider pixelData = await decoder.GetPixelDataAsync();
return pixelData.DetachPixelData();
}
这段代码返回一个包含像素数据作为BGRA的byte[]
。
棘手的部分来了。我无法成功地将字节数组转换为BitmapImage。我已经搜索了所有的地方,很多人建议使用WriteableBitmap,但这对我没有多大好处。我还发现了一些应该可以工作的代码……但他们没有。
我尝试过的解决方案之一是使用InMemoryRandomAccessStream这样:
public async Task<BitmapImage> ByteArrayToBitmapImage(Byte[] pixels)
{
var stream = new InMemoryRandomAccessStream();
await stream.WriteAsync(pixels.AsBuffer());
stream.Seek(0);
var image = new BitmapImage();
await image.SetSourceAsync(stream);
return image;
}
这个会抛出以下异常:
类型为'System '的异常。在mscorlib.dll中发生异常,但未在用户代码中处理
附加信息:无法找到组件。(Exception from HRESULT: 0x88982F50)
我试着用这行代替:
PixelDataProvider pixelData = await decoder.GetPixelDataAsync(
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Ignore,
new BitmapTransform(),
ExifOrientationMode.IgnoreExifOrientation,
ColorManagementMode.DoNotColorManage);
但是这对我没有任何好处,因为我总是得到那个异常。
我也试过这个:
var bitmapImage = new BitmapImage();
var pixels = await ImageFileToByteArray(file);
ImageSource imgSource;
using (InMemoryRandomAccessStream ms = new InMemoryRandomAccessStream())
{
using (DataWriter writer = new DataWriter(ms.GetOutputStreamAt(0)))
{
writer.WriteBytes(pixels);
await writer.StoreAsync();
}
await bitmapImage.SetSourceAsync(ms);
imgSource = bitmapImage;
}
并得到与第一段代码相同的异常。
我还尝试了其他几种方法,包括使用正常的流,然后转换为IRandomAccessStream,但它们也不起作用。
以上所有代码对我来说似乎都很好。所以我现在的猜测是问题出在byte[]
里。我猜pixelData里面的格式是无效的,所以我试着把它改成RGBA,但这也没有帮助。此外,BitmapImage的PixelHeight和PixelWidth为0。
这是为我工作,
private async Task<BitmapImage> ByteArrayToBitmapImage(byte[] byteArray)
{
var bitmapImage = new BitmapImage();
var stream = new InMemoryRandomAccessStream();
await stream.WriteAsync(byteArray.AsBuffer());
stream.Seek(0);
bitmapImage.SetSource(stream);
return bitmapImage;
}
这是我的第一个答案,希望对大家有所帮助。
我有完全相同的问题,我花了6个多小时试图解决这个问题。这是我的想法:你说得对。有两种方法将图像转换为byteArray:
第一方式(你的)
public async Task<byte[]> ImageFileToByteArrayAsync(StorageFile file)
{
IRandomAccessStream stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
PixelDataProvider pixelData = await decoder.GetPixelDataAsync();
return pixelData.DetachPixelData();
}
第二次进场
public async Task<byte[]> ImageFileToByteArrayAsync(StorageFile file)
{
var inputStream = await file.OpenSequentialReadAsync();
var readStream = inputStream.AsStreamForRead();
var buffer = new byte[readStream.Length];
await readStream.ReadAsync(buffer, 0, buffer.Length);
return buffer;
}
如果你使用第二种方法来解码pic,没有像素,这个转换器将工作:
public class ByteArrayToImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value == null || !(value is byte[]))
return null;
using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())
{
using (DataWriter writer = new DataWriter(stream.GetOutputStreamAt(0)))
{
writer.WriteBytes((byte[])value);
writer.StoreAsync().GetResults();
}
BitmapImage image = new BitmapImage();
image.SetSource(stream);
return image;
}
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
对于第一种方法,你需要像你说的那样使用WriteableBitmap