HotPDF dekodira vrten QR simbole v naloženi strani PDF z normalizacijo vzorčene matrice modulov skozi vseh osem orientacij D4 znotraj samega dekoderja. Zunanji poskus z vrtenjem, ki deluje za linearne simbologije, za QR ne more delovati, razumevanje zakaj pa vam prihrani dan lova na dekoder, ki izgleda pokvarjen, a ni
Scenarij je povsem vsakdanji. Skenirane dobavnice prispejo kot PDF-ji, vsaka stran nosi nalepko QR, operater skenerja pa je podal kup listov v katero koli smer, ki jo je pladenj sprejel. Nekatere nalepke so pokončne, nekatere so za četrtinko zgrešene, nekaj jih je na glavo. Pokličete dekoder črtne kode, polovica strani se razreši, druga polovica pa se vrne prazna, brez nobene napake
Zakaj vrtenje maske skeniranja nikoli ne popravi vrtenega QR?
Ker je razporeditev vzorca iskalnika QR namerno asimetrična, vrtenje cele slike pa to asimetrijo ohrani, namesto da bi jo odstranilo. QR Code postavi tri kvadrate iskalnika v kote zgoraj-levo, zgoraj-desno in spodaj-levo, kot spodaj-desno pa pusti praznega (ISO/IEC 18004:2015 §6.3.3). Ta manjkajoči kot je namig orientacije. Bitno preslikavo strani zavrtite za devetdeset stopinj in vrzel se preprosto preseli v drug kot. Ne obstaja netrivialno vrtenje ravnine, ki bi razporeditev s tremi koti preslikalo nazaj nase, zato bo dekoder, ki sprejema le kanonično razporeditev, vsak poskus po vrsti zavrl
To šteje, ker je očitno popravilo napačno. Naravni instinkt je obesiti poskus na zunanjost: izrišite stran, masko podajte dekoderju in če to spodleti, masko zavrtite in poskusite znova za 90, 180 in 270 stopinj. Za Code 39 je ta politika točno prava, ker ima linearna simbologija vzorca začetka in ustavitve, ki jih skener najde, takrat ko črte tečejo vodoravno. Za QR so to štirje zagotovljeni spodleti, ki jim sledi poročilo o nič najdenega
Grupa D4, uporabljena na matrici modulov
Pravo mesto za normalizacijo je po vzorčenju, na boolean mreži modulov in ne na maski pikslov. Ko dekoder simbol razreši v matrico temnih in svetlih modulov velikosti n-krat-n, lahko našteje diedrsko grupo kvadrata: štiri vrtenja krat dva zrcaljenja, skupaj osem kandidatskih orientacij. Za vsakega kandidata preveri trikotnik iskalnikov in prvi kandidat, ki njegovi trije iskalniki pristanejo na mestih zgoraj-levo, zgoraj-desno in spodaj-levo, je prava orientacija. Od tam naprej obstoječi cevovod teče nespremenjen, ker biti informacije o formatu, cikcak postavitev podatkov in popravilo Reed-Solomon vsi privzemajo kanonično matrico in zdaj jo dobijo
Dve lastnosti naredita to poceni. Matrica je majhna v primerjavi z izrisano bitno preslikavo, tako da osem transpozicij stane veliko manj kot osem izrisov strani. Matrica je čist boolean seznam, zgrajen s strani vzorčevalnika, zato nobena transformacija na poti ne more uvesti vrednosti, ki nikoli niso bile vzorčene
Zaznavanje verzije je iskanje deljivosti, ne deljenje
Števila modulov ni mogoče izpeljati z deljenjem vzorčene širine s privzetimi velikostjo modula, napaka tu pa je subtilen vir spodletelih dekodiranj na izrisih visoke ločljivosti. Simbol QR verzije v je 4v + 17 modulov čez, tako da je verzija 1 21 modulov in verzija 40 177. Maska, široka 126 pikslov, je enakovredno skladna z verzijo 1 pri šestih pikslih na modul in z več višjimi verzijami pri manjših velikostih modulov. Linearno deljenje izbere enega od njih in je običajno napačno
Deluje iskanje deljivosti čez kandidatske verzije. Pojdite od verzije 40 navzdol do verzije 1, obdržite kandidate, katerih število modulov deli vzorčeno širino brez ostanka in pušča vsaj tri piksle na modul, ter vzemite najmanjšo preživelo verzijo. Tla treh pikslov so tisto, kar iskanju prepreči sprejeti absurdno gosto branje grobega simbola, pravilo najmanjše verzije pa razreši preostalo dvoumnost v prid branju, ki bi ga dejansko dal skener
var
Pdf: THotPDF;
Options: THPDFBarcodeDecodeOptions;
Codes: THPDFDecodedBarcodes;
Info: THPDFBarcodeDecodeInfo;
I: Integer;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.LoadFromFile('delivery-notes.pdf');
Options := THPDFBarcodeDecodeOptions.Default;
Options.DPI := 300;
Options.RotationPolicy := bdrpFallback;
Options.MinimumConfidence := 0.5;
Options.MaxResults := 16;
if Pdf.DecodeLoadedPageBarcodes(0, Options, Codes, Info) then
for I := 0 to High(Codes) do
if Codes[I].Symbology = bsyQRCode then
Writeln(Codes[I].Text, ' at ',
Format('%.0f', [Codes[I].OrientationDegrees]), ' degrees');
finally
Pdf.Free;
end;
end;
THPDFBarcodeDecodeOptions.Default vrne zapolnjen zapis in ne izničenega, kar šteje, ker je DPI nič ali omejitev rezultatov nič videti veljaven način, da ne dobite nič nazaj. RotationPolicy nadzoruje le zunanji poskus: bdrpNone izriše enkrat, bdrpFallback poskusi druge orientacije po spodletelem prvem prehodu, bdrpAll pa izriše vsako orientacijo brezpogojno. Ker se normalizacija QR zgodi znotraj dekoderja, se strani QR razrešijo ob prvem poskusu pod katero koli od treh politik. Politika je tam za linearne simbologije, ki jo dejansko potrebujejo
Kako dokažete, da bitna preslikava ne izmišljuje pikslov?
Preštejte črnilo na obeh straneh in zahtevajte, da se vsoti ujemata. Vrtenje je permutacija pikslov in nič več, tako da mora število neničelnih celic v izhodu biti enako številu v vnosu. Ko je vrtenje maske na poti zunanjega poskusa sporočilo 4800 nastavljenih celic na vstopu in 7439 na izstopu, je bila ta ena sama primerjava dovolj, da se transformacija obsodi, brez branja ene same vrstice njene geometrije
Vzrok je bil vsakdanj in vreden odnesti kot pravilo. Dinamičnemu seznamu, velikosti z SetLength, ni jamstvo, da pride izničen, ko je rezultat funkcije, ki potuje po poti, ki je izvajalno okolje ne počisti, celice, ki jih vrtenje nikoli ne zapiše, pa nosijo kateri koli bajte, ki so bili tam prej. Nekateri od teh zastarelih bajtov so neničelni, neničelno pa pomeni črnilo. Popravilo je ena vrstica, FillChar(Result[0], N, 0), preden zažene zanka permutacije, disciplina, ki jo implicira, pa je širša: vsaka funkcija, ki vrača masko ali medpomnilnik bitne preslikave, naj svoj izhod izrecno počisti, namesto da bi se zanašala na semantiko dodelitve
Tisto, kar je pomanjkljivost pustilo preživeti tri izdaje, je zanimivejše od pomanjkljivosti. Ko je QR preselil svojo obravnavo orientacije v dekoder, je QR prenehal popolnoma izvajati zunanje vrtenje maske in edini preostali potrošnik te kodne poti je bil Code 39. Deljena infrastruktura skriva takšne hrošče nenehno: pokritost iz ene zmožnosti naredi pot videti testirano, medtem ko zmožnost, ki dejansko visi od nje, nima nobene svoje. Vsaka pot, ki jo nova zmožnost preneha uporabljati, potrebuje test, ki jo še uporablja
Branje rezultatov nazaj v koordinatah strani
Vsaka geometrijska vrednost, ki jo dekoder proizvede, je izražena v koordinatnem okvirju poskusne bitne preslikave, klicatelj pa jo potrebuje v uporabniškem prostoru PDF. Pretvorba teče v dveh stopnjah: razveljavite četrtinski obrat, ki ga je nanesel poskus, nato razveljavite izrisno transformacijo, ki je uporabniški prostor preslikala na bitno preslikavo. Kar pride v THPDFDecodedBarcode, je omejitvena škatla, poravnana z osmimi, v uporabniškem prostoru, z Left, Bottom, Right in Top, ki sledijo konvenciji PDF, da Y narašča navzgor, plus OrientationDegrees v nasprotni smeri urinega kazalca
Zmešajte smer te druge pretvorbe in simptom je grd: besedilo se dekodira popolnoma, a škatla, ki jo narišete za pregledno plast, pristane na zrcalni sliki pravega položaja. Kdorkoli gradi pregledni vmesnik na dekoderju, naj trditev postavi proti znani napravi, s simbolom, namerno postavljenim blizu enega od kotov strani, da je obrnjen os Y viden na prvi pogled. Isto razmišljanje velja za vsako koordinato, ki prečka izrisno mejo, zato je vredno razumeti izris strani PDF v bitno preslikavo v Delphi, preden gradite na dekoderju
Kaj bo in česar ne bo vgrajeni dekoder
Vgrajeni dekoder je omejena implementacija brez odvisnosti in je iskren glede svojih mej, namesto da bi se tiho zapadel. Prepozna Code 39 in QR, validira BCH zaščitene bite formata in vzorec maske, preden objavi kakršne koli podatke, in ne poskuša obnoviti napak na poškodovanih simbolih. Če je vaš vhod fotografija ukrivljene nalepke pod neenakomerno svetlobo, je to drugačen razred težav in želi specializiran motor
// Zamenjajte svoj motor: implementirajte IHPDFBarcodeDecoder in ga podajte
// preobremenitvi, ki zna dekoder. HotPDF še vedno lasti izris strani,
// proračune, preslikavo koordinat in odstranjevanje dvojnikov
if not Pdf.DecodeLoadedPageBarcodes(PageIndex, MyDecoder, Options,
Codes, Info) then
case Info.Status of
bdsBudgetExceeded:
Log('raise MaxPixels or lower DPI: ' + string(Info.Diagnostic));
bdsRenderError:
Log('page did not render: ' + string(Info.Diagnostic));
bdsDecoderError:
Log(string(Info.DecoderName) + ' failed: ' + string(Info.Diagnostic));
end;
THPDFBarcodeDecodeInfo je tisto, pri čemer produkcijski cevovod zasluži svoje. RotationAttemptCount in DecoderCallCount vam povesta, ali je zunanji poskus sploh tekel, ReceivedResultCount proti AcceptedResultCount loči dekoder, ki ni našel nič, od praga zaupanja, ki je zavrnil vse, kar je našel, RenderedPixels z PeakWorkingBytes pa je tisto, kar grafično prikažete, ko se paketno opravilo začne dušiti samo. Prazen nabor rezultatov plus bdsSucceeded pomeni, da stran res nima berljivega simbola, kar je druga operativno dejstvo od bdsBudgetExceeded
Polja proračuna si zaslužijo premišljeno odločitev in ne privzetka. MaxPixels in MaxWorkingBytes obstajata, ker DPI množi kvadratno: prehod s 300 na 600 DPI na strani A4 štirikratno poveča tako ceno izrisa kot vrh dodelitve, nezaupljiv vhod, ki razglasi ogromno škatlo strani, pa lahko skeniransko opravilo spremeni v incident zmanjkane pomnilnine. Omejitve nastavite na to, kar potrebuje vaš najslabši legitimni dokument, nato pa naj bdsBudgetExceeded osamelce usmeri na počasnejšo, izolirano pot
Če vaši dokumenti mešajo strojno berljive nalepke z natisnjenim besedilom, ki ga nameravate indeksirati, se dekoder črtnih kod naravno poveže z prepoznavalnim motorjem, obravnavanim v OCR z iskanjem predlog znotraj HotPDF, generacijska stran iste zgodbe pa je v risanju črtnih kod v PDF s HotPDF. Oba tečeta na isti infrastrukturi izrisa in proračuna, tako da cevovod, ki že postavi zdrave meje za enega, drugega dobi skoraj zastonj
Toleranca vrtenja je ena od tistih zmožnosti, ki je nevidna, ko deluje, in razjarjujoča, ko ne, inženirski pouk pa se posplošuje čez QR: normalizirajte tako blizu semantični predstavitvi, kot lahko pridete, in ne na plasti pikslov, kjer podatki še nosijo vsako nesrečo tega, kako so bili zajeti. HotPDF to pošilja kot del HotPDF Delphi PDF component, ob delih izrisa, OCR in analize strani, ki jih isti sprejemni cevovodi običajno potrebujejo