5

I am creating a chat application very basic. I establish the chat with a tcp connection. I often send serialized object through the network stream because it is simplier to program that way. anyways if I have a class person{ public string name{get;set;} } then it will be eassy to serialize that class. when I include a public ImageSource Img {get;set;} I am not able to serialize that class person any more.

the way I serialize is as:

Person p = new Person();
p.name = \\some name
p.Img = \\ some image

System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(p.GetType());

x.Serialize(connection.stream, p);//here is when the problem comes. I am not able to serialize it if I include an Img
Tono Nam
  • 34,064
  • 78
  • 298
  • 470

3 Answers3

9

You can't serialize an image to XML, but you can save it to a MemoryStream and encode the binary data to base64.

string ImageToBase64(BitmapSource bitmap)
{
    var encoder = new PngBitmapEncoder();
    var frame = BitmapFrame.Create(bitmap);
    encoder.Frames.Add(frame);
    using(var stream = new MemoryStream())
    {
        encoder.Save(stream);
        return Convert.ToBase64String(stream.ToArray());
    }
}

BitmapSource Base64ToImage(string base64)
{
    byte[] bytes = Convert.FromBase64String(base64);
    using(var stream = new MemoryStream(bytes))
    {
        return BitmapFrame.Create(stream);
    }
}

Note that base64 is not very efficient in terms of space... If possible, it would be better to transmit the image in binary form, rather than in XML.

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
  • and once I have the image as a string how do I convert it back to an image? – Tono Nam Sep 01 '11 at 01:20
  • 3
    There seems to be a problem with the `Base64ToImage` method - the stream gets disposed before `BitmapFrame` actually accesses it. I've described the fix in [this answer](http://stackoverflow.com/a/13424285/197913). – Damir Arh Nov 16 '12 at 20:59
  • For deserializing, instead of BitmapFrame I ended up using BitmapImage (https://stackoverflow.com/a/1685504/316760). The former returned the first image on subsequent calls (so, same image throughout my UI). I'm sure it was user error on my part. – Vimes May 15 '18 at 21:09
1

your approach is correct but does not work anymore as soon as the class Person contains any non serializable object like in your case the ImageSource.

If I had to solve it staying close to your solution, I would store the byte[] of the image and parse it back after deserialization to reconstruct the ImageSource.

Davide Piras
  • 43,984
  • 10
  • 98
  • 147
1

You can use BinaryFormatter or available encoders like http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.jpegbitmapencoder.aspx from System.Windows.Media.Imaging Namespace. Also see WPF BitmapImage Serialization/Deserialization . If you want to use string (xml) then i think the Base64 is the only way.

Community
  • 1
  • 1
Tomas Voracek
  • 5,886
  • 1
  • 25
  • 41