15

我正在开发一个将过滤器应用于图像的 Windows 8 Metro 应用程序。我有该应用程序的 Web 版本,并希望将其移植。但众所周知,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();
    }

这段代码返回一个byte[]包含像素数据的 BGRA。

棘手的部分来了。我无法成功地将字节数组转换为 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;
    }

这会引发以下异常:

mscorlib.dll 中出现“System.Exception”类型的异常,但未在用户代码中处理

附加信息:找不到该组件。(来自 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;
        }

并得到与第一段代码相同的异常。

我还尝试了其他几种方法,包括使用普通 Stream 然后转换为 IRandomAccessStream 但它们也不起作用。

以上所有代码对我来说似乎都很好。所以我目前的猜测是问题出在byte[]. 我猜里面的 pixelData 格式无效,所以我尝试将其更改为 RGBA,但这也无济于事。BitmapImage 的 PixelHeight 和 PixelWidth 也是 0。

4

2 回答 2

13

这对我有用,

    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;
    }
于 2013-08-09T15:33:23.223 回答
1

这是我的第一个答案..希望它会有所帮助。

我遇到了完全相同的问题,我花了超过 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;
    }

如果你使用第二种方法来解码图片,没有像素,这个转换器将工作:

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。

于 2014-11-28T21:34:46.190 回答