C# 两幅图像之间的差异比两幅图像之间的差异大?
我正在创建TCP远程桌面应用程序 我只想发送之前发送的帧的差异 当我比较原始图像和第二幅图像时,我将已更改的像素信息放入ArrayList ArrayList中的五项包含一个像素的信息 第一项包含一个高度点 第二项包含一个宽度点 第三项包含RGB.red 第四项包含RGB.Green 第五项包含RGB.Blue 这是密码C# 两幅图像之间的差异比两幅图像之间的差异大?,c#,C#,我正在创建TCP远程桌面应用程序 我只想发送之前发送的帧的差异 当我比较原始图像和第二幅图像时,我将已更改的像素信息放入ArrayList ArrayList中的五项包含一个像素的信息 第一项包含一个高度点 第二项包含一个宽度点 第三项包含RGB.red 第四项包含RGB.Green 第五项包含RGB.Blue 这是密码 private void button1_Click(object sender, EventArgs e) { ArrayList new_p
private void button1_Click(object sender, EventArgs e)
{
ArrayList new_pixel = Unsafe_diff_array(pictureBox2.Image, pictureBox1.Image);
Bitmap new_bit_map = (Bitmap)pictureBox3.Image;
for (int i = 0; i < new_pixel.Count; i+=5)
{
int x = (int)new_pixel[i +1];
int y=(int)new_pixel[i];
int red= Convert.ToInt16(new_pixel[i + 4]) ;
int green= Convert.ToInt16(new_pixel[i + 3]) ;
int blue=Convert.ToInt16(new_pixel[i + 2]);
new_bit_map.SetPixel(x, y, Color.FromArgb(red , green, blue));
}
pictureBox3.Image = new_bit_map;
}
public ArrayList Unsafe_diff_array(Image OrginalImage, Image SecondImage)
{
Bitmap BOrginalImage = new Bitmap(OrginalImage);
Bitmap BSecondImage = new Bitmap(SecondImage);
BitmapData bitmapData1 = BOrginalImage.LockBits(new Rectangle(0, 0,
OrginalImage.Width, OrginalImage.Height),
ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb);
BitmapData bitmapData2 = BSecondImage.LockBits(new Rectangle(0, 0,
SecondImage.Width, SecondImage.Height),
ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb);
ArrayList siblings = new ArrayList();
unsafe
{
byte* imagePointer1 = (byte*)bitmapData1.Scan0;
byte* imagePointer2 = (byte*)bitmapData2.Scan0;
for (int i = 0; i < bitmapData1.Height; i++)
{
for (int j = 0; j < bitmapData1.Width; j++)
{
// write the logic implementation here
if ((imagePointer1[0] != imagePointer2[0]) || (imagePointer1[1] != imagePointer2[1]) || (imagePointer1[2] != imagePointer2[2]))
{
imagePointer2[0] = imagePointer1[0];
imagePointer2[1] = imagePointer1[1];
imagePointer2[2] = imagePointer1[2];
siblings.Add(i);
siblings.Add(j);
siblings.Add(imagePointer2[0]);
siblings.Add(imagePointer2[1]);
siblings.Add(imagePointer2[2]);
}
imagePointer2[3] = imagePointer1[3];
imagePointer1 += 4;
imagePointer2 += 4;
}//end for j
imagePointer1 += bitmapData1.Stride -
(bitmapData1.Width * 4);
imagePointer2 += bitmapData1.Stride -
(bitmapData1.Width * 4);
}//end for i
}//end unsafe
BOrginalImage.UnlockBits(bitmapData1);
BSecondImage.UnlockBits(bitmapData2);
return siblings ;
// return BSecondImage.GetThumbnailImage(SecondImage.Width, SecondImage.Height, null, new IntPtr()); ;
}
当然会更大 位图具有内存中的结构,包括标头、像素数据,有时还包括调色板,而ArrayList的二进制格式化程序序列化结果具有完全不同的格式,包括程序集元数据、类型metatdata等
同样遗憾的是,在像素上进行不安全编码所获得的所有性能收益都将浪费在使用ArrayList时的装箱上。当然会更大 位图具有内存中的结构,包括标头、像素数据,有时还包括调色板,而ArrayList的二进制格式化程序序列化结果具有完全不同的格式,包括程序集元数据、类型metatdata等
另外,遗憾的是,在像素上进行不安全编码所获得的所有性能增益都将浪费在使用ArrayList的装箱上。典型的32位WxH图像使用WxHx4字节的内存(对于1024x1024位图来说是4MB) 假设您以[x][y][color]格式发送具有16位[x]和[y]以及32位[color]值的不同像素列表,并且有D个不同的像素,那么差异将使用Dx8字节的内存。因此,如果超过一半的像素不同(D>WxH/2),则差异将大于图像 在您的例子中,您使用的是一个数组,这意味着[color]实际上表示为三个[r][g][b]16位值。内存使用量变为Dx10,如果40%的像素发生变化,则可以找到阈值(D>WxH/2.5) 考虑使用bit来判断您发送的是差异列表还是完整图像,并发送两者中最小的一个。还考虑诸如RLE编码之类的事情,使用单个[偏移] 16位值而不是[X]和[Y],或者只是使任何不变的值透明,并以PNG格式保存结果。
当然,这是由运行时插入的任何附加序列化数据以及图像可以压缩(例如PNG是无损的)这一事实造成的。典型的32位WxH图像使用WxHx4字节的内存(对于1024x1024位图是4MB) 假设您以[x][y][color]格式发送具有16位[x]和[y]以及32位[color]值的不同像素列表,并且有D个不同的像素,那么差异将使用Dx8字节的内存。因此,如果超过一半的像素不同(D>WxH/2),则差异将大于图像 在您的例子中,您使用的是一个数组,这意味着[color]实际上表示为三个[r][g][b]16位值。内存使用量变为Dx10,如果40%的像素发生变化,则可以找到阈值(D>WxH/2.5) 考虑使用bit来判断您发送的是差异列表还是完整图像,并发送两者中最小的一个。还考虑诸如RLE编码之类的事情,使用单个[偏移] 16位值而不是[X]和[Y],或者只是使任何不变的值透明,并以PNG格式保存结果。
当然,这是由运行时插入的任何附加序列化数据以及图像可以压缩(例如PNG是无损的)这一事实造成的。原始图像是压缩格式吗?例如jpg、png或gif?您的数组将与该区域的位图一样大,如果不是更大的话。另外,数组列表(如果我没记错的话)是一个链表类型的集合,因此它可以动态扩展,因此会给每个像素增加一点开销。我认为你需要停下来重新考虑你的设计。每像素包含5条信息的ArrayList?你永远也无法让它表现得很好。原始图像是压缩格式的吗?例如jpg、png或gif?您的数组将与该区域的位图一样大,如果不是更大的话。另外,数组列表(如果我没记错的话)是一个链表类型的集合,因此它可以动态扩展,因此会给每个像素增加一点开销。我认为你需要停下来重新考虑你的设计。每像素包含5条信息的ArrayList?你永远不会让它表现得很好。
private System.IO.MemoryStream SerializeBinary(object obj){
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter serializer = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
System.IO.MemoryStream memStrm = new System.IO.MemoryStream();
serializer.Serialize(memStrm, obj);
return memStrm;
}