Tekninen artikkeli

HotPDF OCR-tekstitason siirtymä: kartoitus CropBoxin läpi

OCR-tekstitasot, viivakoodirajat ja kasvojen mustauslaatikot ajautuvat sivuiltaan rajatuilla PDF-sivuilla, kun bittikarttapikselit kartoitetaan takaisin MediaBoxin kautta sen sijaan, että käyttäisi laatikkoa, jonka renderöijä oikeasti rasteroi: CropBoxia, leikattuna MediaBoxiin (ISO 32000-1 §14.11.2). HotPDF korjasi tämän funktiolle ApplyLoadedOCRTextLayer versiossa v2.770.153 sekä funktioille DecodeLoadedPageBarcodes ja DetectLoadedRedactionFindings versiossa v2.770.154

Bugiraportti, joka yleensä saapuu, näyttää tältä. Skannattu sopimusarkisto käy läpi OCR:n, tuotos on haettava, ja hakutulos lauseen numerolle korostuu puoli tuumaa alle ja vasemmalle painetusta numerosta. Useimmat erän tiedostot ovat kunnossa. Rikkinäiset tulivat kaikkea yhdestä skannausasemasta, joka kirjoittaa /CropBoxin rajaamaan skannerin lasipöydän marginaalin. Yksityiskohta erottaa toisistaan kuvan, jonka OCR-moottori näki, ja kehyksen, johon tekstitaso sijoitettiin, ja sama ristiriita siirtää viivakoodirajoja ja, vakavammin, kasvojen mustauslaatikoita

Miksi OCR-tekstitaso ajautuu pois skannatuista sanoista?

Tekstitaso ajautuu sivuiltaan, koska putken kaksi puoliskoa olivat eri mieltä siitä, minkä suorakulmion bittikartta kattaa. Versiossa v2.766.64 HotPDF muutti renderöinnin, SVG-viennin, katseluohjelman ja tulostuksen kunnioittamaan CropBoxia: sivu näytetään sen CropBoxin kautta, leikattuna sen MediaBoxiin, mikä on se, minkä ISO 32000-1 §14.11.2 määrää, ja GetLoadedPageVisibleBox lisättiin palauttamaan kyseinen näkyvä laatikko. Tunnistusominaisuudet rakensivat yhä laite–sivu-muunnoksensa funktiosta GetLoadedPageBox(PageIndex, pbMediaBox, ...). Rasteri kattoi nyt näkyvän laatikon, muunnos oletti yhä MediaBoxin, ja jokainen tunnistettu sijainti palautui siirtymänä kahden välin verran

Vaurioitunut ikkuna on siksi täsmällinen. ApplyLoadedOCRTextLayer sijoitti tekstin väärin versiosta v2.766.64 versioon v2.770.152 asti. Kokosivun DecodeLoadedPageBarcodes ja kasvojentunnistus funktion DetectLoadedRedactionFindings sisällä olivat väärin yhden koosteen pidempään, versioon v2.770.153 asti. Ennen v2.766.64 renderöijä piirsi koko MediaBoxin, joten kartoitus ja rasteri sopivat yhteen tunnistamalla sisältöä, jota katseluohjelmat eivät koskaan näytä. Korjaukset muuttivat kolmea asiaa yhdessä kutakin ominaisuutta varten: muunnosta, pikselibudjettiarviota ja pyyntötietueeseen omalle moottorille annettavaa sivulaatikkoa

Useat tapaukset eivät koskaan vaurioituneet:

  • Sivut ilman /CropBoxia tai sivut, joiden CropBox on yhtä suuri kuin MediaBox, kartoittuvat identtisesti ennen ja jälkeen korjauksen
  • DecodeLoadedPageBarcodes arvolla HasRegion asetettuna renderöi täsmälleen antamasi alueen ja kartoittaa sen saman alueen kautta, joten eksplisiittisen alueen dekoodaus oli oikein koko ajan; tarkistus siitä, että alue on sivun sisällä, käyttää yhä MediaBoxia
  • Kaavapohjaiset mustauslöydökset (sähköpostit, korttinumerot ja niin edelleen) tulevat tekstin poiminasta käyttäjätilassa, eivät rasterista, joten vain kasvojentunnistuslöydökset siirtyivät

Kolme koordinaatistoa ja mitkä HotPDF-API:t käyttävät kutakin

Tunnistukseen koskeva HotPDF-koodi käsittelee kolmea koordinaatistoa, ja useimmat kartoitusbugit tulevat kahden sekoittamisesta

  • Bittikarttapikselit: vasemman yläkulman alkukohta, Y kasvaa alaspäin, yksikkönä pikselit pyynnön DPI:llä. Kentät THPDFOCRWord.Left, Top, Right ja Bottom ovat tässä koordinaatistossa, samoin valinnaiset perusviivapisteet, tulokset, jotka oma IHPDFBarcodeDecoder palauttaa, sekä laatikot, jotka oma IHPDFFaceDetector palauttaa
  • Ladatun sivun PDF-käyttäjätila: vasemman alakulman alkukohta, Y kasvaa ylöspäin, yksikkönä pisteet, kun Bottom < Top. Funktiot GetLoadedPageBox ja GetLoadedPageVisibleBox palauttavat Left-, Bottom-, Right- ja Top-arvot tässä koordinaatistossa, samoin THPDFOCRRequestin kentät PageLeft, PageBottom, PageRight ja PageTop, rajat tietueessa THPDFDecodedBarcode sekä suorakulmiot tietueessa THPDFRedactionFinding
  • HotPDF:n sivunpiirtokoordinaatit: API, jolla rakennat uusia sivuja (tekstitulostus, muodot, viivakoodit, linkit, lomakekentät), toimii vasemman yläkulman alkukohdalla ja Y:n kasvaessa alaspäin. Kyseinen koordinaatisto kuuluu asiakirjojen generointiin, eikä sillä ole mitään tekemistä yllä olevien ladattujen asiakirjojen API:jen kanssa, joten älä koskaan syötä siihen ladatun sivun käyttäjätilan suorakulmiota muuttumattomana

OCR-sanatietue on tahallaan pikselipohjainen: moottori raportoi, mitä se näki kuvassa, ja ApplyLoadedOCRTextLayer omistaa muunnoksen. Kyseinen jako toimii vain, kun muunnos käyttää oikeaa laatikkoa, ja juuri sen v2.770.153 palautti

HotPDF:n tunnistuksen koordinaatistot: bittikarttapikselit vasemman yläkulman alkukohdalla, joita THPDFOCRWord-laatikot ja omat dekooderit käyttävät, PDF-käyttäjätila vasemman alakulman alkukohdalla, jonka GetLoadedPageBox ja GetLoadedPageVisibleBox palauttavat, sekä vasemman yläkulman sivunpiirto-API, jolle ei koskaan saa antaa ladatun sivun suorakulmiota muuttumattomana
Moottorit raportoi pikseleitä, koska sitä ne näkivät, HotPDF kartoittaa ne, ja kahden koordinaatiston sekoittaminen on tapa, jolla tasot ja mustauslaatikot ajautuvat sivuiltaan

Laite–sivu-muunnos OCR:n, viivakoodien ja kasvojen takana

HotPDF kartoittaa bittikarttapikselit sivulle yhdellä viidestä syötteestä rakennetulla affiinimatriisilla: kiertymällä, skaalalla DPI / 72, bittikartan korkeudella sekä renderöidyn laatikon Left-, Bottom-, Right- ja Top-arvoilla. OCR, viivakoodien dekoodaus ja kasvojentunnistus jakavat yhden rutiinin sen tekemiseen, minkä vuoksi yksi väärä laatikkosyöte rikkoi kaikki kolme samalla tavalla. Kiertymättömälle sivulle sivu–laite-matriisi [A B C D E F] on:

  • A = Scale ja D = -Scale, jossa Scale = DPI / 72; negatiivinen D kääntää käyttäjätilan (Y ylös) bittikarttatilaan (Y alas)
  • B = C = 0, koska kiertymättömällä sivulla ei ole leikkausta eikä akselien vaihtoa
  • E = -Left * Scale, joka siirtää laatikon vasemman reunan pikselisarakkeeseen 0
  • F = BitmapHeight + Bottom * Scale, joka kartoittaa laatikon alareunan arvoon y = BitmapHeight, bittikarttaan alareunaan, joten yläreuna laskeutuu riville 0

Pikselit palaavat sivulle kyseisen matriisin käänteiskuvan kautta. Request.PageRotation kantaa sivun /Rotaten normalisoituna arvoihin 0, 90, 180 tai 270 (mikä tahansa arvo, joka ei ole 90:n kerrannainen, käsitellään arvona 0), ja renderöijä kääntää sivun myötäpäivään, niin kuin ISO 32000-1 §7.7.3.3 vaatii. Kiertymän alla akselit vaihtuvat, ja eri pari laatikon reunoja kiinnitetään bittikartan alkukohtaan. Kirjoitettuna käänteiskaavoina, arvoilla S = DPI / 72, x ja y pikseleinä ja H bittikartan korkeutena:

/RotateSivun XSivun YLaatikon reunat, joista kartoitus riippuu
0Left + x / SBottom + (H - y) / SLeft, Bottom
90Left + y / SBottom + x / SLeft, Bottom
180Right - x / SBottom + y / SRight, Bottom
270Right - y / STop - x / SRight, Top

Viimeinen sarake selittää, miksi bugi näytti tuotannossa satunnaiselta. CropBox, joka rajaa vain sivun yläosaa, jättää Leftin ja Bottomin koskemattomiksi, joten kiertymättömät sivut tulivat täydellisesti ulos ja vain sivut, jotka kantoivat arvon /Rotate 270, ajautuivat sivuiltaan. Kiertymä vaihtaa myös bittikartan dimensiot: arvoilla 90 ja 270 bittikartta on (Top - Bottom) * S pikseliä leveä ja (Right - Left) * S pikseliä korkea

HotPDF:n käänteiskartoituksen taulukko sivunkiertymälle: arvoilla /Rotate 0 ja 90 muunnos kiinnittää renderöidyn laatikon Left- ja Bottom-reunat, arvolla 180 Rightin ja Bottomin, arvolla 270 Rightin ja Topin, minkä vuoksi rajattu sivu ajautuu eri suuntaan jokaista suuntausta kohden sekaisin asiakirjassa
Sama puolen tuuman rajaus näyttää kolmelta eri buggilta, kun sivut kantavat eri /Rotate-arvoja, koska jokainen suuntaus kiinnittää eri parin laatikon reunoja

Mitä menee pieleen arvoilla MediaBox [0 0 612 792] ja CropBox [36 36 576 756]?

Puolen tuuman rajauksella joka sivulta kiertymättömän sivun tekstitaso laskeutuu täsmälleen 36 pistettä vasemmalle ja 36 pistettä alle skannatuista sanoista, kun MediaBoxia käytetään. Ota US Letter -sivu, jonka CropBox rajaa 36 pistettä (0.5 tuumaa) jokaiselta reunalta. Näkyvä laatikko on 540 kertaa 720 pistettä, joten oletusarvoisella OCR-resoluutiolla 300 DPI skaala on 300 / 72 ≈ 4.1667 ja bittikartta 2250 kertaa 3000 pikseliä

Oletetaan, että moottori raportoi sanan pikselilaatikolla Left 450, Top 600, Right 900, Bottom 660 ilman perusviivaa. HotPDF sijoittaa sitten perusviivan 20 prosenttiin sanan korkeudesta alareunan yläpuolelle, pikseliriville 648, ja kartoittaa alkupisteen (450, 648):

  • Näkyvän laatikon kautta: x = 36 + 450 / 4.1667 = 144.0 ja y = 36 + (3000 - 648) / 4.1667 = 600.48, mikä on kohta, jossa sana on painettu
  • MediaBoxin kautta: x = 0 + 108.0 = 108.0 ja y = 0 + 564.48 = 564.48, yhtenäinen siirtymä (-36, -36) pistettä
HotPDF:n CropBox-ajautumisen anatomia US Letter -sivulla, jonka MediaBox on 0 0 612 792 ja CropBox 36 36 576 756: renderöijä rasteroi näkyvän laatikon 300 DPI:llä, joten sanan pikselin 450 kartoittaminen funktiolla GetLoadedPageVisibleBox antaa arvot 144.0 ja 600.48, kun taas MediaBox-muunnos laskeutuu arvoihin 108.0 ja 564.48
Rasteri kattaa CropBoxin, joten mikä tahansa MediaBoxista rakennettu muunnos siirtää jokaisen tunnistetun sanan täsmälleen rajausmarginaalin verran

Kierrä sama sivu, ja virheen suunta muuttuu, koska eri reunat ovat kuvioissa mukana. Arvolla /Rotate 180 X-termi käyttää Rightia, ja 612 arvon 576 sijaan työntää taso 36 pistettä oikealle, kun Bottom vetäisi yhä 36 pistettä alas. Arvolla /Rotate 270 sekä Right että Top ovat liian suuria, joten taso siirtyy 36 pistettä oikealle ja 36 pistettä ylös. Asiakirja, jolla on sekaisin suuntauksia, voi näyttää ajautumisen kolmeen suuntaan, luotettava sormenjälki tälle bugille. Käsin kirjoitettu koodi, joka johtaa skaalan laatikosta, kuten Bitmap.Width / (Right - Left), venyttää myös jokaisen koordinaatin 612 / 540, noin 13 prosenttia, siirtymän päälle

Mitkä omista PDF-asiakirjoistasi ovat vaarantuneita?

PDF-asiakirja on altistunut, kun vähintään yhdellä sivulla on näkyvä laatikko, joka eroaa sen MediaBoxista, ja HotPDF kertoo sen sinulle muutamalla rivillä. Vertaa funktiota GetLoadedPageBox arvolla pbMediaBox funktioon GetLoadedPageVisibleBox jokaisella sivulla ja tulosta GetLoadedPageRotation rinnalle, jotta voit ennakoida ajautumisen suunnan yllä olevasta taulukosta. THPDFPageBoundary tarjoaa lisäksi arvot pbCropBox, pbBleedBox, pbTrimBox ja pbArtBox, mutta GetLoadedPageBox(pbCropBox) palaa MediaBoxiin, kun crop-laatikkoa ei ole, eikä leikkaa, joten näkyvä laatikko on oikea vertailukohde

uses
  System.SysUtils, HPDFDoc;

procedure ReportCroppedPages(const FileName: string);
var
  Pdf: THotPDF;
  I: Integer;
  ML, MB, MR, MT, VL, VB, VR, VT, Tmp: Single;
begin
  Pdf := THotPDF.Create(nil);
  try
    if Pdf.LoadFromFile(FileName) < 1 then
      raise Exception.Create('Cannot load ' + FileName);
    for I := 0 to Pdf.LoadedPageCount - 1 do
    begin
      if not Pdf.GetLoadedPageBox(I, pbMediaBox, ML, MB, MR, MT) then
        Continue;
      // talletettu taulukko saattaa luetteloida kulmansa missä tahansa järjestyksessä
      if MR < ML then begin Tmp := ML; ML := MR; MR := Tmp; end;
      if MT < MB then begin Tmp := MB; MB := MT; MT := Tmp; end;
      // jo normalisoitu ja leikattu MediaBoxiin
      if not Pdf.GetLoadedPageVisibleBox(I, VL, VB, VR, VT) then
        Continue;
      if (Abs(VL - ML) > 0.01) or (Abs(VB - MB) > 0.01) or
         (Abs(VR - MR) > 0.01) or (Abs(VT - MT) > 0.01) then
        Writeln(Format('Page %d  MediaBox [%g %g %g %g]  visible [%g %g %g %g]  /Rotate %d',
          [I + 1, ML, MB, MR, MT, VL, VB, VR, VT,
           Pdf.GetLoadedPageRotation(I)]));
    end;
  finally
    Pdf.Free;
  end;
end;

Kaksi yksityiskohtaa funktiossa GetLoadedPageVisibleBox merkitsee tällaisille skripteille. Funktio jättää out-parametrinsä koskemattomiksi epäonnistuessaan, joten oletussivukoon esiasettaminen ennen kutsua on turvallinen kaava. Ja kun epäkelpo CropBox ei leikkaa MediaBoxia yhtään, funktio palauttaa MediaBoxin tyhjän suorakulmion sijaan. Jos raportti luetteloi sivuja ja käytössäsi oleva kooste on vanhempi kuin v2.770.153 OCR:n kohdalla tai v2.770.154 viivakoodeille ja kasvoille, aja tunnistus uudelleen kyseisillä sivuilla päivityksen jälkeen. Vaurioituneen koosteen vahvistama OCR-taso jää tallennettuun tiedostoon, ja oletusvalinta SkipPagesWithText ohittaa kyseiset sivut toisella kierroksella, ellet kytke sitä pois tai poista vanhaa tasoa ensin

Miten oman IHPDFOCREngine:n pitäisi kartoittaa pikselit takaisin PDF-tilaan?

Oman IHPDFOCREnginen pitäisi palauttaa sanalaatikot bittikarttapikseleinä ja antaa HotPDF:n tehdä kartoitus; muunna käyttäjätilaan vain omia päätöksiäsi varten, ja käytä silloin pyynnön laatikkoa, ei koskaan MediaBoxia. Versiosta v2.770.153 alkaen pyynnön kentät PageLeft, PageBottom, PageRight ja PageTop kuvaavat renderöityä näkyvää laatikkoa, joten ne vastaavat kohtaa Request.Bitmap täsmälleen. Alla oleva avustaja on kirjaston muunnoksen käänteiskuva, mukaan lukien sen käyttö todellista bittikartan korkeutta pystysuorilla sivuilla, joten se sopii HotPDF:n kanssa yhteen pikseliin asti

uses
  System.SysUtils, System.Math, Vcl.Graphics, HPDFDoc;

// Bittikarttapikseli (vasemman yläkulman alkukohta, Y alaspäin) PDF:n
// käyttäjätilaan (vasemman alakulman alkukohta, Y ylöspäin) sitä laatikkoa pitkin, josta bittikartta renderöitiin
procedure HotPixelToPage(Rotation, DPI, BitmapHeight: Integer;
  Left, Bottom, Right, Top: Single; X, Y: Double;
  out PageX, PageY: Double);
var
  S: Double;
begin
  S := DPI / 72.0;
  case Rotation of
    90:  begin PageX := Left + Y / S;  PageY := Bottom + X / S; end;
    180: begin PageX := Right - X / S; PageY := Bottom + Y / S; end;
    270: begin PageX := Right - Y / S; PageY := Top - X / S; end;
  else
    PageX := Left + X / S;
    PageY := Bottom + (BitmapHeight - Y) / S;
  end;
end;

Realistinen syy tarvita käyttäjätilaa moottorin sisällä on vyöhykesääntö: laskut, joiden kirjeenpohjaa ei koskaan haluta haettavaksi, tai leima-alue, joka sekoittaa tunnistimen. Alla oleva moottori, kirjoitettu luokalla TInterfacedObject niin, että viitemääritys hoitaa sen eliniän, suodattaa sanat sen mukaan, mihin niiden keskipisteet putoavat sivulla, ja palauttaa sitten selvinneet koskemattomina pikselikoordinaateissa. RunRecognizer edustaa omaa tunnistinkutsuasi

type
  TZoneFilterOCREngine = class(TInterfacedObject, IHPDFOCREngine)
  private
    FSkipLeft, FSkipBottom, FSkipRight, FSkipTop: Single;  // käyttäjätila
    function RunRecognizer(Bitmap: TBitmap; MaxWords: Integer;
      out Words: THPDFOCRWords): boolean;  // oma tunnistimesi, pikselilaatikot
  public
    constructor Create(SkipLeft, SkipBottom, SkipRight, SkipTop: Single);
    function GetName: AnsiString;
    function Recognize(const Request: THPDFOCRRequest;
      out Words: THPDFOCRWords; out Diagnostic: AnsiString): boolean;
  end;

function TZoneFilterOCREngine.Recognize(const Request: THPDFOCRRequest;
  out Words: THPDFOCRWords; out Diagnostic: AnsiString): boolean;
var
  Raw: THPDFOCRWords;
  I, Count: Integer;
  CX, CY: Double;
begin
  Diagnostic := '';
  SetLength(Words, 0);
  if not RunRecognizer(Request.Bitmap, Request.MaxWords, Raw) then
  begin
    Diagnostic := 'recognizer failed';
    Exit(False);
  end;
  SetLength(Words, Length(Raw));
  Count := 0;
  for I := 0 to High(Raw) do
  begin
    HotPixelToPage(Request.PageRotation, Request.DPI,
      Request.Bitmap.Height, Request.PageLeft, Request.PageBottom,
      Request.PageRight, Request.PageTop,
      (Raw[I].Left + Raw[I].Right) / 2, (Raw[I].Top + Raw[I].Bottom) / 2,
      CX, CY);
    if (CX >= FSkipLeft) and (CX <= FSkipRight) and
       (CY >= FSkipBottom) and (CY <= FSkipTop) then
      Continue;
    Words[Count] := Raw[I];  // yhä pikseleitä: HotPDF kartoittaa ne itse
    Inc(Count);
  end;
  SetLength(Words, Count);
  Result := True;
end;

Anna moottori funktiolle ApplyLoadedOCRTextLayer(PageIndices, Engine, Options, Info) kuten mille tahansa muulle moottorille. Kirjasto validoi palautuvan ennen kuin luottaa siihen: sana pudotetaan ja se lasketaan kenttään Info.DroppedWordCount, kun sen laatikko poistuu bittikartasta, kun Right <= Left tai Bottom <= Top, tai kun Confidence on väliltä 0..1 poissa tai alle MinimumConfidencein. Useampien sanojen palauttaminen kuin MaxWordsPerPage tai juoksevan summan työntäminen arvon MaxTotalWords yli kaataa koko kutsun budjettivirheellä, joten kunnioita arvoa Request.MaxWords moottorissasi. Älä muunna sanalaatikoita käyttäjätilaan ennen niiden palauttamista; HotPDF käsittelisi pistearvot pikseleinä, ja taso luhistuisi bittikartan alkukohtaa kohti

Oman detektorin tuotoksen kartoittaminen

Sama avustaja palvelee kotikutoista putkea, joka rakentuu funktion RenderLoadedPageToBitmap päälle, renderöi näkyvän laatikon ja soveltaa arvoa /Rotate aivan kuten tunnistusominaisuudet. Lue laatikko funktiolla GetLoadedPageVisibleBox, normalisoi kiertymä samalla tavalla kuin HotPDF ja kartoita jokaisen pikselilaatikon kaksi vastakkaista kulmaa. Y-akseli kääntyy ja arvoilla 90 ja 270 astetta akselit vaihtuvat, joten kartoitetut kulmat tulevat ulos missä tahansa järjestyksessä; ota kartoitettujen pisteiden minimi ja maksimi, mikä on myös tapa, jolla HotPDF rakentaa viivakoodirajat

const
  DPI = 200;
var
  Pdf: THotPDF;
  Bmp: TBitmap;
  VL, VB, VR, VT: Single;
  Rotation: Integer;
  PxL, PxT, PxR, PxB, X1, Y1, X2, Y2: Double;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.LoadFromFile('scanned-ids.pdf');
    if not Pdf.GetLoadedPageVisibleBox(0, VL, VB, VR, VT) then Exit;
    Rotation := Pdf.GetLoadedPageRotation(0) mod 360;
    if Rotation < 0 then Inc(Rotation, 360);
    if (Rotation <> 90) and (Rotation <> 180) and (Rotation <> 270) then
      Rotation := 0;
    Bmp := Pdf.RenderLoadedPageToBitmap(0, DPI);
    if Bmp = nil then Exit;
    try
      MyDetector(Bmp, PxL, PxT, PxR, PxB);  // oma koodisi, pikselilaatikko
      HotPixelToPage(Rotation, DPI, Bmp.Height, VL, VB, VR, VT,
        PxL, PxT, X1, Y1);
      HotPixelToPage(Rotation, DPI, Bmp.Height, VL, VB, VR, VT,
        PxR, PxB, X2, Y2);
      Writeln(Format('User-space box [%.2f %.2f %.2f %.2f]',
        [Min(X1, X2), Min(Y1, Y2), Max(X1, X2), Max(Y1, Y2)]));
    finally
      Bmp.Free;
    end;
  finally
    Pdf.Free;
  end;
end;

Kiertymäkäyttäytyminen käsitellään syvemmin artikkelissa sivunkiertyman tasoittaminen rikkomatta sivulaatikoita ja viivakoodien dekoodausputki, joka kuluttaa saman muunnoksen, artikkelissa kiertyneiden QR-koodien dekoodaus PDF-sivuilta. Jos moottorisi kietoo ulkoisen tunnistimen, artikkeli Tesseract-OCR-sovitin haettavaan PDF:ään näyttää saman rajapinnan prosessieristyksen ja peruuttamisen puolen

Pikaopas: CropBox-turvallinen koordinaattikartoitus

  • Renderöijä rasteroi näkyvän laatikon, CropBoxin leikattuna MediaBoxiin (ISO 32000-1 §14.11.2); jokaisen pikseli–sivu-kartoituksen on käytettävä kyseistä laatikkoa, luettuna funktiolla GetLoadedPageVisibleBox
  • HotPDF v2.770.153 korjasi funktion ApplyLoadedOCRTextLayer; v2.770.154 korjasi kokosivun DecodeLoadedPageBarcodesin ja kasvolöydökset funktiosta DetectLoadedRedactionFindings; koosteet versiosta v2.766.64 näihin versioihin asti ovat vaurioituneita
  • THPDFOCRWord-laatikot ovat bittikarttapikseleitä vasemman yläkulman alkukohdalla; GetLoadedPageBox ja GetLoadedPageVisibleBox palauttavat PDF-käyttäjätilan vasemman alakulman alkukohdalla ja arvolla Bottom < Top
  • Skaala on DPI / 72; johda se DPI:stä, ei koskaan sivulaatikosta jaettuna bittikartan leveydellä
  • /Rotate päättää, mitkä reunat merkitsevät: Left ja Bottom arvoilla 0 ja 90, Right ja Bottom arvolla 180, Right ja Top arvolla 270
  • Palauta OCR-sanat pikseleinä ja anna HotPDF:n kartoittaa ne; muunna vain omaa suodatuslogiikkaasi varten
  • Aja OCR uudelleen rajatuilla sivuilla, jotka vaurioitunut kooste käsittelee, ja muista, että SkipPagesWithText ohittaa sivut, jotka kantavat jo vanhaa tasoa

Tunnistusominaisuudet, sivulaatikkokyselyt ja ladattujen asiakirjojen renderöinti, joita täällä käytetään, toimitetaan kaikki HotPDF-komponentissa Delphille ja C++Builderille; käyttöoikeudet, kokeiluversiot ja täysi ominaisuusluettelo ovat HotPDF Delphi PDF component -sivulla