使用 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);
- json 只能序列化原语
- 在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();
}
}
我正处于团队查看器主题项目的最开始阶段。
现在我设法将当前屏幕的屏幕截图作为位图变量,我需要通过套接字将其传输到远处。这样的过程显然需要使用 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);
- json 只能序列化原语
- 在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();
}
}