【问题标题】:BufferedImage reduces Image sizeBufferedImage 减小图像大小
【发布时间】:2020-01-03 14:36:27
【问题描述】:

我使用 java ImageIO 和 BufferedImage 进行一些图像操作,想看看当我将图像输出为 jpg 时它的行为。在那里我发现了一些我无法解释的有趣行为。我有以下代码。该代码读取图像,然后在同一文件夹中输出与“copy.jpg”相同的图像。代码在 Kotlin 中,但使用的函数是 java 函数:

val image = File("some/image/path.jpg")
val bufImage = ImageIO.read(image.inputStream())
FileOutputStream(File(image.parentFile, "copy.jpg")).use { os ->
    ImageIO.write(bufImage, "jpg", os)
}

我希望它输出完全相同的文件,除了元信息。然而,生成的文件几乎是原始文件的十分之一。我怀疑元信息会那么多。确切的大小差异取决于我使用的图像文件,但是每次输出图像都会变小。但我看不到旧文件的质量差异。放大时,我会看到相同的像素。

为什么文件大小会如此显着减小?

【问题讨论】:

  • JPG 是一种有损压缩格式。这可能就是原因。
  • 如果您想要完全相同的文件,您可能希望使用另一个文件写入操作直接进行字节缓冲区复制,而不是 ImageIO.write。本质上,使用 ImageIO.write 可能会根据扩展名对最终文件应用额外的压缩。
  • JPEG 格式有许多选项。例如,如果您从GIMP 将图像导出为 JPEG,它会询问您的图像质量设置,这会影响图像的压缩程度。几乎可以肯定,您保存的图像比使用的原始图像具有更大的压缩系数。
  • 我想如果你对两张图片做减法,你会发现一些不同。另外,是什么创建了您的原始 jpg?一些相机会使用质量比 java 的默认值高得多的 jpg。此外,每次打开图像并使用 jpg 压缩保存一些损失值时,它都会丢失一些信息。
  • 无论图像尺寸/压缩如何,JPEG 文件的元数据通常大小相同。因此,对于小图像,元数据可能占据文件的大部分......但没有知道原始 JPEG 中的内容,这当然只是猜测。

标签: java kotlin bufferedimage javax.imageio


【解决方案1】:

JPEG 是lossy compression:它会丢弃大量信息以保持文件较小。 (未压缩的图像文件可能要大几个数量级。)

当然,它旨在丢弃您不太可能看到或关心的信息;但它仍然会丢失一些图像数据。

而且损失是世代相传的:如果您有一张来自 JPEG 文件的图像,然后将其重新压缩为 JPEG 文件,它通常会丢失 更多 数据,提供比第一个 JPEG 文件质量更差的结果 — 即使压缩设置完全相同。 (尝试逼近已经压缩的图像与尝试逼近原始源图像的工作方式不同。并且无法恢复已经丢失的信息!)

几乎可以肯定这就是这里发生的事情。您的代码读取 JPEG 文件并将其扩展为 BufferedImage(其中包含未压缩的图像数据),然后再次将其压缩为新的 JPEG 文件,这会进一步降低质量。它可能使用比第一个文件更高的压缩率,因此更小。

如果您在放大的图像查看器或编辑器中看不到两个 JPEG 文件之间的任何差异,我会感到惊讶。 (JPEG 伪影在锐利的边缘和边界周围最为明显,但如果您知道要查找的内容,有时可以在其他地方看到它们。如果您可以将两个图像排列在完全相同的屏幕区域并翻转,则可以更容易地看到细微的变化直接在他们之间。)

您可以在创建 JPEG 时控制丢失的信息量,但您使用的 ImageIO.write() 方法无法做到这一点。请参阅this question 了解如何操作。 (它是用 Java 编写的,但你应该能够遵循它。)

显然,您准备丢失的信息越多,您最终可以得到的文件就越小。但请注意,如果您选择高质量设置,结果可能会比第一个 JPEG 大很多,尽管它可能仍会损失更多质量。

(这就是为什么,如果您要对图像进行任何类型的处理,最好将其保持在无损格式直到最后,并且只压缩一次像 JPEG 这样的有损格式,以避免每次都损失质量你保存并重新加载。)

正如您所指出的,另一个原因可能是丢失了非图像数据 - 您不太可能注意到相机设置等元数据的丢失,但该文件可能有一个相当大的缩略图图片也是。

【讨论】:

    猜你喜欢
    • 2017-02-06
    • 2019-04-13
    • 1970-01-01
    • 1970-01-01
    • 2019-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多