使用 LocationTextLocationStrategy 的 iText "Coordinate outside allowed range" 异常

iText "Coordinate outside allowed range" exception using LocationTextLocationStrategy

当我尝试使用 LocationTextExtractionStrategy 时抛出异常 "Coordinate outside allowed range"。

for (int pageNum = 1; pageNum <= document.getNumberOfPages(); pageNum++)
{
    PdfPage page = document.getPage(pageNum);
    sb.append(PdfTextExtractor.getTextFromPage(page, new LocationTextExtractionStrategy()));
}

有关异常的更多信息:

java.lang.IllegalStateException: Coordinate outside allowed range

    at com.itextpdf.kernel.pdf.canvas.parser.clipper.ClipperBase.rangeTest(ClipperBase.java:76)

我有 2 个由同一个软件生成的类似 PDF,第一个抛出异常,第二个没有。

PDF 1 (exception)

PDF 2 (ok)

什么在第一个 PDF 中引发此异常?如何在不使用 SimpleTextExtractionStrategy 的情况下解决这个问题?

(根据您的堆栈跟踪,您使用的是 iText 7.* 版本。我相应地更新了您的问题标签,并使用当前的 iText 7.1.2-SNAPSHOT 重现了该问题。)

什么在第一个 PDF 中引发此异常?

简而言之

您的两个 PDF 都包含用于定义剪辑路径的极端 y 坐标(超出 ISO 32000-1 实施限制),您的 PDF 1 仅是 PDF 2 和 iText 剪辑的两倍路径例程在两者之间的某个地方开始打嗝。

详细

PDF 1 第 1 页的页面内容流基本上如下所示:

q
[...]
% modifyCTM
0.802969 0 0 -0.802969 0 842 cm
[...]
q
0 0 741 98417 re W n
[...]
Q
q
0 0 741 98417 re W n
[...]
Q
q
0 0 741 98417 re W n
[...]
Q
q
0 0 741 98417 re W n
[...]
Q
q
0 0 741 98417 re W n
[...]
Q
q
0 0 741 98417 re W n
[...]
Q
Q

因此,即使考虑到 CTM 的初始修改,您也六次定义了高度为 98417 * 0.802969 默认用户单位的剪辑路径矩形,该高度大约等于 79026 默认用户单位。

ISO 32000-1 Annex C.2 架构限制 另一方面表明

conforming readers should accommodate PDF files that obey the constraints.

[...]

  • The minimum page size should be 3 by 3 units in default user space; the maximum should be 14,400 by 14,400 units.

因此,您的剪辑路径矩形是符合要求的 reader 预期支持的页面高度的五倍多。因此,符合要求的 reader 不需要支持您的极端剪辑路径。

PDF 2 的构建方式类似,所讨论的剪辑路径只有 41879 * 0.802969 个单位高,即大约 33628 个单位,这只是需要支持的两倍多。由于某些原因,iText 似乎仍然支持这一点。

如何在不使用 SimpleTextExtractionStrategy 的情况下解决这个问题?

您可以通过更改常量来调整 iText 7 com.itextpdf.kernel.pdf.canvas.parser.clipper.ClipperBridge.floatMultiplier

/**
 * Since the clipper library uses integer coordinates, we should convert
 * our floating point numbers into fixed point numbers by multiplying by
 * this coefficient. Vary it to adjust the preciseness of the calculations.
 */
public static double floatMultiplier = Math.pow(10, 14);

你可以试试Math.pow(10, 10) 这对我适用于你的两个文件。


也就是说,ISO 32000-2 似乎已经放弃了这个特定的页面大小限制,只是有更通用的限制加上声明,例如特定设备上的 特定 PDF 处理器 运行而且在特定的运行环境下总会有实际的限制。

因此,@iText 应该考虑当前的限制是实际限制还是应该放宽。