【发布时间】:2018-04-26 13:56:06
【问题描述】:
文件示例:test
在表格的第 2 行,在“3500 RENT”之后,PdfTextStripper 返回了 2 个文本标记(“1”、“1”),但实际上在原始 PDF 中不可见。
我知道这可能是剪辑路径(如帖子here)或颜色问题(如帖子here)。
但是,在这种情况下,它似乎被其他方式隐藏了......剪辑路径不重叠,并且这些标记的颜色为黑色。
还能是什么?
【问题讨论】:
文件示例:test
在表格的第 2 行,在“3500 RENT”之后,PdfTextStripper 返回了 2 个文本标记(“1”、“1”),但实际上在原始 PDF 中不可见。
我知道这可能是剪辑路径(如帖子here)或颜色问题(如帖子here)。
但是,在这种情况下,它似乎被其他方式隐藏了......剪辑路径不重叠,并且这些标记的颜色为黑色。
还能是什么?
【问题讨论】:
这是颜色问题,'1's 打印为白色。
使情况有点特别的是,使用的 ColorSpace 不是您现成的 DeviceRGB 或 DeviceGray 而是一个Separation 颜色空间,Separation 颜色空间中的颜色值始终被视为减色。因此,0.0 的色调值表示使用给定着色剂可以实现的最亮颜色,而 1.0 表示最暗。此约定与 DeviceCMYK 颜色分量相同,但与 DeviceGray 和 DeviceRGB 的约定相反。
(参见 ISO 32000-1 第 8.6.6.4 节“分离颜色空间”)
您的内容流开始如下:
/Cs8 cs 1 scn
Cs8是一个Separation色彩空间:
/Cs8 [/Separation /Black [/ICCBased 17 0 R] 18 0 R]
具有 ICCBased 备用空间,而该备用空间又具有 DeviceRGB 作为备用空间
17 0 obj
<<
/Length 2597
/Alternate /DeviceRGB
/Filter /FlateDecode
/N 3
>>
stream
[...ICC profile...]
endstream
endobj
以及通过采样到备用色彩空间的色调变换
18 0 obj
<<
/Length 779
/BitsPerSample 8
/Decode [0 1 0 1 0 1]
/Domain [0 1]
/Encode [0 254]
/Filter /FlateDecode
/FunctionType 0
/Range [0 1 0 1 0 1]
/Size [255]
>>
stream
[...255 samples from (255,255,255) to (35,31,32)...]
endstream
endobj
您的内容流继续绘制标题和第一行开头的操作,然后
/TT2 1 Tf
0 scn
13.559 0 TD
6.8438 Tc
<00140014>Tj
1 scn
0 scn 将颜色设置为最亮的 Cs8 BLACK 分色,由样本映射到屏幕上的 (255,255,255),这将是非常白色的,6.8438 Tc 设置较大的字符间距(导致在两个 '1' 之间的间隙中),<00140014>Tj 绘制了两个 '1',1 scn 切换回由样本映射到 (35,31,32) 的最暗 Cs8 BLACK 分色屏幕上的颜色将是非常深的灰色。
在你说的评论中
当我在
processTextPosition(TextPosition text)中调试它时,gs.getNonStrokingColor()对那些“1”标记与其他标记具有相同的值,实际上是黑色的
要使用 PDFBox 识别这一点,您必须告诉其 PDFTextStripper 查找通用颜色空间选择和颜色选择运算符 cs 和 scn 并扩展 @987654334 @like 在这个概念验证中:
PDFTextStripper stripper = new PDFTextStripper() {
@Override
protected void processTextPosition(TextPosition text) {
PDGraphicsState gs = getGraphicsState();
PDColor color = gs.getNonStrokingColor();
float[] currentComponents = color.getComponents();
if (!Arrays.equals(components, currentComponents)) {
System.out.print(Arrays.toString(currentComponents));
components = currentComponents;
}
System.out.print(text.getUnicode());
super.processTextPosition(text);
}
float[] components;
};
stripper.addOperator(new SetNonStrokingColorSpace());
stripper.addOperator(new SetNonStrokingColorN());
(ExtractText 测试testTestSeparation)
有了这些设置,你就可以得到
[1.0]TenantLeaseStart ... 3,500.00RENT[0.0]11[1.0]16,133.33
如您所见,颜色分量以1.0 开头,对于两个“1”,它是0.0,然后再次变为1.0,直到下一次运行不可见的“1”。
【讨论】: