diff / patch for images

时间:2011-07-07 16:24:53

标签: java image diff binary-diff

我正在编写一个项目,我需要通过网络传输一组类似的图像。为了加快速度,我想到了做大多数电影编解码器所做的事情。有关键帧,然后只发送更改。

现在,我得到的是一组BufferedImage s,所以与文本文件类似,我基本上只想区分它们并发送补丁。 但是我以前从来没有真正使用过图像,所以如果我这样做的话,它会很糟糕。

那么,实现这样的事情的最佳方式是什么,或者这样的事情已经有了很好的实现?

我猜想将图像存储在一个字节数组中,二进制差异就不会非常有效。

编辑:我需要传输这些图像。 编辑2:与实现的具体细节不同之处在于:算法的最有效思想是什么。就像只使​​用5px块而不是忽略px如果它只是变化那么少,眼睛就不会注意到(我可以忍受一些质量损失)

6 个答案:

答案 0 :(得分:5)

一种简单的方法是对两个图像进行等效的XOR运算。这将显示相​​同的像素(将为零)和已更改的像素(非零)。

如果您不关心几乎难以察觉的差异,那么可选择使用“减法”混合然后右移以丢弃一位或两位差异。

然后,您可以计算边界(可能是一个简单的矩形)并仅传输增量。 delta可能包含很多零或最多几个字节,几乎没有最差位差异 - 即,它具有低'熵',这意味着理论上它应该是使用当代压缩算法高度可压缩的。

在接收端,反向过程同样简单。给定delta和边界框,解压缩delta,然后将其应用(XOR,或左移,然后添加)到前一个/现有图像的受影响区域。

对于更复杂的无损方法,请研究动画GIF / PNG的动画方式以及用于计算/编码帧之间的增量信息的算法。例如,请参阅What's the best way to make an animated GIF using an algorithm?

对于更复杂的方法,在处理真实世界的图像时,如果你愿意走有损路线 - 那么你已经暗示了它。查看视频编解码器如何编码/传输帧,例如MPEG Video Encoding

不言而喻,因为在复杂性(编码/解码过程)与传输数据大小减少之间需要权衡,你必须决定两端计算的额外开销是否值得传输节省。

答案 1 :(得分:3)

您可以使用getRGB(int x, int y)迭代BufferedImage的所有像素。

for (int x = 0; x < img.getWidth(); ++x)
{
    for (int y = 0; y < img.getHeight(); ++y)
    {
        int oldARGB = oldImg.getRGB(x, y);
        int newARGB = img.getRGB(x, y);
        if (oldARGB != newARGB)
        {
            // handle the diffrence
        }
    }

}

答案 2 :(得分:2)

我有个主意,其实这很简单。逐个比较像素

如果像素相等,则保存为RGBA(0,0,0,0)。然后将差异存储为PNG。

这是演示结果。差异非常小。

stackoverflow说you need at least 10 reputation to post images。所以我只能在这里张贴图片地址。

http://oi61.tinypic.com/2vs5ifl.jpg

答案 3 :(得分:0)

根据您想要投入的工作量,我建议一个相当简单的解决方案,将这些图像保存为位图并让7z压缩它们。然后发送档案。

答案 4 :(得分:0)

如果您不介意质量有所降低,并且想要一个非常有效的带宽解决方案,而无需为您做大量的手动工作,您还可以使用真实的电影编解码器对图像进行编码。特别是你有一个GPU来卸载计算,这种方法在计算工作方面也非常有效。

答案 5 :(得分:-1)

您可以更好地花时间开发应用程序,然后在出现问题时评估性能改进。我猜这整件事都是YAGNI。

  

为了加快速度,我想到了......

这不是一个要求,只是'如果......那就不会很酷'。凭借今天的网络速度,甚至可以在不到一分钟的时间内完成几百兆的传输。