带有图像的数据合同 serialization/serialization

Datacontract serialization/serialization with images

我有一个 class 的图像,根据图像是否嵌入的事实,必须(有时)serialized/deserialized。

[DataContract(IsReference = true)]
public class Data
{
  [DataContract(IsReference = true)]
  public class MyImage
  {

  [DataMember]
  int WidthStorage
  [DataMember]
  int HeightStorage;

  [DataMember]
  public string strImageLocation;
  [DataMember]
  public Image ImageEmbedded = new Image();<----- not working null
  public bool GetImage(Image image, int width, int height)
  {
    ...
  }

  public void SetImageFSlocation(string _strImageLocation, int _widthStorage, int _heightStorage)
  {
    ...        
  }

  public void SetImageEmbedded(string strPathFilename, int _widthStorage, int _heightStorage)
  {
    ...
  }

}

所以问题是尽管把

public Image ImageEmbedded = new Image();

ImageEmbedded 始终为空。 所以我把它放在像

这样的构造函数中
[DataContract(IsReference = true)]
  public class MyImage
  {
    public MyImage()
    {
      ImageEmbedded = new Image();
    }
    ...

但是当我这样做时,出现序列化错误。 那我该怎么办? 我不会将 Image 转换为 byte[] 或其他。我选择了 Datacontract 序列化,因为我认为它可以序列化图像。 谢谢

如果你的序列化器不直接知道如何转换一个字段的类型,那你就是在逆风而行。更简单的解决方案是恢复到大多数语言中的更原始类型;创建一个 Data-Transfer Object. For example, I store quite a diverse amount of 1- 2-dimensional data with protobuf.net 使用类似的东西(根据您的需要编辑):

[DataContract]
class ImageDTO
{
    [DataMember(Order = 1)]
    public int Width { get; set; }

    [DataMember(Order = 2)]
    public int Height { get; set; }

    [DataMember(Order = 3)]
    public ImageFormat Format { get; set; }

    [DataMember(Order = 4)]
    public byte[] Data { get; set; }

    [DataMember(Order = 5)]
    public string AltUrl { get; set; }
}

因此,在您的情况下,您只需要处理图像格式枚举代码并从图像中获取二进制数据。参见 Fastest way to convert Image to Byte array OR WPF Image to byte[] OR https://github.com/teichgraf/WriteableBitmapEx/

然后你可以简单地将这个 ImageDTO 的任何实例扔给几乎大多数基于合约的序列化器/反序列化器。例如,如果您选择协议缓冲区,在 .net 领域,您可以使用 protobuf.net, while in javascript land you can deserialise with protobuf.js 序列化给定 .proto

message ImageDTO {
   optional int32 Width = 1 [default = 0];
   optional int32 Height = 2 [default = 0];
   optional ImageFormat Format = 3 [default = RGB];
   optional bytes Data = 4;
   optional string AltUrl = 5;
}
enum ImageFormat {
   RGB = 0;
   RGBA = 1;
   PNG = 2;
   JPEG = 3;
}

您的代码中存在一个主要问题:在 WPF 中,如果您序列化一个图像,您就会序列化 System.Windows.Controls.Image。所以简而言之,序列化一个控件是没有意义的。相反,您可能想序列化一个 BitmapSource,但这里又不能序列化它们,因此您必须将它们变成 byte[],如前所述。

[DataMember]
public byte[] bytesBitmapEmbedded;

然后通过这个简单的改成BitmapSource或者byte[]:

bytesBitmapEmbedded = Converter.BitmapSource2ByteArray(bitmapSource);

bitmapSource = Converter.ByteArray2BitmapSource(bytesBitmapEmbedded);

public static class Converter
{
    public static byte[] BitmapSource2ByteArray(BitmapSource bitmap)
    {
        using (var stream = new MemoryStream())
        {
            var encoder = new PngBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(bitmap));
            encoder.Save(stream);
            return stream.ToArray();
        }
    }

    public static BitmapSource ByteArray2BitmapSource(byte[] buffer)
    {
        using (var stream = new MemoryStream(buffer))
        {
            return BitmapFrame.Create(stream,
                BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
        }
    }
}