PDFlibPas lahko kodira dvonivojske slike (bilevel) kot JBIG2 skozi dve različni zaledji. Ena je lastni kodirnik MMR v Object Pascalu, ki je vedno prisoten. Druga je zunanji kodirnik slovarja simbolov (symbol-dictionary), ki proizvede bistveno manjši izhod na skeniranem besedilu, in je neobvezen: projekt mora povezati zaledjno enoto, da sploh obstaja. To razlikovanje je vir najpogostejšega presenečenja s to funkcijo, zato je vredno najprej povedati: DefaultJBIG2EncodeOptions zahteva zunanji kodirnik privzeto, in ko zaledjna enota ni povezana, se zahteva tiho vrne na pot Pascal MMR
Na Delphi in C++Builder je zunanje zaledje nabor vnaprej zgrajenih statičnih objektov. Na Free Pascalu je moralo postati DLL, pot do tega sklepa pa je zgodba o povezovalniku, koristna vsakomur, ki je poskušal povezati objekte C++ v program Free Pascal
Registracija je pogodba
Zaledjna enota registrira sebe iz svojega razdelka inicializacije s klicem RegisterJBIG2EncoderBackend. Klicatelji jo zahtevajo bodisi skozi bit možnosti PDF_JBIG2_OPTION_EXTERNAL_ENCODER, ki ima vrednost 4, bodisi skozi parameter UseExternalEncoder razširjenih vstopnih točk slik. Dežnik knjižnice namenoma ne vleče zaledjne enote noter, ker naj bi nošenje velikega nabora objektov bila odločitev vsakega projekta; v drevesu C++Builder jo na primer izrecno vključijo projekti, ki jo želijo
Posledica za klicatelje je, da je zahteva po zunanjem kodirniku preferenca in ne garancija, gradnja, ki pozabi enoto, pa proizvede večje datoteke namesto napake. Če je velikost izhoda dovolj pomembna, da zahtevate boljši kodirnik, je dovolj pomembna, da preverite, ali ste ga dobili
uses
PDFlibrary,
{$IFDEF FPC}
PDFlibJBIG2EncDLL; // dinamično zaledje za Free Pascal
{$ELSE}
PDFlibJBIG2EncC; // statični nabor objektov za Delphi / C++Builder
{$ENDIF}
var
Pdf: TPDFlib;
ImageId: Integer;
begin
Pdf := TPDFlib.Create(nil);
try
Pdf.NewDocument;
Pdf.NewPage;
// Interpolate, SymbolExtract, UseExternalEncoder, SkipBlackDots,
// BlackDotSize, LossyLevel
ImageId := Pdf.AddImageJBIG2FromFileEx('scan-page-1.tif',
0, 1, 1, 0, 0, 0);
if ImageId = 0 then
raise Exception.Create('JBIG2 encoding failed');
Pdf.SaveToFile('archive.pdf');
finally
Pdf.Free;
end;
end;
Prevajanje enote je bilo v dveh vrsticah. Simboli so bili delo
Da se je zaledjna enota sama prevedla pod Free Pascalom, je vzelo natanko dve spremembi: nastavitev narečja zbirnika in zamenjavo konstruktorja nastavitev oblike na osnovi zapisa z globalno privzeto spremenljivko. To je pošten odsev tega, kako prenosljiv je enostaven Pascal med tema dvema prevajalnikoma
Stran simbolov je bilo pravo delo. Nabor objektov se sklicuje na 176 simbolov C. Od teh jih je 128 že imelo Pascalove implementacije znotraj enote in je potrebovalo samo pripete izvozne imena, ker Delphi uporabi ime funkcije kot ime simbola, Free Pascal pa zahteva izrecno deklaracijo javnega imena. Sedemindvajset jih je bilo v skupni rabi s kodekom JPEG 2000 in jih je bilo treba izvoziti iz natanko enega kraja, ker jih določitev dvakrat prelomi vsak program, ki povezuje oboje. Preostalih 21 je bilo vnosov platforme in izvajalnega okolja C, šestnajst funkcij datotek Win32 plus peščica klicev standardne knjižnice, in šli so v novo združljivostno enoto
Nič od tega konceptualno ni težko in vse je potrebno, preden bo povezovalnik sploh poskusil. Povezovalnik je mesto, kjer se je ustavilo
Tri povezovalne poti, tri slepe ulice
Notranji povezovalnik Free Pascala ne more brati objektnih datotek, ker so bile proizvedene s prevajalnikom, ki izda asociativne razdelke COMDAT, notranji povezovalnik pa poroča, da jih ne podpira. To je ravna zavrnitev, ne opozorilo
Preklop na zunanji povezovalnik je izgledal kot odgovor. Povezovalnik binutils, ki je pripet k Free Pascalu, se popolnoma sesuje med uporabo zbiranja smeti razdelkov (garbage collection) na ta arhiv, ta zastavica pa je del fiksnega nabora parametrov, ki jih Free Pascal posreduje za 64-bitni cilj Windows, zato je ni mogoče odstraniti iz ukazne vrstice; dokumentirana stikala za njeno zatiranje so na tej poti ignorirana. Preskrba veliko novejšega binutils namesto tega odpove drugače: sploh ne more obdelati povezovalnega skripta Free Pascala, proizvede prazen izhod brez skripta in zid relokacijskih napak z njim
Meja, odkrita ob poti, je vredna poznanstva, tudi če težave s povezovalnikom nikoli ne srečate. Zunanji povezovalnik razreši poti objektnih datotek glede na izhodno mapo izvedljive datoteke in ne glede na drevo virov, zato relativna direktiva vključitve objekta deluje samo, ko izhodna mapa slučajno ustreza delovni mapi ob prevajanju. Knjižnica tega ne more predpostavljati o projektu potrošnika, kar je samo po sebi razlog, da raje izberete povezano knjižnico pred ohlapnimi objekti
Zakaj drug prevajalnik C++ ne pomaga
Očitna naslednja ideja je znova zgraditi stran C++ s prevajalnikom, katerega objekte Free Pascal zna brati. Tudi to ne deluje, razlog pa je temeljna in ne stvar stikal. Minimalna prevajalska enota C++, ki vsebuje predlogo (template), prevedena z vsako funkcijo generiranja kode izklopljeno, vseeno izda šibke zunanje simbole, ker jih instanciacija predlog in inline proizvede po zasnovi. Free Pascal ta razred simbolov odkloni popolnoma. Obratna smer odpove prav tako: povezovalnik glavnega toka C++ ne more porabiti objektov od drugega prevajalnika zaradi enake obravnave razdelkov COMDAT
Kode C++ torej ni mogoče dostaviti kot objekte Free Pascalu po nobeni razpoložljivi poti. Dostaviti ga je mogoče kot DLL, kar se je zgodilo: kodirnik in njegova odvisnost obdelave slik sta zgrajena v eno knjižnico, ki izpostavlja dve ravni vstopni točki C, zaledjna enota Free Pascal pa ju veže dinamično in registrira sebe natanko tako kot statično zaledje. Pot Delphi in C++Builder ni bila sploh dotaknjena, kar je pravi izid; težava prenosljivosti na eni orodjarni ne bi smela motiti orodjarne, ki je že delovala
Polariteta je tista stvar, ki vas bo ugriznila
Med bitno sliko dvonivojske Windows in kodirnikom JBIG2 je neskladje konvencij, ki ga noben tipni sistem ne bo ujel. Vrstica prekrivanja (scanline) napravi neodvisne bitne slike z enim bitom na pikslo obravnava nastavljeni bit kot belo. Kodirnik obravnava nastavljeni bit kot črno. Posredujte vrstice prekrivanja nespremenjene in dobite popolnoma veljaven tok JBIG2 fotografskega negativa vaše strani
// Enobitna DIB: nastavljeni bit pomeni belo. Kodirnik JBIG2:
// nastavljeni bit pomeni črno. Invertirajte vsak bajt na poti noter
for I := 0 to RowBytes - 1 do
Row[I] := Row[I] xor $FF;
Metoda preverjanja je enako pomembna kot popravek. Primerjanje dolžin stisnjenih tokov vam ne pove nič, ker se negativna slika stisne v podobno velikost. Pogled na stran dokaže samo, da očitno ni invertirana. Zanesljiv pregled je upodobiti izhod obeh kodirnih poti, lastne Pascal in zunanje, v PNG in jih primerjati bajt za bajtom: oba kodirnika sta brezizgubna na isti izvorni sliki, zato je karkoli drugega od natančnega ujemanja hrošč v enem od njiju. Ta primerjava je zdaj trajen regresijski test in je tista vrsta trditve, vredna izgradnje, kadar koli naj se dve implementaciji ujemata natančno
Katero zaledje uporabiti
Za splošno dvonivojsko vsebino, razpršene poltone (dithered halftones), črtno grafiko, mešano grafiko, je lastni kodirnik Pascal MMR zadosten in nima stroška namestitve. Za skenirano besedilo, kar je primer, za katerega je bil JBIG2 zasnovan, je zunanji kodirnik slovarja simbolov tam, kjer živi zmanjšanje velikosti, ker razčleni ponavljajoče se oblike glifov v slovar namesto ponovnega kodiranja vsake pojavitve. Če proizvajate arhive skeniranih dokumentov, je ta razlika dovolj velika, da spremeni načrtovanje shrambe
Vprašanje tokovno gor, kako sploh nastane dvonivojska slika, je enako pomembno za velikost izhoda; upodabljanje enobarvnih regij na osnovi regij je pokrito v članku o upodabljanju enobarvnih regij, strategija velikosti po dokumentu pa v optimizaciji velikosti datoteke PDF in podnaborih pisav. Za nize skenov s ponavljajočimi se stranmi odstranjevanje podvojenih pogosto premaga boljše stiskanje, kar je tema odstranjevanja podvojenih slik na osnovi percepcije. Razpoložljivost orodjarn in zaledij po platformi je navedena na strani produkta losLab PDF Developer Library