使用 Json 序列化位图

Serializing Bitmap using Json

我正处于团队查看器主题项目的最开始阶段。

现在我设法将当前屏幕的屏幕截图作为位图变量,我需要通过套接字将其传输到远处。这样的过程显然需要使用 json.

序列化 Bitmap 变量

我已尝试这样做,但似乎 Bitmap 变量无法序列化。在序列化之后,json 字符串变量包含字符串 "system.Drawing.Bitmap"。如何正确转换?谢谢。

截图方法:

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;       
}

序列化:

Image image = TakeScreen();

string jsonData = JsonConvert.SerializeObject(image, Formatting.None);
Console.WriteLine(jsonData);
  1. json 只能序列化原语
  2. 在json中发送图片非常昂贵,图像或声音等数据应通过UDP流数据传输

如果还需要将图片转成JSON,首先需要将字节数组提取出来,转成HEX或BASE64

下面我举个简单的例子

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);

    }

使用此 class 作为在 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;
        }
    }

使用以下方法处理图片和数据转换。

/// <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();
        }
    }