【问题标题】:JAI: How do I extract a single page input stream from a multipaged TIFF image container?JAI:如何从多页 TIFF 图像容器中提取单页输入流?
【发布时间】:2017-06-15 11:06:10
【问题描述】:

我有一个将 PDF 文档转换为图片的组件,每页一张图片。由于该组件使用生成内存中图像的转换器,因此它会严重影响 JVM 堆并需要一些时间来完成转换。

我正在尝试提高转换过程的整体性能,并找到了一个带有 JNI 绑定的本机库,可以将 PDF 转换为 TIFF。该库只能将 PDF 转换为单个 TIFF 文件(需要中间文件系统存储;甚至不消耗转换流),因此结果 TIFF 文件具有嵌入的转换页面,而不是文件系统上的每页图像。拥有一个原生库极大地改善了整体转换并且性能变得非常快,但是有一个真正的瓶颈:因为我必须进行源页面到目标页面的转换,现在我必须从结果文件中提取每个页面并编写他们都在别处。 RenderedImages 的简单天真方法:

final SeekableStream seekableStream = new FileSeekableStream(tempFile);
final ImageDecoder imageDecoder = createImageDecoder("tiff", seekableStream, null);
...
//                                               V--- heap is wasted here
final RenderedImage renderedImage = imageDecoder.decodeAsRenderedImage(pageNumber);
// ... do the rest stuff ...

实际上,我真的很想从 TIFF 容器文件 (tempFile) 中提取一个具体的页面输入流,然后将其重定向到其他地方,而无需将其存储为内存中的图像。我会想象一种类似于容器处理的方法,我需要寻找一个特定的条目来从中提取数据(例如,ZIP 文件处理等)。但是我在ImageDecoder 中找不到类似的东西,或者我的期望可能有误,只是在这里遗漏了一些重要的东西......

是否可以使用 JAI API 或第三方替代方案提取 TIFF 容器页面输入流?提前致谢。

【问题讨论】:

    标签: java tiff jai


    【解决方案1】:

    我可能是错的,但不认为 JAI 支持在不将文件解码为内存图像的情况下拆分 TIFF。而且,很抱歉推广我自己的库,但我认为它完全符合您的需要(用于拆分 TIFF 的解决方案的主要部分由第三方提供)。

    通过使用 com.twelvemonkeys.contrib.tiff 中的 TIFFUtilities 类,您应该能够将多页 TIFF 拆分为多个单页 TIFF,如下所示:

    TIFFUtilities.split(tempFile, new File("output"));
    

    没有对图像进行解码,仅将每个 IFD 拆分为一个单独的文件,并使用更正的偏移量和字节数写入流。

    文件将命名为output/0001.tifoutput/0002.tif 等。如果您需要对输出名称进行更多控制或有其他要求,您可以轻松修改代码。该代码带有 BSD 风格的许可证。

    【讨论】:

    • 没有完成图像解码 - 这是我发布问题时没有 100% 知道的一点(我只是假设它可能看起来像邮编容器)。据我了解 TIFF 是如何实现的,它只是一个容器,从容器中按页码撕下每个图像可能很容易,对吧?因此,如果我做对了,TIFFUtilities.split 在某种意义上使开销为零,因为它不进行任何图像编码/解码,因此它会按原样发出 TIFF 图像集,就像它们最初的形式一样存放在容器中?
    • @LyubomyrShaydariv 是的,TIFF 在某些方面是一种容器格式。但是,由于图像数据和标签和标签数据(IFD)都可以交错存储,因此比仅找到单个偏移量并从那里写入要稍微困难一些。每个 IFD 的元数据都会更改,并且必须为每个新文件重写。但是图像数据本身将被原封不动地复制,所以是的,开销应该可以忽略不计。
    • 这太棒了,因为您的库节省了很多,并且做了我所不知道的其他库所做的事情,谢谢!只有一个问题:您的库是否支持按页码提取图像并将单页图像重定向到输出流而不是生成单页图像文件?
    • @LyubomyrShaydariv 不,不是开箱即用。但我认为您应该能够通过一些小的更改来重新设计 split 方法来做到这一点。
    • 我刚刚检查了split方法的实现,看起来非常简单,所以可以很容易地实现以满足我的需求。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多