【发布时间】: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