【问题标题】:Sequential PrintScreens Comparison, Generate a difference image?顺序打印屏幕比较,生成差异图像?
【发布时间】:2015-03-03 01:17:53
【问题描述】:

我正在开发一个定期保存打印屏幕的应用程序,比如 10 秒。

一般来说,图像非常相似,有时是相等的,所以我想创建一个位图来表示当前打印屏幕和前一个打印屏幕之间的差异。

为了实现这一点,我逐像素比较了 2 个图像,当它们相等时,我将像素设置为透明颜色(在原始代码中,我使用 Bitmap.LockBits 以获得更好的性能) :

for (var x = 0; x < width; y++)
for (var y = 0; y < height; y++)
{
   var oldColor = lastPrint.GetPixel(x, y);
   var color = currentPrint.GetPixel(x, y);

   if (oldColor == color)
   {
        differencePrint.SetPixel(x, y, Color.Transparent);
   }
}

为了恢复图像,我得到第一个打印屏幕并替换为顺序位图。

private void MergePrints()
    {
        var lastBitmap = new BitMap(firstPrint);
        foreach (var print in prints.OrderBy(e => e.Date))
        {
            using (var difference = new Bitmap(print.Image))
            {
                 using (var grfx = Graphics.FromImage(lastBitmap))
                 {
                     grfx.DrawImage(difference, 0, 0);
                 }                 
            }

            lastBitmap.Save(print.id + ".png");
        }
        lastBitmap.Dispose();
    }

我的问题是:除了具有透明像素的新图像之外,是否有更好的方法来生成表示两个图像之间差异的对象?也许是一个新的班级?但是这个类需要持久化,当然比位图“更小”,目前我在使用 7zip 算法压缩它后将位图持久化为 byte[]。

【问题讨论】:

  • 您是否只是要求一个能够容纳您的差异的数据访问对象?在这种情况下,它只是System.Drawing.Point 的列表,即您只需要存储公共区域的 x,y,这似乎就是您所需要的 - 您已经具备根据该信息创建新图像的功能。
  • 是的,但是我需要一个不常见像素的列表,而不是一个常见像素的列表,它就像一个代表差异的 Dictionary。但是,如果我采用这种方法,我还需要保留字典,将它保留在这本字典中的最佳方法是什么?每行代表一个像素的子表?
  • 目前您仍在使用位图,它是像素颜色数组。如果变化不大(意味着会有很多透明像素),那么只存储坐标列表(x,y)和相应的新颜色会更有效。类似于List&lt;Tuple&lt;int, int, Color&gt;&gt;。绘制旧位图,然后从此类列表中更新点将为您提供新位图。其他选择是使用专门的容器来处理这些事情:GIF 应该这样做,如果您接受图像丢失,那么 MPEG 等。他们使用相同的关键帧和更改的想法。
  • @Sinatr 对不起,我的无知,您认为将这些元组存储在数据库中的每个像素的行中比将透明位图数组(大小)存储在单行中更好吗?那是因为位图数组是可以使用的位图。是的,图像丢失是可以接受的
  • 颜色为 4 字节。坐标是,2-4 (byte - uint)。如果您有50% 的透明像素,则新方法会更好(25% 保存,如果byte)或相同(0 保存)。更重要的是——绝对是一场胜利。可以说,使用透明像素对位图进行简单压缩可能会消除更多。但是您可以进一步优化提供的方式,例如,不要保存所有点的坐标,而是保存路径(第一个点仍然是xy,但下一个点是偏移量的byte,如果下一个点不可达,开始一条新路径)...

标签: c# image performance bitmap system.drawing


【解决方案1】:

您可以使用code in this answer 这样做

它使用LockBits 并且非常快。它假定格式为原生ARGB 像素格式。

以两个Bitmaps为参数,返回差值Bitmap

第三个参数可以让你从差异中恢复原始(如果你无损存储,推荐Png);这是为了只允许更快地传输差异图像而编写的,因为只有很小的差异它允许更好的压缩比。

这听起来和你的情况很相似,对吧?

直接回答这个问题:我找不到比 Png 的开发者更好的压缩或更方便的格式。作为额外的奖励,你总是可以查看差异进行测试并立即查看更改的数量和分布..

【讨论】:

  • 嗨,是的,它非常相似,但正如我所说,我也使用 LockBits 来获取设置像素,是的,它非常快。我尝试使用@Sinatr 建议将坐标和颜色保存到压缩数组中,但 PNG 仍然是最好的。所以我会标记你的答案来结束这个话题,谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-05-15
  • 2019-08-03
  • 2011-05-24
  • 2011-02-02
  • 2019-06-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多