BufferedImage减小图像大小

我正在使用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)
}

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

为什么文件大小如此减少?

nabela123 回答:BufferedImage减小图像大小

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

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

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

几乎可以肯定,这里正在发生什么。您的代码读取JPEG文件,并将其扩展为BufferedImage(用于保存未压缩的图像数据),然后再次将其压缩为新的JPEG文件,这将进一步降低质量。它使用的压缩率可能比使用的第一个文件高很多,因此文件的大小更小。

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

创建JPEG时,您可以控制丢失多少信息-但是您使用的ImageIO.write()方法无法提供实现此目的的方法。有关操作方法,请参见this question。 (它是Java语言,但是您应该可以遵循它。)

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

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

正如您所指出的,另一个原因可能是丢失了非图像数据 –您不太可能注意到丢失了诸如相机设置之类的元数据,但是该文件的缩略图可能很大图像。

本文链接:https://www.f2er.com/2824380.html

大家都在问