Setiap ekstraktor teks geometris sedang menebak. Ia membaca glyph yang digambar sebuah halaman, mengurutkannya berdasarkan baseline dan posisi horizontal, dan berharap susunan visualnya cocok dengan urutan yang dibaca manusia. Pada laporan satu kolom tebakan itu benar. Pada artikel jurnal dua kolom, form dengan sidebar, atau tabel yang selnya dipancarkan kolom demi kolom, tebakannya keliru dengan cara yang sulit disadari dan mahal ditemukan di hilir. HotPDF menjawabnya dengan ExtractLoadedPageStructureText, yang mengabaikan geometri sepenuhnya: ia menelusuri pohon struktur dokumen dalam urutan penulisan sebagaimana didefinisikan ISO 32000-1 §14.8.4, lalu menyusun ulang glyph halaman berdasarkan marked-content identifier-nya. Untuk PDF bertag itu bukan heuristik, melainkan urutan yang dideklarasikan aplikasi pembuatnya
Fungsi itu mengembalikan False ketika halaman tidak punya pohon struktur yang dapat dipakai, yang merupakan sinyal untuk jatuh kembali ke ekstraktor geometris alih-alih gagal. Desain dua jalur itu lebih penting daripada algoritmanya: intake dokumen nyata melihat form pemerintahan bertag dan output pemindai di folder yang sama, dan pipeline yang hanya menangani salah satunya bukanlah pipeline
Mengapa ekstraksi geometris mendapat urutan baca yang keliru?
Karena content stream PDF tidak membawa urutan baca sama sekali. Ia adalah rangkaian operator menggambar, dan produsen bebas memancarkannya dalam urutan apa pun yang cocok dengan layout engine-nya sendiri. Word processor biasanya memancarkan dalam urutan aliran dan pengurutan geometris tampak baik. Layout tool, perancang form, dan generator laporan sering kali tidak: footer halaman bisa dipancarkan sebelum badan, tabel bisa diisi column-major, dan halaman dua kolom bisa menyilangkan baris dari kedua kolom karena composer menyelesaikannya bersamaan
Mode kegagalannya senyap. Ekstraktor geometris tidak pernah melaporkan error, ia sekadar menyerahkan kembali prosa yang kalimat-kalimatnya disambung dari dua kolom. Apa pun yang mengonsumsi teks itu, indeks pencarian, mapper field e-invoice, pipeline retrieval yang memberi makan model bahasa, mewarisi kerusakannya tanpa peringatan. HotPDF juga mengirim ekstraktor geometris untuk dokumen yang dimuat, dan keduanya tetap menjadi alat yang tepat untuk berkas tanpa tag; inti jalur urutan struktur adalah berhenti menebak ketika dokumen sudah membawa jawabannya
Apa yang sebenarnya disimpan pohon struktur
PDF bertag menyimpan deskripsi kedua yang paralel tentang halaman. Katalog menunjuk ke /StructTreeRoot, yang anak-anak /K-nya membentuk pohon elemen struktur: /Document, /Sect, /P, /Table, /TR, /TD, dan seterusnya. Daun-daun pohon itu adalah referensi marked-content, integer yang menamai satu rentang content stream halaman. Di sisi konten, rentang-rentang itu dibuka dengan operator BDC yang membawa /MCID dan ditutup dengan EMC. Setiap elemen struktur juga membawa entri /Pg yang menamai halaman tempatnya berada, dan itulah yang membuat penelusuran per halaman mungkin pada dokumen yang pohon strukturnya membentang ratusan halaman
HotPDF menelusuri pohon itu dengan batas kedalaman 128 level dan menyaring pada /Pg sehingga hanya halaman saat ini yang berkontribusi. Output penelusuran itu bukan teks, melainkan daftar nilai MCID yang terurut: urutan penulisan rentang marked-content pada halaman ini. Menyusun ulang teks kemudian tinggal memutar ulang glyph dalam urutan itu
MCID dicatat saat ekstraksi glyph, bukan dicari setelahnya
Inilah detail implementasi yang membuat fitur ini murah. HotPDF sudah mencatat marked-content identifier aktif pada setiap glyph yang diekstraknya, di field MCID dari THPDFGlyphRecord, karena interpreter content stream tahu scope BDC mana yang terbuka pada saat ia memproses setiap operator Tj atau TJ. Ekstraksi urutan struktur karenanya tidak membutuhkan lintasan kedua atas content stream. Ia mengumpulkan urutan MCID dari pohon struktur, lalu membucketkan glyph yang sudah diekstrak berdasarkan MCID dan memancarkannya dalam urutan itu
var
Pdf: THotPDF;
PageCount, I, Untagged: Integer;
PageText, AllText: UnicodeString;
Report: TStrings; // penampung diagnostik milik caller
begin
Pdf := THotPDF.Create(nil);
try
PageCount := Pdf.LoadFromFile('accessible-form.pdf');
AllText := '';
for I := 0 to PageCount - 1 do
begin
if Pdf.ExtractLoadedPageStructureText(I, PageText, Untagged) then
begin
// Urutan penulisan langsung dari pohon struktur
if Untagged > 0 then
Report.Add(Format('page %d: %d glyphs outside the structure tree',
[I, Untagged]));
end
else
// Tidak ada pohon struktur yang dapat dipakai di halaman ini: fallback geometris
Pdf.ExtractLoadedPageText(I, PageText);
AllText := AllText + PageText + #13#10;
end;
finally
Pdf.Free;
end;
end;
Glyph tanpa tag dihitung, tidak pernah dibuang diam-diam
Sebuah halaman bisa bertag sebagian. Produsen menambahkan garis dekoratif, nomor halaman, atau watermark tahap akhir di luar scope BDC mana pun, dan glyph-glyph itu tidak milik MCID mana pun. Membuangnya adalah implementasi yang rapi dan yang keliru, karena celah yang sama juga muncul ketika produsen menandai badan tetapi lupa tabelnya, dan Anda akan kehilangan tabelnya tanpa menyadarinya
HotPDF menambahkan glyph tak terklaim sebagai ekor geometris setelah teks terurut struktur dan melaporkan jumlahnya melalui parameter output UntaggedGlyphCount. Angka itu adalah sinyal kualitas yang bisa Anda tindaklanjuti. Segelintir glyph pada halaman berisi dua ribu adalah furnitur halaman dan bisa diabaikan. Empat puluh persen halaman di luar pohon struktur berarti penandaiannya dekoratif dan ekstraktor geometris adalah jawaban yang lebih jujur untuk berkas itu
function ExtractPageBestEffort(Pdf: THotPDF; PageIndex: Integer;
out AText: UnicodeString; out UsedStructure: Boolean): Boolean;
var
Untagged, TotalGlyphs: Integer;
Glyphs: THPDFGlyphArray;
begin
UsedStructure := False;
if Pdf.ExtractLoadedPageStructureText(PageIndex, AText, Untagged) then
begin
TotalGlyphs := 0;
if Pdf.ExtractLoadedPageGlyphs(PageIndex, Glyphs) then
TotalGlyphs := Length(Glyphs);
// Percayai pohon struktur hanya ketika ia mengklaim sebagian besar halaman
if (TotalGlyphs = 0) or (Untagged * 4 <= TotalGlyphs) then
begin
UsedStructure := True;
Result := True;
Exit;
end;
end;
Result := Pdf.ExtractLoadedPageText(PageIndex, AText);
end;
Apa yang membuat fungsi mengembalikan False
Tiga kasus, dan ketiganya layak dibedakan karena hanya satu yang merupakan defek pada dokumen. Yang pertama adalah PDF tanpa tag biasa: tanpa /StructTreeRoot, tidak ada yang ditelusuri, dan False sekadar kebenarannya. Yang kedua adalah halaman hasil pindai yang teksnya datang dari lapisan OCR yang tidak pernah ditandai. Yang ketiga adalah yang menarik: konten yang membawa operator BDC dengan nilai /MCID tetapi halamannya tidak punya entri /StructParents dan pohon strukturnya tidak pernah merujuk identifier-identifier itu. Marked content-nya ada, sisi strukturnya tidak, dan tidak ada urutan untuk dipulihkan. HotPDF melaporkan False alih-alih mengarang satu
Kasus terakhir itu muncul di berkas yang disunting tangan dan di output dari tool yang memancarkan marked content untuk keperluan optional-content atau artifact tanpa membangun pohon struktur. Jika Anda sendiri memproduksi PDF bertag, asimetri yang sama adalah yang diperiksa oleh validasi PDF/UA, dan padanan sisi penulisnya dibahas dalam layout DOM yang memancarkan output bertag berhalaman
Di mana urutan struktur membayar dirinya sendiri
Audit aksesibilitas adalah yang paling jelas: jika Anda mensertifikasi dokumen terhadap PDF/UA, urutan baca yang akan diumumkan screen reader persis adalah urutan struktur, sehingga mengekstraknya adalah cara Anda meninjaunya tanpa screen reader. Penangkapan data adalah kasus komersial yang lebih besar. Form pemerintahan bertag, pengungkapan yang diatur, dan lampiran e-invoice membawa label dan nilai field dalam urutan yang dideklarasikan, dan membacanya dalam urutan itu menghapus satu kelas utuh bug pemetaan yang diciptakan ekstraksi geometris pada layout multi-kolom
Konsumen terbaru adalah retrieval untuk model bahasa. Chunking dokumen untuk embedding hanya sebaik urutan teksnya, dan chunk yang menyambung dua kolom menghasilkan kalimat yang tidak pernah ada. Ekstraksi urutan struktur adalah perbaikan termurah yang tersedia untuk itu, karena untuk dokumen bertag urutan yang benar sudah ada di berkas dan hanya perlu dibaca
HotPDF adalah komponen VCL native untuk Delphi dan C++Builder, sehingga penelusuran pohon struktur dan pemutaran ulang glyph sama-sama berjalan in-process terhadap dokumen yang dimuat tanpa renderer eksternal yang terlibat. Detail API lengkap untuk keluarga ekstraksi dokumen yang dimuat ada di halaman produk HotPDF Delphi PDF component