Teknik Makale

HotPDF ile Delphi'de Yapı Sırasına Göre PDF Metni Çıkarma

Her geometrik metin çıkarıcı tahmin yürütür. Bir sayfanın çizdiği glifleri okur, bunları taban çizgisine ve yatay konuma göre sıralar ve görsel dizilimin bir insanın okuyacağı sırayla örtüşmesini umar. Tek sütunlu bir raporda o tahmin doğrudur. İki sütunlu bir dergi makalesinde, yan sütunu olan bir formda ya da hücreleri sütun sütun yazılmış bir tabloda yanlıştır; fark etmesi zor, aşağı akışta keşfetmesi pahalı biçimlerde. HotPDF buna ExtractLoadedPageStructureText ile cevap verir; geometriyi tümüyle yok sayar: ISO 32000-1 §14.8.4'te tanımlandığı gibi belge yapı ağacını yazar sırasında yürür, sonra sayfa gliflerini işaretli içerik tanımlayıcılarına göre yeniden birleştirir. Etiketli bir PDF için bu bir sezgi değildir; üreten uygulamanın beyan ettiği sıradır

İşlev, sayfanın kullanılabilir bir yapı ağacı olmadığında False döndürür; bu da başarısız olmak yerine geometrik çıkarıcıya geri düşme sinyalidir. İki yollu o tasarım algoritmadan daha önemlidir: gerçek belge kabulü, aynı klasörde etiketli kamu formlarını ve tarayıcı çıktısını görür ve yalnızca birini ele alan bir hat, hat değildir

Geometrik çıkarma okuma sırasını neden yanlış alır?

Çünkü bir PDF içerik akışı hiç okuma sırası taşımaz. Çizim operatörlerinden oluşan bir dizidir ve üretici, kendi sayfa düzeni motoruna uygun herhangi bir sırayla yaymakta serbesttir. Kelime işlemciler genellikle akış sırasında yayar ve geometrik sıralama iyi görünür. Düzen araçları, form tasarımcıları ve rapor üreticileri sık sık öyle yapmaz: sayfa altbilisi gövdeden önce yayılabilir, bir tablo sütun öncelikli doldurulabilir ve iki sütunlu bir sayfa, iki sütundan gelen satırları iç içe geçirebilir; çünkü düzenleyici onları birlikte çözmüştür

İki sütunlu PDF sayfası karşılaştırması; taban çizgisiyle sıralanan geometrik çıkarmanın sütunları birleştirişini HotPDF'deki yapı sırası MCID çıkarmasıyla yan yana koyar
Glifleri taban çizgisine göre sıralamak iki sütunu anlamsızlığa iç içe geçirir; yapı ağacı ise üreticinin beyan ettiği sırayı yeniden oynatır

Hata modu sessizdir. Geometrik bir çıkarıcı asla hata bildirmez; cümleleri iki sütundan eklenmiş düzyazıyı geri verir. O metni tüketen her şey —bir arama dizini, bir e-fatura alan eşleyici, bir dil modelini besleyen erişim hattı— uyarısız hasarı miras alır. HotPDF ayrıca yüklenen belgeler için geometrik çıkarıcıları da gönderir ve bunlar etiketsiz dosyalar için doğru araç olmaya devam eder; yapı sırası yolunun amacı, belge cevabı zaten taşıyorken tahmin etmeyi bırakmaktır

Yapı ağacı gerçekte neyi saklar

Etiketli bir PDF, sayfanın ikinci, paralel bir betimlemesini taşır. Katalog, /StructTreeRoot işaret eder; onun /K çocukları bir yapı elemanları ağacı oluşturur: /Document, /Sect, /P, /Table, /TR, /TD ve devamı. O ağacın yaprakları, sayfa içerik akışının bir aralığını adlandıran işaretli içerik referanslarıdır, yani tamsayılardır. İçerik tarafında o aralıklar, /MCID taşıyan bir BDC operatörüyle açılır ve EMC ile kapanır. Her yapı elemanı ayrıca ait olduğu sayfayı adlandıran bir /Pg girdisi taşır; yapı ağacı yüzlerce sayfaya yayılan bir belgede sayfa başına yürüyüşü mümkün kılan budur

PDF yapı ağacı anatomisi; Sect, Table, TR ve TD gibi StructTreeRoot elemanlarını HotPDF sayfa içerik akışındaki BDC MCID aralıklarına bağlar
Ağacın yaprakları işaretli içerik referanslarıdır ve her eleman, yürüyüşün geçerli sayfaya filtrelemesini sağlayan bir Pg girdisi taşır

HotPDF o ağacı 128 düzeylik bir derinlik sınırıyla dolaşır ve /Pg üzerinde filtreler, böylece yalnızca geçerli sayfa katkı verir. Yürüyüşün çıktısı metin değildir; sıralı bir MCID değerleri listesidir: bu sayfadaki işaretli içerik aralıklarının yazar sırası. Metni yeniden birleştirmek bundan sonra glifleri o sırayla yeniden oynatmaktan ibarettir

MCID, glif çıkarma sırasında kaydedilir, sonradan aranmaz

Bu, özelliği ucuz kılan uygulama ayrıntısıdır. HotPDF, çıkardığı her glifin üzerinde etkin işaretli içerik tanımlayıcısını zaten kaydeder; THPDFGlyphRecord türünün MCID alanında, çünkü içerik akışı yorumlayıcısı her Tj ya da TJ operatörünü işlediği anda hangi BDC kapsamının açık olduğunu bilir. Yapı sırası çıkarma bu nedenle içerik akışı üzerinde ikinci bir geçiş gerektirmez. MCID dizisini yapı ağacından toplar, sonra zaten çıkarılmış glifleri MCID ile gruplar ve o dizide yayar

var
  Pdf: THotPDF;
  PageCount, I, Untagged: Integer;
  PageText, AllText: UnicodeString;
  Report: TStrings;   // çağıranın sahiplendiği tanılama çıkışı
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
        // Doğrudan yapı ağacından yazar sırası
        if Untagged > 0 then
          Report.Add(Format('page %d: %d glyphs outside the structure tree',
            [I, Untagged]));
      end
      else
        // Bu sayfada kullanılabilir yapı ağacı yok: geometrik geri düşme
        Pdf.ExtractLoadedPageText(I, PageText);
      AllText := AllText + PageText + #13#10;
    end;
  finally
    Pdf.Free;
  end;
end;

Etiketsiz glifler sayılır, asla sessizce atılmaz

Bir sayfa kısmen etiketli olabilir. Üreticiler dekoratif bir çizgiyi, bir sayfa numarasını ya da sonradan eklenmiş bir filigranı herhangi bir BDC kapsamının dışına ekler ve o glifler hiçbir MCID'ye ait değildir. Onları atmak derli toplu uygulama olurdu ve yanlış olan da budur; çünkü aynı boşluk, bir üretici gövdeyi etiketleyip tabloyu unuttuğunda da belirir ve tabloyu fark etmeden kaybederdiniz

HotPDF, sahipsiz glifleri yapı sıralı metinden sonra geometrik bir kuyruk olarak ekler ve sayılarını UntaggedGlyphCount çıkış parametresiyle bildirir. O sayı, harekete geçebileceğiniz bir kalite sinyalidir. İki binlik bir sayfadaki bir avuç glif sayfa süsüdür ve yok sayılabilir. Sayfanın yüzde kırkının yapı ağacının dışında olması, etiketlemenin dekoratif olduğu ve o dosya için daha dürüst cevabın geometrik çıkarıcı olduğu anlamına gelir

HotPDF yapı metni çıkarması için karar akışı; sayfada kullanılabilir yapı ağacı ya da dekoratif etiketleme olmadığında geometrik geri düşme
True, etiketsiz kuyruk eklenmiş yapı sırası demektir; False ise sayfayı başarısız olmak yerine geometrik çıkarıcıya yönlendirir
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);
    // Yapı ağacına yalnızca sayfanın çoğunu kapsadığını iddia ettiğinde güven
    if (TotalGlyphs = 0) or (Untagged * 4 <= TotalGlyphs) then
    begin
      UsedStructure := True;
      Result := True;
      Exit;
    end;
  end;
  Result := Pdf.ExtractLoadedPageText(PageIndex, AText);
end;

İşlevi False döndüren şey

Üç durum ve ayırt etmeye değerler, çünkü yalnızca biri belgedeki bir kusurdur. İlki sıradan bir etiketsiz PDF'tir: /StructTreeRoot yoktur, yürünecek bir şey yoktur ve False yalnızca gerçektir. İkincisi, metni hiç etiketlenmemiş bir OCR katmanından gelen taranmış bir sayfadır. Üçüncüsü ilginç olandır: /MCID değerli BDC operatörleri taşıyan ama sayfasında /StructParents girdisi bulunmayan ve yapı ağacının o tanımlayıcılara hiç atıf yapmadığı içerik. İşaretli içerik vardır, yapı tarafı yoktur ve geri kazanılacak bir sıra yoktur. HotPDF bir sıra icat etmek yerine False bildirir

Son durum, elle düzenlenmiş dosyalarda ve yapı ağacı kurmadan isteğe bağlı içerik ya da artifact amaçlarıyla işaretli içerik yayan araçların çıktısında görülür. Kendiniz etiketli PDF üretiyorsanız aynı asimetri, PDF/UA doğrulamasının denetlediği şeydir; yazıcı tarafındaki karşılığı ise etiketli, sayfalanmış çıktı yayınlayan düzen DOM'unda kapsanır

Yapı sırasının kendini ödediği yerler

Erişilebilirlik denetimi bariz olandır: bir belgeyi PDF/UA'ya göre sertifikalandırıyorsanız bir ekran okuyucunun duyuracağı okuma sırası tam olarak yapı sırasıdır; dolayısıyla onu çıkarmak, ekran okuyucusuz gözden geçirmenin yoludur. Veri yakalama daha büyük ticari durumdur. Etiketli kamu formları, düzenlenmiş açıklamalar ve e-fatura ekleri alan etiketlerini ve değerlerini beyan edilen sırada taşır ve onları o sırada okumak, geometrik çıkarmanın çok sütunlu düzenlerde ürettiği bir sınıf eşleme hatasının tamamını kaldırır

En yeni tüketici, dil modelleri için erişimdir. Bir belgeyi gömme için parçalara ayırmak, ancak metin sırası kadar iyidir ve iki sütunu ekleyen bir parça hiç var olmamış cümleler üretir. Yapı sırası çıkarma bunun için bulunabilecek en ucuz düzeltmedir; çünkü etiketli belgelerde doğru sıra zaten dosyanın içindedir ve yalnızca okunmaya muhtaçtır

HotPDF, Delphi ve C++Builder için yerel bir VCL bileşenidir; dolayısıyla yapı ağacı yürüyüşü de glif yeniden oynatması da, harici bir çizici devrede olmadan yüklenmiş bir belgeye karşı işlem içinde çalışır. Yüklenen belge çıkarma ailesinin API ayrıntılarının tamamı HotPDF Delphi PDF component ürün sayfasındadır