Naskenovaná smlouva je jen pár set bodů na palec černého inkoustu na bílém papíře. Jako bitmapa s jedním bitem na pixel je sama o sobě malá, přesto sto takovýchto stránek nafouká PDF nad jakoukoli rozumnou velikost pro e-mail. Správný filtr tuto matematiku změní. JBIG2 je komprese s nejvyšším kompresním poměrem, kterou ISO 32000-1 definuje pro dvouúrovňové obrázky, a na zásobníku naskenovaného textu obvykle dosáhne poloviční velikosti oproti CCITT Group 4. Tento filtr je volbou číslo jedna tehdy, když je vstup faxovaný, naskenovaný nebo jinak redukovaný na dvě barvy, a HotPDF jej dokáže zapsat přímo do PDF
Formát dosahuje tohoto poměru díky dvěma myšlenkám, které obecný obrazový kodek nemá. Modeluje, jak černé úseky leží na bílém pozadí, a všímá si, že naskenovaná stránka sestává převážně z několika set tvarů glyfů opakovaných tisícekrát. Pochopení obojího umožňuje zvolit možnosti kódování záměrně, nikoli náhodně
Kde JBIG2 stojí ve specifikaci PDF
ISO 32000-1 uvádí JBIG2Decode mezi proudovými filtry v §7.4.7, dostupný od PDF 1.4. Vztahuje se pouze na jediné místo: obrazové XObjects, jejichž /BitsPerComponent je 1 a jejichž barevný prostor se převádí na jediný kanál. To je celý smysl. JBIG2 je dvouúrovňový kodek, takže nesoupeří s DCT ani JPXDecode na fotografiích. Soupeří s CCITTFaxDecode, faxovými filtry Group 3 a Group 4, přesně na tom druhu dvoutónových stránek, které produkuje dokumentový skener
Dekodér zpracovává vloženou organizaci JBIG2, kterou standard nazývá profilem PDF, kde každý obrazový proud obsahuje sekvenci segmentů místo holého bitového proudu. Volitelný proud /JBIG2Globals nese segmenty sdílené napříč několika obrázky v tomtéž dokumentu, což je mechanismus umožňující uložit opakující se obsah jednou pro celý soubor místo jednou na stránku. HotPDF ve výchozím nastavení generuje proud pro každý obrázek zvlášť a ponechává globální kanál volný, pokud jej backend výslovně nepožaduje
Architektura kodéru s backends jako první vrstvou
Kompletní kodér JBIG2 je velký kus softwaru a jeho nejagresivnější části byly historicky zatíženy patenty a dodávány pod licencemi, které nevyhovují každému produktu. HotPDF toto napětí řeší oddělením rozhraní od jádra. Jednotka HPDFJBIG2 definuje volání, která provádí zbytek knihovny, a dodává skromný vestavěný kodér, takže JBIG2 funguje hned po instalaci. Když potřebujete produkční kompresní poměry, zaregistrujete silnější jádro a knihovna na něj deleguje, aniž by se cokoliv změnilo ve vašem volajícím kódu
Přepnutí je jediné registrační volání. Bez zaregistrovaného backendu kodér přejde na svou vestavěnou cestu. Zaregistrujte jeden a každé následující kódování projde přes něj
uses
HPDFJBIG2;
// Query what is active, then optionally install a stronger engine.
if not IsJBIG2EncoderBackendAvailable then
// Production backend not present: HotPDF uses its built-in MMR path.
RegisterJBIG2EncoderBackend(MyVendorJBIG2Encode);
// Later, to return to the built-in behaviour:
// ClearJBIG2Backends;
Stejný háček existuje pro dekódování prostřednictvím RegisterJBIG2DecoderBackend a funkce IsJBIG2DecoderBackendAvailable ho prověří. Proto knihovna dodává malou vestavěnou cestu plus šev pro backend místo jednoho monolitického kodéru. Vestavěná cesta udržuje binárku štíhlou a bez licenčních komplikací, zatímco šev umožňuje týmu, který získal licenci na plný kodér, zapojit jej bez jakéhokoli zásahu do vrstvy zápisu PDF
Co možnosti kódování skutečně obchodují
Kódování se konfiguruje prostřednictvím záznamu TJBIG2EncodeOptions, který obsahuje pole Lossless, UseGlobalSegments, UseSymbolDictionary a LossyLevel. Obálka přizpůsobená pro komponenty THPDFJBIG2Options zpřístupňuje Lossless, UseSymbolDictionary a LossyLevel, aby je bylo možné nastavit z Object Inspectoru, a interně provádí převod na záznam. Nastavení se řídí třemi záměry
Bezeztrátová rekonstrukce zachovává každý pixel. Nastavte Lossless na True a ponechte LossyLevel na nule a dekódovaná bitmapa bude bit po bitu identická se vstupem. To je jediná bezpečná volba pro čárové kresby, technické výkresy a jakoukoliv stránku, kde vynechaný pixel může změnit význam, jako je podpis nebo razítko. Kódování se slovníkem symbolů zapíná deduplikaci uvědomující si text a je možností, která odlišuje JBIG2 od faxových filtrů. Ztrátová úroveň, celé číslo od 0 do 9, umožňuje schopnému backendu vyměnit věrnost za velikost tím, že zachází s téměř identickými značkami jako se stejným symbolem. Nula znamená bezeztrátový režim. Vestavěný kodér respektuje pouze bezeztrátovou cestu a ignoruje jakoukoli nenulovou ztrátovou úroveň, takže vyšší úrovně se uplatní až po registraci backendu, který je implementuje
var
Options: TJBIG2EncodeOptions;
begin
Options := DefaultJBIG2EncodeOptions; // Lossless True, symbol dictionary on
Options.Lossless := True;
Options.LossyLevel := 0; // 0 keeps every pixel
Options.UseSymbolDictionary := True; // dedupe repeated glyphs
// Pass Options to a backend, or let THPDFJBIG2Options carry them.
end;
Slovníky symbolů a proč naskenovaný text vítězí
Stránka naskenovaného textu není ve skutečnosti obrázkem slov. Je to tatáž písmena e vytištěná několik set krát, tatáž t, tatáž čárka, přičemž každý výskyt je mírně zarušenou kopií jednoho základního tvaru. Slovník symbolů tuto strukturu zachytí. Kodér shromáždí odlišné značky na stránce do slovníku, uloží každý tvar jednou a poté zaznamenává stránku jako seznam pozic odkazujících na záznamy slovníku. Tisíc výskytů téhož glyfu stojí jednu uloženou bitmapu plus tisíc levných umístění
Právě zde JBIG2 předbíhá CCITT Group 4. Group 4 kóduje každý skenovací řádek vůči řádku nad ním bez jakékoli představy o glyfu, takže platí plnou cenu za každé písmeno pokaždé, když se písmeno objeví. JBIG2 platí jednou. Když je tentýž slovník povýšen do proudu globálních dat na úrovni dokumentu, úspora se násobí napříč vícestránkovým skenem, protože tvary sdílené stránkou za stránkou jsou uloženy jednou pro celý soubor. U hustého textu není rozdíl zanedbatelný. Je to důvod, proč JBIG2 existuje
Obecné oblasti a MMR pro vše ostatní
Ne každý dvouúrovňový obrázek je text. Mapy, schémata, technické výkresy a smíšené stránky obsahují čárové kresby, které žádný slovník nedokáže shrnout. Pro tyto případy JBIG2 kóduje obecnou oblast, obdélník pixelů komprimovaný přímo bez jakéhokoli trénování symbolů. Standard umožňuje obecné oblasti využívat MMR, modifikované kódování Modified READ, které již používá fax Group 4 a které modeluje každý řádek pixelů vůči řádku nad ním
To je cesta, kterou HotPDF dodává ve svém vestavěném kodéru. Když není registrován žádný backend a požadavek je bezeztrátový, knihovna komprimuje bitmapu jako jednu obecnou oblast MMR a zabalí ji do struktury segmentů JBIG2, kterou vyžaduje profil PDF. Nepotřebuje žádný slovník, žádný trénovací průchod ani druhý referenční obrázek, takže je spolehlivým výchozím nastavením pro čárové kresby a smíšený dvouúrovňový obsah. Na čistém textu se nevyrovná plnému kodéru se slovníkem symbolů, ale je vždy správný, vždy bezeztrátový a vždy dostupný. Povrch kodéru pro tuto funkci tvoří jediné volání
var
Encoder: THPDFJBIG2Encoder;
ImageData: TJBIG2ByteArray;
Scanlines: TJBIG2ScanlineArray; // one byte array per row, MSB-first
W, H: Integer;
begin
// Scanlines, W and H describe a 1-bit page; each row is (W + 7) div 8 bytes.
Encoder := THPDFJBIG2Encoder.Create;
try
if Encoder.EncodeToByteArray(Scanlines, W, H, ImageData) then
// ImageData now holds a JBIG2 stream ready for a /JBIG2Decode XObject.
;
finally
Encoder.Free;
end;
end;
Zapnutí při sestavování dokumentu
Pro každodenní použití se přímo nedotýkáte třídy kodéru. HotPDF zpřístupňuje JBIG2 jako volbu komprese obrázků dokumentu. Výčet THPDFImageCompressionType zahrnuje icJBIG2 vedle možností Flate, JPEG a CCITT a dokument nese vlastnost JBIG2Options typu THPDFJBIG2Options, která uchovává nastavení použitá při výběru této komprese. Obojí nakonfigurujte před přidáním dvouúrovňových obrázků, které chcete tímto způsobem komprimovat
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.ImageCompressionType := icJBIG2; // route 1-bit images through JBIG2
Pdf.JBIG2Options.Lossless := True; // keep every pixel
Pdf.JBIG2Options.UseSymbolDictionary := True;
Pdf.JBIG2Options.LossyLevel := 0;
// Add pages and place your scanned 1-bit images here.
finally
Pdf.Free;
end;
end;
Za zmínku stojí doplněk DBGridHotPDFExport, který vykresluje TDBGrid přímo do PDF. Jeho výstup je z velké části tvořen dvouúrovňovými linkami a textem, takže dokument nakonfigurovaný pro JBIG2 udržuje tyto exporty kompaktní bez jakékoli dodatečné obsluhy z vaší strany. Dvě příbuzná témata na tomto blogu jdou hlouběji do okolního pracovního postupu. Jak jsou při sestavování sestav ukládány obrázky a fonty, naleznete v části výstup sestav s fonty a obrázky v Delphi. Když komprimovaný dokument musí splňovat archivační profil, pravidla v části validace PDF/A, PDF/X a PDF/UA v Delphi vám řeknou, které filtry daná úroveň shody přijímá. JBIG2 je součástí HotPDF Component pro Delphi a C++Builder, vedle rozhraní API pro načítání, úpravy a šifrování popsaných jinde na tomto blogu