13

我正在尝试编写一个程序(java中的prob)以无损地将多个jpeg连接在一起而无需先解码它们。

我想我会从简单开始,尝试使用十六进制编辑器附加 2 个相同大小的 jpeg,使用相同的设置压缩在另一个之上。

首先,我提取 jpeg B 的图像数据并将其附加到 jpeg A。通过修改标题中指定的尺寸,我得到了一个可以显示的新可识别图片(jpeg A + jpeg B 附加在 y 轴上)。然而,虽然 jpeg B 的图像数据清晰可辨,但似乎丢失了很多颜色信息,显然是不正确的。

所以我的问题是我在这里错过了哪些步骤?我认为我不需要更改任何其他特定于维度的标头值,所以也许我需要对两个 jpeg 中的图像数据进行霍夫曼解码,然后将它们附加在一起,然后重新编码很多?

我花了一些时间阅读 jpeg 规范和标题等,但老实说,我已经超出了我的深度,真的可以用一两个指针来做!

非常感谢您的帮助。


感谢所有的建议。是的,这绝对是可能的,我应该在我原来的问题中提到 jpegtran。我基本上是在尝试复制 jpegtran 功能的这一方面,但在我自己的程序中使用它。我想我应该看一下 jpegtran 源代码,但我对 C 一无所知,对一般编程也不太了解,所以逆向工程源代码说起来容易做起来难!

4

8 回答 8

20

这是非常可行的。我在很多谷歌地图图像块上做了这个,加入这些块并形成一个海报大小的图像。有一个用于 Unix 的包叫做 JPEG Tools 来做这件事。该程序称为jpegjoin。纯 C 源代码,提供Windows 二进制文件。编译后,它会创建一个命令行应用程序,该应用程序在运行时会无损地连接两个 jpeg 图像以及许多其他内容。它不会解压缩任何图像,只是将压缩数据合并在一起并相应地修复标题。我用它合并了 100 个图像以创建 50 个条带,然后再次合并这些条带以创建一个大图像。

更多信息可以在http://en.wikipedia.org/wiki/Lossy_compression#Lossless_editing找到

源代码

可以在此处找到底层jpegtran库的源代码。一个模拟jpegjoin的示例脚本在这里

于 2009-03-04T08:42:02.540 回答
3

好的,我找出了哪里出错了。

1)图像扫描数据以字节为单位保存,但实际的重要信息被编码为可变长度的位串。这意味着实际图像数据的结尾不一定落在字节边界上。当 jpeg 编码器需要填充比特数以形成字节边界时,它只需添加一系列 1。

2)实际像素信息的存储方式有点太复杂(至少对我来说)无法解释,但基本上所有内容都在 MCU 内编码,最小编码单元或其他东西。它们的大小取决于色度二次采样,水平和垂直大小为 8 或 16 像素。对于每个 MCU,都有 DC 和 AC 部分组成亮度、Y 或色度、Cb 和 Cr 的单个分量。问题是直流分量被存储为与前一个 MCU 的相关直流值相关的值。因此,当我添加来自 jpg B 的新图像数据时,它已经存储了与 0 相关的 DC 值(因为没有以前的 MCU),但它需要考虑来自 jpg A 的最后一个 MCU 的最终 DC 值。 (希望这是有道理的)。

解决方案:

您需要对图像数据进行初始解码(霍夫曼 + 游程长度),以准确找出图像数据结束的位置,然后去除尾随的 1。您还需要适当地更改第二个 jpg 中的初始 DC 值。然后,您需要重新编码适当的位,添加 1 以适应字节边界,等等。

如果你想在 x 轴上追加,它有点复杂。您必须重新排列 MCU,以便它们以正确的顺序扫描。Jpgs 从左到右扫描,然后从上到下扫描,然后适当调整 DC 值。

到目前为止,我只在单个 MCU jpg 上对此进行了测试,但理论上它也应该适用于更大的 jpg。

顺便说一句,感谢这个优秀的 jpg 相关资源/博客的所有者,我才解决了这个问题

于 2009-03-19T16:13:41.703 回答
2

jpeg 与 mp3 一样 - 在您重新压缩它时通常是稳定的(使用相同的算法)。

因此,当您加入图像并重新压缩它们时,只需确保新的压缩率高于或等于 2 张图片中的最高值。这样你就不会真正失去准确性。

于 2009-03-04T08:23:19.793 回答
2

两种方法:

1)解码两个源JPEG图像,合并生成的位图并再次编码为JPEG。这里的缺点是重新压缩。

2) 确保源图像的宽度和高度是 16 的倍数,可能通过裁剪图像。不要解码图像,而是从源 MCU 块(16 x 16 像素大小,因此裁剪)组装目标 JPEG。

于 2009-03-04T08:29:06.223 回答
1

我建议您考虑 DRI 和 RSTn 标记,虽然这需要很多先决条件,但它适用于我:将 PPM(位图格式)附加到使用 DRI 和 RSTn 编码的 jpeg,两者宽度相同,两者都是 MCU 的倍数。

我只是在最后一个 RSTn 标记(如果有)之后剪掉 jpeg 数据,将其解码为 PPM,然后将两个 PPM 连接到单个 MCU 行,使用与原始 jpeg 相同的选项对其进行编码,重新排列结果中的 RST jpeg 根据原始 jpeg,然后将结果附加到原始 jpeg。使用这种方法,它可以防止我解码整个原始 jpeg 并再次对其进行编码。

作为解码和编码的东西,我使用的是 libjpeg。

于 2012-07-20T02:20:41.867 回答
0

与水平附加图像不同,将每个图像旋转 90 度,然后垂直连接它们,然后将生成的图像旋转回 -90 度可能更容易。

于 2013-05-02T12:58:04.477 回答
-3

无损 JPEG 操作几乎是矛盾的。你可以做一些诡计,比如旋转,但仅此而已。

我建议您使用无损源图像(想到 TIFF 或 PNG),或者重新评估您的图像质量要求 - 再次重新采样 JPEG,给定不错的原始文件,对于那里的绝大多数人来说是无法区分的。

于 2009-03-04T07:52:19.307 回答
-4

你想要做的基本上是不可能的。
JPEG 文件的编码有点复杂,如果您要更改像素的内容,那么编码将会被更改。您最终可能会得到一个小于或大于您组合的两个图像的总和的图像。唯一可能无损的操作是与原始图像的像素保持一一对应的操作。这基本上可以归结为 90 度旋转。

于 2009-03-04T08:24:31.693 回答