Jokainen geometrinen tekstiuuttaja arvaa. Se lukee glyfit, jotka sivu piirtää, lajittelee ne perusviivan ja vaakasuoran sijainnin mukaan ja toivoo visuaalisen asettelun vastaavan sitä järjestystä, jossa ihminen lukisi. Yhden palstan raportissa se arvaus on oikein. Kaksipalstaisessa aikakauslehtiartikkelissa, sivupalkin sisältävässä lomakkeessa tai taulukossa, jonka solut emittoitiin palsta kerrallaan, se on väärin tavalla, jota on vaikea huomata ja joka on kallis havaita alavirrassa. HotPDF vastaa tähän funktiolla ExtractLoadedPageStructureText, joka ohittaa geometrian kokonaan: se kulkee dokumentin rakennepuun läpi luontijärjestyksessä, niin kuin ISO 32000-1 §14.8.4 määrittelee, ja kokoaa sitten sivun glyfit niiden marked-content-tunnisteen mukaan. Tagatulle PDF:lle tuo ei ole heuristiikka, se on järjestys, jonka tuottava sovellus ilmoitti
Funktio palauttaa arvon False, kun sivulla ei ole käytettävissä olevaa rakennepuuta, mikä on merkki varata geometriseen uuttajaan epäonnistumisen sijaan. Kaksipolkinen suunnittelu merkitsee enemmän kuin algoritmi: todellinen dokumenttien saanti näkee tagatut viranomaislomakkeet ja skannerin tuotoksen samassa kansiossa, eikä putki, joka käsittelee vain toista niistä, ole putki
Miksi geometrinen uutto saa lukujärjestyksen väärin?
Koska PDF-sisältövirta ei kanna lukujärjestystä lainkaan. Se on piirto-operaattorien jono, ja tuottaja voi vapaasti emitoida ne siinä jonossa, mikä sopii sen omalle asettelukoneelle. Tekstinkäsittelyohjelmat emittoivat yleensä virtajärjestyksessä ja geometrinen lajittelu näyttää hyvältä. Asettelutyökalut, lomakesuunnittelijat ja raporttigeneraattorit eivät useinkaan: sivun alatunniste voidaan emittoida rungon ennen, taulukko voidaan täyttää palstapääjärjestyksessä, ja kaksipalstainen sivu voi lomittaa rivejä molemmista palstoista, koska sommitteli ratkaisi ne yhdessä
Vikamuoto on hiljainen. Geometrinen uuttaja ei koskaan raportoi virhettä, se vain palauttaa proosaa, jonka lauseet on lomitettu kahdesta palstasta. Mikä tahansa kyseistä tekstiä kuluttava, hakemisto, sähköisen laskun kenttäkartoittaja tai kielimalliin ruokkiva hakuputki, perii vaurion ilman varoitusta. HotPDF toimittaa myös geometriset uuttajat ladatuille dokumenteille, ja ne pysyvät oikeana työkaluna tagaamattomille tiedostoille; rakenteen järjestyksen polun pointti on lopettaa arvaaminen, kun dokumentti jo kantaa vastauksen
Mitä rakennepuu oikeasti tallentaa
Tagattu PDF pitää sisällään toisen, rinnakkaisen kuvauksen sivusta. Luettelo osoittaa kohteeseen /StructTreeRoot, jonka /K-lapset muodostavat rakenne-elementtien puun: /Document, /Sect, /P, /Table, /TR, /TD ja niin edelleen. Tuon puun lehdet ovat marked-content-viittauksia, kokonaislukuja, jotka nimeävät sivun sisältövirran jakson. Sisältöpuolella kyseiset jaksot avataan BDC-operaattorilla, joka kantaa arvon /MCID, ja suljetaan operaattorilla EMC. Jokainen rakenne-elementti kantaa myös /Pg-merkinnän, joka nimeää sivun, johon se kuuluu, ja se tekee sivukohtaisen läpikäynnin mahdolliseksi dokumentissa, jonka rakennepuu ulottuu sadoille sivuille
HotPDF käy kyseisen puun läpi 128 tason syvyyskatolla ja suodattaa arvon /Pg mukaan niin, että vain nykyinen sivu osallistuu. Läpikäynnin tuloste ei ole tekstiä, se on järjestetty luettelo MCID-arvoista: marked-content-jaksojen luontijärjestys tällä sivulla. Tekstin kokoaminen on sitten kyse siitä, että glyfit toistetaan tuossa järjestyksessä
MCID tallennetaan glyfiuuton aikana, ei etsitä jälkikäteen
Tämä on se toteutuksen yksityiskohta, joka tekee ominaisuudesta halvan. HotPDF tallentaa jo aktiivisen marked-content-tunnisteen jokaiseen uuttamaansa glyfiin, kohteeseen THPDFGlyphRecordin MCID-kenttään, koska sisältövirran tulkki tietää, mikä BDC-vaikutusalue on auki sillä hetkellä, kun se käsittelee jokaisen Tj- tai TJ-operaattorin. Rakenteen järjestyksen uutto ei siksi tarvitse toista läpikäyntiä sisältövirran yllä. Se kerää MCID-jonon rakennepuusta, bucketoi jo uutetut glyfit MCID:n mukaan ja emittoi ne tuossa jonossa
var
Pdf: THotPDF;
PageCount, I, Untagged: Integer;
PageText, AllText: UnicodeString;
Report: TStrings; // kutsujan omistama diagnostiikkavastaanotto
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
// Luontijärjestys suoraan rakennepuusta
if Untagged > 0 then
Report.Add(Format('page %d: %d glyphs outside the structure tree',
[I, Untagged]));
end
else
// Ei käytettävissä olevaa rakennepuuta tällä sivulla: geometrinen varatie
Pdf.ExtractLoadedPageText(I, PageText);
AllText := AllText + PageText + #13#10;
end;
finally
Pdf.Free;
end;
end;
Tagaamattomat glyfit lasketaan, ei koskaan pudoteta hiljaa
Sivu voi olla osittain tagattu. Tuottajat lisäävät koristeellisen viivan, sivunumeron tai myöhäisvaiheen vesileiman minkä tahansa BDC-vaikutusalueen ulkopuolelle, ja ne glyfit eivät kuulu mihinkään MCID:hen. Niiden pudottaminen olisi siisti toteutus ja väärä, koska sama aukko ilmestyy myös silloin, kun tuottaja tagaa rungon mutta unohtaa taulukon, ja menettäisit taulukon huomaamatta
HotPDF liittää vaatimattomat glyfit geometrisenä häntänä rakenteen järjestyksessä olevan tekstin jälkeen ja raportoi niiden lukumäärän UntaggedGlyphCount-tulostusparametrin kautta. Tuo luku on laatusignaali, johon voi reagoida. Kourallinen glyfejä kahdentuhannen sivulla on sivukalusteita ja voidaan ohittaa. Neljäkymmentä prosenttia sivusta rakennepuun ulkopuolella tarkoittaa, että taggaus on koristeellista ja geometrinen uuttaja on rehellisempi vastaus kyseiselle tiedostolle
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);
// Luota rakennepuuhun vain, kun se vaatii suurimman osan sivusta
if (TotalGlyphs = 0) or (Untagged * 4 <= TotalGlyphs) then
begin
UsedStructure := True;
Result := True;
Exit;
end;
end;
Result := Pdf.ExtractLoadedPageText(PageIndex, AText);
end;
Mikä saa funktion palauttamaan arvon False
Kolme tapausta, ja ne kannattaa erottaa, koska vain yksi niistä on vika dokumentissa. Ensimmäinen on tavallinen tagaamaton PDF: ei /StructTreeRootia, ei mitään kuljettavaa, ja arvo False on yksinkertaisesti totuus. Toinen on skannattu sivu, jonka teksti tulee OCR-kerroksesta, jota ei koskaan tagattu. Kolmas on kiinnostava: sisältö, joka kantaa BDC-operaattoreita arvoilla /MCID, mutta jonka sivulla ei ole /StructParents-merkintää ja jonka rakennepuu ei koskaan viittaa kyseisiin tunnisteisiin. Marked content on olemassa, rakennepuoli ei ole, eikä ole järjestystä palautettavana. HotPDF raportoi arvon False sen keksimisen sijaan
Tuo viimeinen tapaus ilmestyy käsin muokattuihin tiedostoihin ja työkalujen tuotoksiin, jotka emittoivat marked contentia valinnaista sisältöä tai artefaktia varten rakennepuuta rakentamatta. Jos tuotat itse tagattuja PDF:itä, sama epäsymmetria on se, mitä PDF/UA-validointi tarkistaa, ja kirjoittajapuolen vastine käsitellään artikkelissa asettelu-DOM, joka emittoi tagattua, sivutettua tulostetta
Missä rakenteen järjestys maksaa itsensä takaisin
Saavutettavuuden auditointi on ilmeinen: jos sertifioit dokumenttia vasten PDF/UA:ta, näytönlukijan ilmoittama lukujärjestys on täsmälleen rakenteen järjestys, joten sen uuttaminen on tapa tarkistaa se ilman näytönlukijaa. Tiedonkeruu on suurempi kaupallinen tapaus. Tagatut viranomaislomakkeet, säännellyt julkistukset ja sähköisen laskun liitteet kantavat kenttäotsikoita ja arvoja ilmoitetussa järjestyksessä, ja niiden lukeminen tuossa järjestyksessä poistaa kokonaisen luokan kartoitusvirheitä, joita geometrinen uutto luo monipalstaisiin asetteluihin
Uusin kuluttaja on kielimallien haku. Dokumentin pilkkominen upotuksia varten on vain niin hyvä kuin tekstijärjestys, ja palanen, joka lomittaa kaksi palstaa, tuottaa lauseita, joita ei koskaan ollut olemassa. Rakenteen järjestyksen uutto on saatavilla olevista korjauksista halvin, koska tagatuille dokumenteille oikea järjestys on jo tiedostossa, sen lukeminen riittää
HotPDF on natiivi VCL-komponentti Delphille ja C++Builderille, joten sekä rakennepuun läpikäynti että glyfien toisto toimivat prosessinsisäisesti ladattua dokumenttia vastaan ilman ulkoista renderöijää. Täydet API-yksityiskohdat ladatun dokumentin uuttoperheestä ovat HotPDF Delphi PDF -komponentin tuotesivulla