Safta11
Safta11

Reputation: 23

Serializing Bitmap using Json

I'm in the very beginning of a team-viewer themed project.

Right now I managed to take a screenshot of the current screen as a Bitmap variable and I need to transfer it to a distant through a socket. Such a process obviously requires Serializing the Bitmap variable using json.

I have tried to do so but it seems like the Bitmap variable just isn't serialize-able. As after the serialization the json string var contains the string "system.Drawing.Bitmap". How do I convert it correctly? thanks.

The method that takes the screenshot:

public static Image TakeScreen()
{
    Bitmap bitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);

    Graphics g = Graphics.FromImage(bitmap);

    g.CopyFromScreen(0,0, 0, 0, bitmap.Size);
    Console.WriteLine(bitmap.ToString());

    return bitmap;       
}

The Serialization:

Image image = TakeScreen();

string jsonData = JsonConvert.SerializeObject(image, Formatting.None);
Console.WriteLine(jsonData);

Upvotes: 1

Views: 4221

Answers (1)

  1. json can serialize only primitives
  2. sending a picture in json is very expensive, such data as an image or sound should be transmitted via UDP streaming data

If you still need to transfer the image to JSON, you first need to extract the byte array and convert it to HEX or BASE64

Below I give a simple example example

public void ImageTest()
    {
        // get image
        Image image = TakeScreen();
        // conver image to bytes
        byte[] img_byte_arr = ImageToBytes(image);
        // creat packet
        ImagePacket packet = new ImagePacket(img_byte_arr);

        // conver object to json there...
        // send json ...
        // receive json ...
        // convert json to object type of ImagePacket ...

        // get bytes from ImagePacket
        byte[] receive_bytes = packet.GetRawData();
        // conver bytes to Image
        Image receive_image = BytesToImage(receive_bytes);

    }

Use this class as a container for serialization in JSON

/// <summary>
    /// Packet with image
    /// </summary>
    public class ImagePacket
    {
        public string hash { get; set; } = string.Empty;
        public int len { get; set; } = 0;
        public string image { get; set; } = string.Empty;
        public ImagePacket() { }
        public ImagePacket(byte[] img_sources)
        {
            hash = StringHash(img_sources);
            len = img_sources.Length;
            image = EncodeBytes(img_sources);
        }
        public byte[] GetRawData()
        {
            byte[] data = DecodeBytes(image);

            if(data.Length != len) throw new Exception("Error data len");
            if(!StringHash(data).Equals(hash)) throw new Exception("Error hash");

            return data;
        }
    }

Use the following methods for working with pictures and data transformations.

/// <summary>
    /// Get original image
    /// </summary>
    /// <returns></returns>
    public static Image TakeScreen()
    {
        Bitmap bitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
        Graphics g = Graphics.FromImage(bitmap);
        g.CopyFromScreen(0, 0, 0, 0, bitmap.Size);
        return bitmap;
    }
    /// <summary>
    /// Conver Image to byte array
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    public static byte[] ImageToBytes(Image value)
    {
        ImageConverter converter = new ImageConverter();
        byte[] arr = (byte[])converter.ConvertTo(value, typeof(byte[]));
        return arr;
    }
    /// <summary>
    /// Conver byte array to Image
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    public static Image BytesToImage(byte[] value)
    {
        using(var ms = new MemoryStream(value))
        {
            return Image.FromStream(ms);
        }
    }
    /// <summary>
    /// Convert bytes to base64
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    public static string EncodeBytes(byte[] value) => Convert.ToBase64String(value);
    /// <summary>
    /// convert base64 to bytes
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    public static byte[] DecodeBytes(string value) => Convert.FromBase64String(value);
    /// <summary>
    /// get MD5 hash from byte array
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    public static string StringHash(byte[] value)
    {
        using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
        {
            byte[] hashBytes = md5.ComputeHash(value);
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < hashBytes.Length; i++)
            {
                sb.Append(hashBytes[i].ToString("X2"));
            }
            return sb.ToString().ToLower();
        }
    }

Upvotes: 3

Related Questions