【问题标题】:Combine multiple tif and Jpeg into single tif file has huge size将多个 tif 和 Jpeg 组合成单个 tif 文件,大小很大
【发布时间】:2020-09-13 15:55:41
【问题描述】:

我正在尝试将多个 tif 和 jpeg 文件合并到一个 tif 文件中。

当多个 tif 文件单独合并为一个 tif 文件时,该文件的大小几乎与原始多个 tif 文件相同(10 MB 多个 tif 文件----> 10 MB 单个 tif 文件)。这是完美的。

但是,当单独的 tif 文件和许多 Jpeg 文件合并为单个 tif 文件时,文件大小与原始文件相比是巨大的(10 MB 的多个 tif 和 Jpeg 文件导致创建 200 MB 的 tif 文件)。

JPEG 文件来时有没有办法防止文件过大?

使用的代码:

List<BufferedImage> bufferedImageList = new ArrayList<>();
for (String page : pages) {
BufferedImage bufferedImage = ImageIO.read(file);
    bufferedImageList.add(bufferedImage);
}

String filename = "D:\home\example.tif";
ImageWriter writer = ImageIO.getImageWritersByFormatName("TIF").next();

try (ImageOutputStream output = ImageIO.createImageOutputStream(new File(filename))) {
    writer.setOutput(output);

    ImageWriteParam params = writer.getDefaultWriteParam();
    params.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);

    params.setCompressionType("LZW");
    params.setCompressionQuality(1.0f);

    writer.prepareWriteSequence(null);

    for (BufferedImage image : bufferedImageList) {
        writer.writeToSequence(new IIOImage(image, null, null), params);
    }
    
    
    writer.endWriteSequence();
    
}

writer.dispose();

【问题讨论】:

  • 有损 jpeg 压缩比 LZW 压缩效率高。
  • 如何实现有损JPEG压缩?
  • 使用压缩类型“JPEG”而不是“LZW”。

标签: java jpeg bufferedimage tiff javax.imageio


【解决方案1】:

正如@Henry 在 cmets 中所写,使用 LZW(或任何其他无损)压缩不会达到与有损 JPEG(对于“自然”图像)相同的压缩效果。在大多数情况下,走这条路会产生更大的文件,但质量可能最高。在许多情况下,这是可以接受的。

另一种方法是在 TIFF 文件中也使用 JPEG 压缩,方法是指定 compressionType "JPEG"。您可能还需要将compressionQuality 设置为较低的值(我相信0.7f 是ImageIO 中JPEG 的默认值),以获得更合理的文件大小。

但是,使用 JPEG 压缩来重新压缩已经 JPEG 压缩的图像,将引入 "generational loss",因为 JPEG 通常无法完美地重建。从技术上讲,通过使用与原始表相同的表重新压缩,将这种质量损失保持在最低限度是可能的,但这在实践中很难实现,因为编码器/解码器中的舍入误差很小(即你最好的选择是使用相同的编写原始代码的编码器,具有完全相同的参数)。

第三个选项是使用/创建一个特殊用途的 TIFF 实用程序,它可以将 JPEG 流按原样存储在新的 TIFF 容器中。这些文件可能不是超高效的 TIFF,因为它们不支持条带/平铺等,并且某些非标准输入可能仍需要重写以生成有效的 TIFF。这将需要更多的工作,并且需要对 TIFF 格式有一些深入的了解,但肯定是可行的。

【讨论】:

  • 您提到的压缩类型和数量帮助很大,谢谢。然而,对于一组文件(75 MB 大小),内存消耗急剧增加,几乎达到 2 GB 的高位。有什么想法吗??
  • 代码中明显的“错误”是您首先将所有图像读入内存,然后将它们全部写入新的 TIFF。一次读取 一个 图像,然后附加到 TIFF inside for(pages) 循环的内存效率要高得多。另一件需要注意的是,任何压缩图像文件的文件大小和解码后的内存大小直接相关。
猜你喜欢
  • 2012-06-23
  • 1970-01-01
  • 1970-01-01
  • 2021-04-18
  • 1970-01-01
  • 2021-09-04
  • 2017-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多