目前我正在使用iText进行PDF评估。评估时我遇到了人工BOLD和人工大纲样式的问题。 任何人都可以帮我看看是否可以使用iText API检查PDF文档中的人工大胆样式和人工轮廓样式? 请在下面找到示例PDF:
https://docs.google.com/file/d/0BzaBYVk1XnP_SGRqRDBwTG8tVUE/edit?pli=1
答案 0 :(得分:2)
iText允许您识别文档中使用的人工粗体和大纲样式。
具有人工样式的文档已经成为前一个问题How to determine artificial bold style ,artificial italic style and artificial outline style of a text using PDFBOX的焦点,并且可以在my answer中找到有关如何在文档中创建这些样式的更详细说明。
简短摘要:
首先以常规模式绘制字母,填充字母区域,然后以轮廓模式绘制字母,沿着字母边框绘制一条线,黑色,CMYK 0,0, 0,1;这留下了一个更厚的字母的印象。
通过首先在常规模式下以白色,CMYK 0,0,0,0绘制字母,填充字母区域,然后以轮廓模式绘制,沿着字母绘制一条线来创建人工轮廓文本边框,黑色,CMYK 0,0,0,1;这会在白色字母上留下轮廓黑色的印象。
了解如何创建这些样式,您可以尝试使用iText识别这些创建模式。幸运的是,iText在其解析事件中转发了所需的信息。
显然,iText中包含的文本提取策略不识别开箱即用的那些人工样式,因为有很多不同的方式可以创建这样的人工样式,样式提取不是iText的重点文本提取。因此,您必须创建自己的文本提取策略。
通过使用以下测试渲染侦听器,您可以获得转发到您的策略的事件的第一印象(文本提取策略是特殊的渲染侦听器,具有用于请求侦听器收集的文本的附加方法;此处的示例侦听器输出到stdout;因此,不需要额外的方法):
class StyleAnalyzer implements RenderListener
{
public void beginTextBlock() { }
public void endTextBlock() { }
public void renderImage(ImageRenderInfo renderInfo) { }
public void renderText(TextRenderInfo renderInfo)
{
System.out.printf("%s - %d - %s - %s - %s\n",
renderInfo.getBaseline().getStartPoint(),
renderInfo.getTextRenderMode(),
toString(renderInfo.getFillColor()),
toString(renderInfo.getStrokeColor()),
renderInfo.getText());
}
String toString(BaseColor color)
{
if (color instanceof CMYKColor)
{
CMYKColor cmyk = (CMYKColor) color;
return String.format("CMYK[%3.1f %3.1f %3.1f %3.1f]",
cmyk.getCyan(), cmyk.getMagenta(), cmyk.getYellow(), cmyk.getBlack());
}
return String.valueOf(color);
}
}
你可以像这样使用它:
PdfReader reader = new PdfReader("artificial text.pdf");
PdfReaderContentParser parser = new PdfReaderContentParser(reader);
System.out.println("start point - rendering mode - fill color - stroke color - text\n");
parser.processContent(1, new StyleAnalyzer());
对于人工粗体文本,您可以获得以下(稍微重新格式化)单词“This”的输出:
start point - rendering mode - fill color - stroke color - text
66.36,729.86,1.0 - 0 - CMYK[0,0 0,0 0,0 1,0] - null - T
66.36,729.86,1.0 - 1 - CMYK[0,0 0,0 0,0 1,0] - CMYK[0,0 0,0 0,0 1,0] - T
81.11,729.86,1.0 - 0 - CMYK[0,0 0,0 0,0 1,0] - null - h
81.11,729.86,1.0 - 1 - CMYK[0,0 0,0 0,0 1,0] - CMYK[0,0 0,0 0,0 1,0] - h
96.11,729.86,1.0 - 0 - CMYK[0,0 0,0 0,0 1,0] - null - i
96.11,729.86,1.0 - 1 - CMYK[0,0 0,0 0,0 1,0] - CMYK[0,0 0,0 0,0 1,0] - i
104.86,729.86,1.0 - 0 - CMYK[0,0 0,0 0,0 1,0] - null - s
104.86,729.86,1.0 - 1 - CMYK[0,0 0,0 0,0 1,0] - CMYK[0,0 0,0 0,0 1,0] - s
因此,对于每个字母,您将获得两个文本呈现调用,包括相同位置和相同文本,第一个处于渲染模式0( fill ),第二个处于模式1(笔画),相关的颜色在CMYK中总是黑色。
对于人工轮廓文本,您可以获得以下(稍微重新格式化)单词“This”的输出:
66.0,661.75,1.0 - 0 - CMYK[0,0 0,0 0,0 0,0] - null - T
66.0,661.75,1.0 - 1 - CMYK[0,0 0,0 0,0 0,0] - CMYK[0,0 0,0 0,0 1,0] - T
79.0,661.75,1.0 - 0 - CMYK[0,0 0,0 0,0 0,0] - null - h
79.0,661.75,1.0 - 1 - CMYK[0,0 0,0 0,0 0,0] - CMYK[0,0 0,0 0,0 1,0] - h
92.5,661.75,1.0 - 0 - CMYK[0,0 0,0 0,0 0,0] - null - i
92.5,661.75,1.0 - 1 - CMYK[0,0 0,0 0,0 0,0] - CMYK[0,0 0,0 0,0 1,0] - i
99.25,661.75,1.0 - 0 - CMYK[0,0 0,0 0,0 0,0] - null - s
99.250015,661.75,1.0 - 1 - CMYK[0,0 0,0 0,0 0,0] - CMYK[0,0 0,0 0,0 1,0] - s
因此,对于每个字母,您将获得两个文本呈现调用,两者都在(几乎)相同的位置和相同的文本,第一个在渲染模式0( fill )中,在CMYK中为白色,模式1中的第二个(描边),CMYK中为黑色。
因此,在渲染侦听器中,您将不得不寻找这样的文本渲染调用模式。
您可能希望首先复制LocationTextExtractionStrategy
,使用呈现模式和颜色信息扩展其TextChunk
辅助类,并在renderText
中创建实例时相应填充这些字段。
只要消化了所有页面事件,就可以使用与LocationTextExtractionStrategy.getResultantText(TextChunkFilter)
类似的方法将块粘合在一起。但是,除了现有的实现之外,您还必须检查相同(或几乎相同,参见上面的最终大纲)位置的块。如果它们包含相同的文本,并且它们的渲染模式和相关颜色显示上面的图案,则您可以使用人工粗体或轮廓文本,并且可以根据需要对其进行处理。
TextRenderInfo
对象中的转换矩阵。但是,你需要这个来识别人工斜体样式,正如我对PDFBox相关问题的回答中所解释的那样。但是,从版本5.4.5开始,它作为私有成员 textToUserSpaceTransformMatrix
出现在那里。因此,使用反射,你能也可以访问该成员(如果没有安全管理员禁止它)并识别人工斜体。