【问题标题】:Serializing Bitmap using Json使用 Json 序列化位图
【发布时间】:2019-11-19 05:52:44
【问题描述】:

我正处于团队查看器主题项目的初期。

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

我已尝试这样做,但似乎 Bitmap 变量不能序列化。在序列化之后,json 字符串 var 包含字符串“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);

【问题讨论】:

  • 为什么要将图像作为 JSON 发送?如果您使用的是 HTTP,则可以作为字节数组发送。
  • 您不会将图像序列化为 JSON。 JSON 用于序列化对象而不是字节,因此名称为 Javascript Object Notation。对于图像或任何文件,您只需发送字节流。
  • 别忘了在处理完 Image image 后将其处理掉,最好将其括在 using 语句中。
  • 看看How do I Serialize object to json using json.net which contains an image property。但是性能可能很差,因为 Json.NET 会将Base64 图像流完全具体化为string,然后是字节数组;见Json.Net deserialize out of memory issue

标签: c# json sockets serialization bitmap


【解决方案1】:
  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);

    }

使用这个类作为 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();
        }
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-15
    • 1970-01-01
    • 2013-09-20
    • 2012-09-05
    • 2021-06-28
    • 2022-01-01
    • 1970-01-01
    相关资源
    最近更新 更多