【问题标题】:Uncompress a TIFF file without going through BufferedImage不通过 BufferedImage 解压 TIFF 文件
【发布时间】:2012-06-01 09:39:20
【问题描述】:

我收到大尺寸的 CCITT Group 4 压缩 TIFF 文件,这些文件需要作为未压缩的 TIFF 文件写入其他地方。我正在使用 jai_imageio TIFF 读取器和写入器来执行此操作,只要图像的乘积 _width * height_ 适合整数,它就可以很好地工作。

这是我正在使用的代码:

TIFFImageReaderSpi readerSpi= new TIFFImageReaderSpi();
ImageReader imageReader = readerSpi.createReaderInstance();
byte[] data = blobManager.getObjectForIdAndVersion(id, version);
ImageInputStream imageInputStream = ImageIO.createImageInputStream(data); 
imageReader.setInput(imageInputStream);

TIFFImageWriterSpi writerSpi = new TIFFImageWriterSpi();
ImageWriter imageWriter = writerSpi.createWriterInstance();
ImageWriteParam imageWriteParam = imageWriter.getDefaultWriteParam();
imageWriteParam.setCompressionMode(ImageWriteParam.MODE_DISABLED);
//bufferFile is created in the constructor
ImageOutputStream imageOutputStream = ImageIO.createImageOutputStream(bufferFile);
imageWriter.setOutput(imageOutputStream);

//Now read the bitmap
BufferedImage bufferedImage = imageReader.read(0);
IIOImage iIOImage = new IIOImage(bufferedImage, null, null);
//and write it
imageWriter.write(null, iIOImage, imageWriteParam);

不幸的是,我收到的文件通常非常大,无法创建 BufferedImage。 我一直在尝试找到一种从 ImageReader 直接流式传输到 ImageWriter 的方法,但我不知道如何做到这一点。 有人有建议吗?

【问题讨论】:

    标签: java tiff jai javax.imageio


    【解决方案1】:

    我遇到了一些问题,最终结果可能会让您感到惊讶:

    我最终使用 Runtime.exec() 方法使用一些命令行选项调用 IrfanView。这样,我不担心压缩或大小,它只是工作并为我在正确的文件夹中输出正确的文件。

    如果你在 Linux 上,你可以使用 ImageMagik 或类似的东西。

    【讨论】:

    • 谢谢,但这不是我的选择。首先是因为它不是开源的,只能在 Windows 下运行。如果我决定使用本机代码,我可以很容易地使用 libtiff 编写自己的解压缩器。
    • 你可以在 Linux 上使用 ImageMagik 做同样的事情 :)
    • 我的问题是关于 JAI 课程的。我知道在 Java 环境之外还有其他解决方案,但这不是我想要的。
    • 一旦你的数组超出整数范围,你就会遇到麻烦。也许有办法对图像进行分区?
    【解决方案2】:

    您可以使用 TIFF 切片将 TIFF 分割成更小的部分(“切片”)。如果您控制创建大图像的代码,JAI 允许您逐块检索图像内容。

    这是一个关于如何使用 JAI 创建平铺图像的示例:

    ColorModel cm = source.createColorModel();
    // SampleModel with the tilesize
    SampleModel sm = cm.createCompatibleSampleModel(tileWidth, tileHeight);
    TiledImage image = new TiledImage(0, 0, imageWidth, imageHeight, 0, 0, sm, cm);
    
    TIFFEncodeParam tep = new TIFFEncodeParam();
    tep.setTileSize(tileWidth, tileHeight); // Set tile size to avoid OOM
    tep.setWriteTiled(true);
    JAI.create("filestore", image, filepath, "TIFF", tep);
    

    如果你不能控制 TIFF 的制作,我对 JAI 的了解太有限,帮不上什么忙。

    【讨论】:

      【解决方案3】:

      为您的 Java VM 提供更多内存。

      如果这不起作用,请查看source code of the TIFF plugin in the JAI source code。您也许可以编写自己的处理器,它只是使用流式方法解压缩数据结构(因此您永远不必随时将整个图像保存在内存中)。

      如果这也不起作用,请查看JNA,它允许您从 Java 调用 DLL 中的代码(无需 C 代码;一切都由纯 Java 完成,与 Sun 的 JNI API 不同)。

      【讨论】:

      • 谢谢,但它与 VM 内存无关。问题是图像数据数组的增长大于整数的最大值。我确实可以分叉 JAI 代码,但这是我想避免的。 JNA 听起来像是一个有趣的项目,但 JNI 在其他地方对我来说效果很好。我只是想避免不得不在外部解决这个问题,但看起来似乎不可能。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多