我正在使用Apache PDFbox库从PDF文件中提取突出显示的文本(即黄色背景)。我对这个库是完全陌生的,并且不知道它用于哪个目的。到目前为止,我已经使用以下代码从注释中提取了文本。
PDDocument pddDocument = PDDocument.load(new File("test.pdf"));
List allPages = pddDocument.getDocumentCatalog().getAllPages();
for (int i = 0; i < allPages.size(); i++) {
int pageNum = i + 1;
PDPage page = (PDPage) allPages.get(i);
List<PDAnnotation> la = page.getAnnotations();
if (la.size() < 1) {
continue;
}
System.out.println("Total annotations = " + la.size());
System.out.println("\nProcess Page " + pageNum + "...");
// Just get the first annotation for testing
PDAnnotation pdfAnnot = la.get(0);
System.out.println("Getting text from comment = " + pdfAnnot.getContents());
Run Code Online (Sandbox Code Playgroud)
现在,我需要突出显示文本,任何代码示例都将受到高度赞赏。
我希望这个答案可以帮助面临相同问题的每个人。
// PDF32000-2008
// 12.5.2 Annotation Dictionaries
// 12.5.6 Annotation Types
// 12.5.6.10 Text Markup Annotations
@SuppressWarnings({ "unchecked", "unused" })
public ArrayList<String> getHighlightedText(String filePath, int pageNumber) throws IOException {
ArrayList<String> highlightedTexts = new ArrayList<>();
// this is the in-memory representation of the PDF document.
// this will load a document from a file.
PDDocument document = PDDocument.load(filePath);
// this represents all pages in a PDF document.
List<PDPage> allPages = document.getDocumentCatalog().getAllPages();
// this represents a single page in a PDF document.
PDPage page = allPages.get(pageNumber);
// get annotation dictionaries
List<PDAnnotation> annotations = page.getAnnotations();
for(int i=0; i<annotations.size(); i++) {
// check subType
if(annotations.get(i).getSubtype().equals("Highlight")) {
// extract highlighted text
PDFTextStripperByArea stripperByArea = new PDFTextStripperByArea();
COSArray quadsArray = (COSArray) annotations.get(i).getDictionary().getDictionaryObject(COSName.getPDFName("QuadPoints"));
String str = null;
for(int j=1, k=0; j<=(quadsArray.size()/8); j++) {
COSFloat ULX = (COSFloat) quadsArray.get(0+k);
COSFloat ULY = (COSFloat) quadsArray.get(1+k);
COSFloat URX = (COSFloat) quadsArray.get(2+k);
COSFloat URY = (COSFloat) quadsArray.get(3+k);
COSFloat LLX = (COSFloat) quadsArray.get(4+k);
COSFloat LLY = (COSFloat) quadsArray.get(5+k);
COSFloat LRX = (COSFloat) quadsArray.get(6+k);
COSFloat LRY = (COSFloat) quadsArray.get(7+k);
k+=8;
float ulx = ULX.floatValue() - 1; // upper left x.
float uly = ULY.floatValue(); // upper left y.
float width = URX.floatValue() - LLX.floatValue(); // calculated by upperRightX - lowerLeftX.
float height = URY.floatValue() - LLY.floatValue(); // calculated by upperRightY - lowerLeftY.
PDRectangle pageSize = page.getMediaBox();
uly = pageSize.getHeight() - uly;
Rectangle2D.Float rectangle_2 = new Rectangle2D.Float(ulx, uly, width, height);
stripperByArea.addRegion("highlightedRegion", rectangle_2);
stripperByArea.extractRegions(page);
String highlightedText = stripperByArea.getTextForRegion("highlightedRegion");
if(j > 1) {
str = str.concat(highlightedText);
} else {
str = highlightedText;
}
}
highlightedTexts.add(str);
}
}
document.close();
return highlightedTexts;
}
Run Code Online (Sandbox Code Playgroud)
问题中的代码无法读取行中突出显示的确切文本,已经说明了大多数概念,这些概念可用于从具有PDFBox的页面上的有限内容区域提取文本。
在研究了这段代码之后,OP仍然在评论中纳闷:
但是令我困惑的一件事是QuadPoints而不是Rect。正如您在评论中提到的那样。这是什么,您能用一些代码行还是用简单的词来解释,因为我也面临着多行高度的相同问题?
通常,注释所指的区域是矩形:
Rect矩形(必填)注释矩形,以默认用户空间单位定义页面上注释的位置。
(摘自表164 – ISO 32000-1中所有注释词典共有的条目)
对于某些注释类型(例如,文本标记),此位置值不足,因为:
因此,为了应对此类注释类型,PDF规范提供了一种更通用的方式来定义区域:
QuadPoints array (必需)由8×n个数字组成的数组,用于指定默认用户空间中n个四边形的坐标。每个四边形应在注释下方的文本中包含一个单词或一组连续单词。每个四边形的坐标应按顺序给出
x 1 y 1 x 2 y 2 x 3 y 3 x 4 y 4
以逆时针顺序指定四边形的四个顶点(请参见图64)。文本应相对于边缘连接点(x 1,y 1)和(x 2,y 2)定向。
(摘自表179 – ISO 32000-1中特定于文本标记注释的其他条目)
因此,代替了给定的矩形
PDRectangle rect = pdfAnnot.getRectangle();
Run Code Online (Sandbox Code Playgroud)
在所引用问题的代码中,您必须考虑由给出的四边形
COSArray quadsArray = (COSArray) pdfAnnot.getDictionary().getDictionaryObject(COSName getPDFName("QuadPoints"));
Run Code Online (Sandbox Code Playgroud)
并相应地定义区域PDFTextStripperByArea stripper。不幸的是PDFTextStripperByArea.addRegion期望矩形作为参数,而不是一些通用的四边形。由于文本通常是水平或垂直打印的,因此不会造成太大的问题。
PS关于QuadPoints规格的警告,在实际的PDF中顺序可能有所不同,请参见。问题PDF规格VS创建的Acrobat(QuadPoints) 。