我正在编写一个项目,我需要通过网络传输一组类似的图像。为了加快速度,我想到了做大多数电影编解码器所做的事情。有关键帧,然后只发送更改。
现在,我得到的是一组BufferedImage
s,所以与文本文件类似,我基本上只想区分它们并发送补丁。
但是我以前从来没有真正使用过图像,所以如果我这样做的话,它会很糟糕。
那么,实现这样的事情的最佳方式是什么,或者这样的事情已经有了很好的实现?
我猜想将图像存储在一个字节数组中,二进制差异就不会非常有效。
编辑:我需要传输这些图像。 编辑2:与实现的具体细节不同之处在于:算法的最有效思想是什么。就像只使用5px块而不是忽略px如果它只是变化那么少,眼睛就不会注意到(我可以忍受一些质量损失)
答案 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
。所以我只能在这里张贴图片地址。
答案 3 :(得分:0)
根据您想要投入的工作量,我建议一个相当简单的解决方案,将这些图像保存为位图并让7z压缩它们。然后发送档案。
答案 4 :(得分:0)
如果您不介意质量有所降低,并且想要一个非常有效的带宽解决方案,而无需为您做大量的手动工作,您还可以使用真实的电影编解码器对图像进行编码。特别是你有一个GPU来卸载计算,这种方法在计算工作方面也非常有效。
答案 5 :(得分:-1)
您可以更好地花时间开发应用程序,然后在出现问题时评估性能改进。我猜这整件事都是YAGNI。
为了加快速度,我想到了......
这不是一个要求,只是'如果......那就不会很酷'。凭借今天的网络速度,甚至可以在不到一分钟的时间内完成几百兆的传输。