带有图像的数据合同 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);
}
}
}
我有一个 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);
}
}
}