【问题标题】:Serializing a WPF Image序列化 WPF 图像
【发布时间】:2010-02-05 07:49:25
【问题描述】:

我试图了解图像序列化在 WPF 中的工作原理。我有以下课程:

[Serializable]
public class TestClass : ISerializable
{
    public TestClass() { }


    protected TestClass(SerializationInfo info, StreamingContext context)
    {
        SerializedImage = (byte[])info.GetValue("SerializedImage", typeof(byte[]));
    }


    public byte[] SerializedImage { get; set; }


    public Image Image { get; set; }


    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("SerializedImage", SerializedImage);
    }


    [OnSerializing]
    private void OnSerializing(StreamingContext sc)
    {
        BitmapImage image = Image.Source as BitmapImage;

        MemoryStream stream = new MemoryStream();
        BmpBitmapEncoder encoder = new BmpBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(image));
        encoder.Save(stream);

        SerializedImage = stream.ToArray();

        stream.Close(); ;
    }


    [OnDeserialized]
    private void OnDeserialized(StreamingContext sc)
    {
        MemoryStream stream = new MemoryStream(SerializedImage);
        Image = new Image
        {
            Source = BitmapFrame.Create(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad)
        };

        stream.Close();
    }
}

这是 Xaml 代码:

<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="358" Width="300" ResizeMode="NoResize">
<StackPanel>

    <Image x:Name="Screenshot" Height="178" />
    <Button Width="80" Height="30" Content="Load Image" Click="Button_Click_1" />
    <Button Width="92" Height="30" Content="Save to file" Click="Button_Click_2" />
    <Button Width="92" Height="30" Content="Load File" Click="Button_Click_3" />
    <Button Width="92" Height="30" Content="Load File (1)" Click="Button_Click_4" />

</StackPanel>

这是背后的代码:

public partial class Window1 : Window
{
    TestClass test;


    public Window1()
    {
        InitializeComponent();

        test = new TestClass();
    }


    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        OpenFileDialog dialog = new OpenFileDialog { Filter = "Bmp Image | *.bmp" };
        dialog.ShowDialog();

        if (dialog.FileName != string.Empty)
        {
            Screenshot.Source = new BitmapImage(new Uri(dialog.FileName));
            test.Image = Screenshot;
        }
    }


    private void Button_Click_2(object sender, RoutedEventArgs e)
    {
        SaveFileDialog dialog = new SaveFileDialog { DefaultExt = ".t", AddExtension = true };
        dialog.ShowDialog();

        if (dialog.FileName != string.Empty)
        {
            BinaryFormatter formatter = new BinaryFormatter();
            FileStream stream = new FileStream(dialog.FileName, FileMode.Create);
            formatter.Serialize(stream, test);
            stream.Close();
        }
    }


    private void Button_Click_3(object sender, RoutedEventArgs e)
    {
        OpenFileDialog dialog = new OpenFileDialog { Filter = "TEST file | *.t" };
        dialog.ShowDialog();

        if (dialog.FileName != string.Empty)
        {
            BinaryFormatter formatter = new BinaryFormatter();
            FileStream stream = new FileStream(dialog.FileName, FileMode.Open);
            test = formatter.Deserialize(stream) as TestClass;
            stream.Close();

            Screenshot = test.Image;
        }
    }


    private void Button_Click_4(object sender, RoutedEventArgs e)
    {
        OpenFileDialog dialog = new OpenFileDialog { Filter = "TEST file | *.t" };
        dialog.ShowDialog();

        if (dialog.FileName != string.Empty)
        {
            BinaryFormatter formatter = new BinaryFormatter();
            FileStream stream = new FileStream(dialog.FileName, FileMode.Open);
            test = formatter.Deserialize(stream) as TestClass;
            stream.Close();

            Screenshot.Source = null;

            MemoryStream stream1 = new MemoryStream(test.SerializedImage);
            Screenshot.Source = BitmapFrame.Create(stream1, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
        }
    }
}

现在由于某种我不知道的原因,TestClass 中图像的反序列化效果不佳。如果我自己抓取字节数组并将其转换回图像(Button_Click_4),它会起作用并且图像会显示在我的表单上。相反,如果我直接从 TestClass 中的 Image 属性中获取图像,则表单上不会显示任何内容。我不知道这怎么可能,因为这两种情况涉及的代码是相同的,除非幕后发生了其他事情。

我做错了什么?我已经提供了完整的代码,你可以粘贴并运行它来查看问题。

【问题讨论】:

    标签: wpf image serialization encoding stream


    【解决方案1】:

    视觉树中的图像对象由一个名为“屏幕截图”的字段引用。将 this.Screenshot 分配给新图像根本不会改变您的视觉树。它只是分配字段屏幕截图。在设置源的情况下,您正在更新视觉树中的图像。

    理想情况下,您的测试类应该公开 ImageSource 属性,而不是 Image。单个 Image 实例只能在可视化树中出现一次。因此,通过公开 ImageSource 属性,您可以在 Image 的多个实例中重用该属性(可以在您的可视化树中的不同位置使用)。

    【讨论】:

    • 谢谢,我现在意识到问题是我重新分配了 Image 控件,而不是控件的图像。
    猜你喜欢
    • 2011-04-13
    • 1970-01-01
    • 2016-06-10
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多