【问题标题】:the difference between two images is larger than the images?两个图像之间的差异大于图像?
【发布时间】:2010-11-11 21:36:46
【问题描述】:

我正在创建 TCP 远程桌面应用程序 我只想发送先前发送的帧的差异。

当我比较原始图像和第二张图像时,我将已更改的像素信息放入 ArrayList ArrayList 中的五个 Item 包含一个像素的信息 第一项包含一个高度点 第二个项目包含一个宽度点 第三项包含 RGB.red 第四个项目包含 RGB.Green 第五项包含RGB.Blue

这是代码

    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 序列化为 MemoryStream 我发现尺寸比图片大 我也试过把变化的像素信息放到Short Array中,但也发现尺寸比图片大!!!!!?

我如何进行这个过程,以便我可以将缩略图尺寸缩小到可能的最小尺寸?

我用来序列化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; 

    }

【问题讨论】:

  • 原始图像是否为压缩格式?例如 jpg、png 还是 gif?您的数组将与该区域的位图一样大,如果不是更大的话。此外,数组列表(如果我没记错的话)是一个链表类型的集合,因此它可以动态扩展,因此会给每个像素增加一点点开销。
  • 我认为你需要停下来重新思考你是设计者。 每像素包含 5 条信息的 ArrayList?你永远不会让它表现良好。

标签: c#


【解决方案1】:

典型的 32 位 WxH 图像使用 WxHx4 字节的内存(对于 1024x1024 位图来说是 4MB)。

假设您要发送具有 16 位 [x] 和 [y] 以及 32 位 [color] 值的 [x][y][color] 格式的不同像素列表,并且有 D不同的像素,差异会使用 Dx8 字节的内存。因此,如果超过一半的像素不同(D > WxH/2),差异将大于图像。

在您的情况下,您使用的是一个数组,这意味着 [color] 实际上表示为三个 [r][g][b] 16 位值。内存使用量变为 Dx10,如果有 40% 的像素发生变化(D > WxH/2.5),则可以找到阈值。

考虑使用一点来判断您是发送差异列表还是完整图像,然后发送两者中最小的一个。还要考虑诸如 RLE 编码之类的事情,使用单个 [offset] 16 位值而不是 [x] 和 [y],或者只是使任何未更改的值透明并将结果保存为 PNG 格式。

当然,运行时插入的任何其他序列化数据以及可以压缩图像的事实(例如,PNG 是无损的)都会加剧这一点。

【讨论】:

    【解决方案2】:

    当然会更大!

    位图的内存结构由标头、像素数据和调色板组成,而 ArrayList 的二进制格式化程序序列化结果具有完全不同的格式,包括程序集元数据、类型元数据等。

    另外很遗憾,您对像素进行不安全编码的所有性能增益都将浪费在使用 ArrayList 发生的装箱上。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-04
      • 2015-01-18
      • 1970-01-01
      • 2011-08-09
      • 2014-06-13
      相关资源
      最近更新 更多