byte []到BitmapImage转换失败

时间:2013-01-13 01:33:15

标签: c# wpf image bitmapimage

我有问题。我想将BitmapImage转换为byte[]数组并返回。

我写了这些方法:

public static byte[] ToByteArray(this BitmapImage bitmapImage)
{
    byte[] bytes;
    using (MemoryStream ms = new MemoryStream())
    {
        bitmapImage.BeginInit();
        bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
        bitmapImage.StreamSource.CopyTo(ms);
        bitmapImage.EndInit();
        bytes = ms.ToArray();
    }
    return bytes;
}

public static BitmapImage ToBitmapImage(this byte[] bytes, int width, int height)
{
    BitmapImage bitmapImage = new BitmapImage();
    using (MemoryStream ms = new MemoryStream(bytes))
    {
        ms.Position = 0;
        bitmapImage.BeginInit();
        bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
        bitmapImage.StreamSource = ms;
        bitmapImage.EndInit(); // HERE'S AN EXCEPTION!!!
    }
    return bitmapImage;
}

第一个工作正常,但当我尝试从byte[]转换为BitmapImage时,我得到了NotSupportedException ...为什么?如何更正第二种方法的代码?

1 个答案:

答案 0 :(得分:5)

ToByteArray方法存在两个问题。

首先,它在已初始化的BitmapImage实例上调用BeginInitEndInit。这是不允许的,请参阅BeginInit中的例外列表。

其次,无法在从Uri而不是Stream创建的BitmapImage上调用该方法。然后StreamSource属性为null

我建议实现如下所示的方法。此实现适用于任何BitmapSource,而不仅适用于BitmapImages。并且您可以通过选择适当的BitmapEncoder来控制图像格式,例如JpegBitmapEncoder代替PngBitmapEncoder

public static byte[] ToByteArray(this BitmapSource bitmap)
{
    var encoder = new PngBitmapEncoder(); // or any other encoder
    encoder.Frames.Add(BitmapFrame.Create(bitmap));

    using (var ms = new MemoryStream())
    {
        encoder.Save(ms);
        return ms.ToArray();
    }
}

ToByteArray方法返回的图像缓冲区始终可以通过ToBitmapImage方法转换回BitmapImage。

请注意,ToBitmapImage方法的宽度和高度参数目前尚未使用。


更新

解码方法的替代实现可能如下所示,尽管它不返回BitmapImage但只返回基类BitmapSource的实例。但是,您可以将返回类型更改为BitmapFrame

public static BitmapSource ToBitmapImage(this byte[] bytes)
{
    using (var stream = new MemoryStream(bytes))
    {
        var decoder = BitmapDecoder.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
        return decoder.Frames[0];
    }
}