該賞金過期5天。此問題的答案有資格獲得 250聲望獎勵。 Sahib Yar正在尋找規范的答案。
如何使用 PDFBox 從 PDF 中提取對角線水印文本?
參考ExtractText 的 rotationMagic
選項后,我現在提取垂直和水平水印但不是對角線。到目前為止,這是我的代碼。
class AngleCollector extends PDFTextStripper {
private final Set<Integer> angles = new TreeSet<>();
AngleCollector() throws IOException {}
Set<Integer> getAngles() {
return angles;
}
@Override
protected void processTextPosition(TextPosition text) {
int angle = ExtractText.getAngle(text);
angle = (angle 360) % 360;
angles.add(angle);
}
}
class FilteredTextStripper extends PDFTextStripper {
FilteredTextStripper() throws IOException {
}
@Override
protected void processTextPosition(TextPosition text) {
int angle = ExtractText.getAngle(text);
if (angle == 0) {
super.processTextPosition(text);
}
}
}
final class ExtractText {
static int getAngle(TextPosition text) {
//The Matrix containing the starting text position
Matrix m = text.getTextMatrix().clone();
m.concatenate(text.getFont().getFontMatrix());
return (int) Math.round(Math.toDegrees(Math.atan2(m.getShearY(), m.getScaleY())));
}
private List<String> getAnnots(PDPage page) throws IOException {
List<String> returnList = new ArrayList<>();
for (PDAnnotation pdAnnot : page.getAnnotations()) {
if(pdAnnot.getContents() != null && !pdAnnot.getContents().isEmpty()) {
returnList.add(pdAnnot.getContents());
}
}
return returnList;
}
public void extractPages(int startPage, int endPage, PDFTextStripper stripper, PDDocument document, Writer output) {
for (int p = startPage; p <= endPage; p) {
stripper.setStartPage(p);
stripper.setEndPage(p);
try {
PDPage page = document.getPage(p - 1);
for (var annot : getAnnots(page)) {
output.write(annot);
}
int rotation = page.getRotation();
page.setRotation(0);
var angleCollector = new AngleCollector();
angleCollector.setStartPage(p);
angleCollector.setEndPage(p);
angleCollector.writeText(document, output);
for (int angle : angleCollector.getAngles()) {
// prepend a transformation
try (var cs = new PDPageContentStream(document, page,
PDPageContentStream.AppendMode.PREPEND, false)) {
cs.transform(Matrix.getRotateInstance(-Math.toRadians(angle), 0, 0));
}
stripper.writeText(document, output);
// remove prepended transformation
((COSArray) page.getCOSObject().getItem(COSName.CONTENTS)).remove(0);
}
page.setRotation(rotation);
} catch (IOException ex) {
System.err.println("Failed to process page " p ex);
}
}
}
}
public class pdfTest {
private pdfTest() {
}
public static void main(String[] args) throws IOException {
var pdfFile = "test-resources/pdf/pdf_sample_2.pdf";
Writer output = new OutputStreamWriter(System.out, StandardCharsets.UTF_8);
var etObj = new ExtractText();
var rawDoc = PDDocument.load(new File(pdfFile));
PDFTextStripper stripper = new FilteredTextStripper();
if(rawDoc.getDocumentCatalog().getAcroForm() != null) {
rawDoc.getDocumentCatalog().getAcroForm().flatten();
}
etObj.extractPages(1, rawDoc.getNumberOfPages(), stripper, rawDoc, output);
output.flush();
}
}
編輯 1: 我也無法通過具有正確 Alignment 的TextExtractor 代碼檢測表單(Acro、XFA)欄位內容。我怎樣才能做到這一點 ?
我附上示例 PDF 以供參考。 示例 PDF 1 示例 PDF 2
我需要使用 PDFBox 執行以下操作
- 對角線文本檢測。(包括水印)。
- 通過保持正確對齊來提取表單欄位。
uj5u.com熱心網友回復:
在您的“問題”中,您實際上會問多個不同的問題。我會仔細研究它們中的每一個。答案可能沒有您希望的那么具體,因為您的問題基于并非全部正確的假設。
“如何使用 PDFBox 從 PDF 中提取對角線水印文本?”
首先,PDF 文本提取的作業原理是檢查頁面內容流中包含的 XObjects指令,在其中查找文本繪制指令,獲取坐標和方向及其字串引數,將字串映射到 Unicode,并排列許多單獨的Unicode 字串按其在單個內容字串中的坐標和方向。
在 PDFBox 的情況下,按PDFTextStripper
原樣執行此操作,對方向處理的支持有限,但它可以擴展為按方向過濾文本片段以獲得更好的方向支持,如激活旋轉魔法的ExtractText
示例所示。
雙水印.pdf
double_watermark.pdf
但是,在您的示例 PDF 的情況下,正如 Tilman 已經指出的那樣,對角線文本“絕密”不是使用文本繪制說明創建的,而是使用路徑構建和繪制說明創建的。(實際上這里的路徑都是非常短的線序列,沒有使用曲線,使用高縮放系數可以看到。)因此,PDF文本提取無法提取此文本。
回答你的問題
如何使用 PDFBox 從 PDF 中提取對角線水印文本?
在這種情況下,因此:你不能。
(當然,您可以使用 PDFBox 作為 PDF 處理框架,您也可以在此基礎上收集路徑并嘗試將它們與字符匹配,但它本身就是一個更大的專案。或者您可以使用 PDFBox 將頁面繪制為位圖并應用 OCR到那些位圖。)
“我也無法通過具有正確對齊的 TextExtractor 代碼檢測表單(Acro、XFA)欄位內容。我該怎么做?”
AcroForm 或 XFA 表單定義中的表單資料不是頁面內容流或從中參考的 XObject 內容流的一部分。因此,它們不會立即受到文本提取的影響。
AcroForm 表格
AcroForm 表單域是抽象的 PDF 資料物件,可能有也可能沒有相關的內容流用于顯示。要將它們包含到文本提取操作的內容流中,您可以先展平表單。正如您在自己的回答中提到的,您還必須激活排序以在背景關系中提取欄位內容。
請注意,PDF 渲染器在創建表單域的可視化時確實有一定的自由度。因此,文本提取順序可能與您期望的略有不同。
XFA 表格
XFA 表單定義是 PDF 中的布谷鳥蛋。它們是與常規 PDF 物件無關的 XML 流;此外,多年前,PDF 中的 XFA 已被棄用。因此,大多數 PDF 庫不支持 XFA 表單。
PDFBox 只允許提取或替換 XFA XML 流。因此,在文本提取期間沒有立即支持 XFA 表單內容。
uj5u.com熱心網友回復:
通過保持正確對齊來提取表單欄位。
這是通過setSortByPosition解決的
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/377363.html