如何从几种不同图像格式的字节数组中获取BitmapImage

m4g*_*gik 1 c# wpf image

我已使用以下方法将图像保存在数据库中,将它们转换为不同图像格式的字节数组:

public byte[] foo()
{
    Image img = Image.FromFile(path);
    var tmpStream = new MemoryStream();
    ImageFormat format = img.RawFormat;
    img.Save(tmpStream, format);
    tmpStream.Seek(0, SeekOrigin.Begin);
    var imgBytes = new byte[MAX_IMG_SIZE];
    tmpStream.Read(imgBytes, 0, MAX_IMG_SIZE);
    return imgBytes;
}
Run Code Online (Sandbox Code Playgroud)

现在我需要读出它们并将它们转换回 BitmapImage 类型,以便我可以将它们显示给用户。我正在考虑使用 Image.FromStream(Stream) 方法,但这似乎没有考虑到不同的 ImageFormats...有人知道该怎么做吗?提前致谢。

Cle*_*ens 6

您不应该在 WPF 应用程序中使用 WinFormsSystem.Drawing命名空间中的类(就像使用Image.FromFile)。

WPF 提供了自己的一组类来从流和 URI 加载和保存位图,并具有自动检测位图帧缓冲区格式的内置支持。

只需直接从 Stream创建一个BitmapImage或一个:BitmapFrame

public static BitmapSource BitmaSourceFromByteArray(byte[] buffer)
{
    var bitmap = new BitmapImage();

    using (var stream = new MemoryStream(buffer))
    {
        bitmap.BeginInit();
        bitmap.CacheOption = BitmapCacheOption.OnLoad;
        bitmap.StreamSource = stream;
        bitmap.EndInit();
    }

    bitmap.Freeze(); // optionally make it cross-thread accessible
    return bitmap;
}
Run Code Online (Sandbox Code Playgroud)

或者

public static BitmapSource BitmaSourceFromByteArray(byte[] buffer)
{
    using (var stream = new MemoryStream(buffer))
    {
        return BitmapFrame.Create(
            stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
    }
}
Run Code Online (Sandbox Code Playgroud)

任一方法都会返回 a BitmapSource,它是 BitmapImage 和 BitmapFrame 的基类,并且应该足以处理应用程序其余部分中的位图。例如,SourceImage 控件的属性使用另一个基类 ,ImageSource作为属性类型。

另请注意,当您从要在加载后关闭的 Stream 加载 BitmapSource 时,您必须设置BitmapCacheOption.OnLoad. 否则,流必须保持打开状态,直到最终显示位图。


要对 BitmapSource 进行编码,您应该使用如下方法:

public static byte[] BitmapSourceToByteArray(BitmapSource bitmap)
{
    var encoder = new PngBitmapEncoder(); // or any other BitmapEncoder

    encoder.Frames.Add(BitmapFrame.Create(bitmap));

    using (var stream = new MemoryStream())
    {
        encoder.Save(stream);
        return stream.ToArray();
    }
}
Run Code Online (Sandbox Code Playgroud)