如何在 wpf mvvm 项目中将图像加载和保存为字节数组

How to load and save image as byte array in a wpf mvvm project

我在视图中有一个图像,它绑定到视图模型中的一个字节数组。

 <Image 
        Source="{Binding InputImage, Converter={StaticResource imageConvertor}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
        Panel.ZIndex="1"
        x:Name="UploadImage"
        Grid.Column="0"
        Grid.Row="0"
        Stretch="Uniform"
        Margin="5"
        />


private byte[] inputImage;

public byte[] InputImage
{
    get { return inputImage; }
    set 
    { 
        inputImage = value; 
        OnPropertyChanged(nameof(InputImage));
    }
}

用户通过执行此命令的按钮加载图像

OpenFileDialog op = new OpenFileDialog();
op.Title = "Select a picture";
op.Filter = "All supported graphics|*.jpg;*.jpeg;*.png|" +
   "JPEG (*.jpg;*.jpeg)|*.jpg;*.jpeg|" +
   "Portable Network Graphic (*.png)|*.png";

if (op.ShowDialog() == true) { UploadImage.Source = new BitmapImage(new Uri(op.FileName)); }

问题是,当我尝试加载图像时,转换器接收 null 作为参数。如果我从 xaml 文件中的绑定中删除转换器,它会成功加载到视图,但不能绑定到视图模型中的 属性。

这是转换器的实现

public class ByteArrayToBitmapImageConverter : IValueConverter
{
    public object Convert(object? value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null)
        {
            return null;
        }
        else
            return ToImage(value as byte[]);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null)
        {
            return null;
        }
        else
            return ToBinary(value as Image);
    }

    public static Image ToImage(Byte[] binary)
    {
        Image image = null;
        if (binary == null || binary.Length < 100) return image;

        using (MemoryStream ms = new MemoryStream(binary))
        {
            image = Image.FromStream(ms);
        }
        return image;
    }

  public static Byte[] ToBinary(Image image)
    {
        if (image == null) return null;
        using (MemoryStream memoryStream = new MemoryStream())
        {
            image.Save(memoryStream, ImageFormat.Png);
            return memoryStream.ToArray();
        }
    }
}

是什么导致了空输入?

您正在使用 WinForms Image class 而不是 WPF BitmapSource。 BitmapSource 是 ImageSource 的子class,它是 Image 元素的 Source 属性.

的类型

您的转换器应如下所示:

public class ByteArrayToBitmapSourceConverter : IValueConverter
{
    public object Convert(
        object value, Type targetType, object parameter, CultureInfo culture)
    {
        return ToBitmapSource(value as byte[]);
    }

    public object ConvertBack(
        object value, Type targetType, object parameter, CultureInfo culture)
    {
        return ToByteArray(value as BitmapSource);
    }

    public static BitmapSource ToBitmapSource(byte[] buffer)
    {
        BitmapSource bitmap = null;

        if (buffer != null)
        {
            using (var stream = new MemoryStream(buffer))
            {
                bitmap = BitmapFrame.Create(
                    stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
            }
        }

        return bitmap;
    }

    public static byte[] ToByteArray(BitmapSource bitmap)
    {
        byte[] buffer = null;

        if (bitmap != null)
        {
            var encoder = new PngBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(bitmap));

            using (var stream = new MemoryStream())
            {
                encoder.Save(stream);
                buffer = stream.ToArray();
            }
        }

        return buffer;
    }
}

然而,直接将图像文件中的帧缓冲区分配给视图模型属性会很多更简单

viewModel.InputImage = File.ReadAllBytes(op.FileName);

您根本不需要您的转换器,因为由于 built-in 类型转换,Image.Source 属性 可以直接绑定到 string 类型的源属性, Uribyte[](除了 ImageSource)。

所以你可以简单地写

<Image Source="{Binding InputImage}" ... />