Odborný článok

Natívna komprimácia JBIG2 dvojúrovňových obrázkov v Delphi PDF súboroch

Naskenovaná zmluva je niekoľko stoviek bodov na palec čierneho atramentu na bielom papieri. Uložená ako bitová mapa s jedným bitom na pixel je už sama o sebe malá, no sto takýchto stránok stále nafúkne PDF nad rámec toho, čo by ste odoslali e-mailom. Správny filter zmení aritmetiku. JBIG2 je komprimácia s najvyšším pomerom, ktorú norma ISO 32000-1 definuje pre dvojúrovňové obrázky, a pri skupinách naskenovaného textu rutinne znižuje veľkosť na polovicu oproti tomu, čo produkuje CCITT Group 4. Toto je filter, po ktorom siahnete, keď vstup pochádza z faxu, skenera alebo je inak redukovaný na dve farby, a HotPDF ho dokáže priamo zapísať do PDF

Formát dosahuje tento pomer vďaka dvom myšlienkam, ktoré bežný obrázkový kodek nemá. Modeluje, ako čierne úseky ležia na bielom pozadí, a rozoznáva, že naskenovaná stránka pozostáva prevažne z niekoľkých stoviek rovnakých tvarov glyfov opakovaných tisíckrát. Pochopenie oboch aspektov vám umožní zámer​ne vyberať možnosti kódovania namiesto hádania

Kde sa JBIG2 nachádza v špecifikácii PDF

Norma ISO 32000-1 uvádza JBIG2Decode medzi filtruváciami streamov v §7.4.7, dostupné od PDF 1.4. Vzťahuje sa len na jedno miesto: obrazové objekty XObject, ktorých hodnota /BitsPerComponent je 1 a farebný priestor sa rozkladá na jediný kanál. To je celý zmysel. JBIG2 je dvojúrovňový kodek, takže nikdy nesúperí s DCT alebo JPXDecode pri fotografiách. Súperí s CCITTFaxDecode, faxovými filtrami Group 3 a Group 4, práve pri type dvojtónovej stránky, ktorú produkuje dokumentový skener

Dekodér spracúva vloženú organizáciu JBIG2, ktorú norma označuje ako PDF profil, kde každý obrazový stream obsahuje sekvenciu segmentov namiesto holého bitového toku. Voliteľný stream /JBIG2Globals prenáša segmenty zdieľané naprieč viacerými obrázkami v tom istom dokumente — to je mechanizmus, ktorý umožňuje uložiť opakujúci sa obsah raz pre celý súbor namiesto raz na stránku. HotPDF predvolene vysiela stream per-image a kanál globals nechá voľný, pokiaľ o to backend nepožiada

Architektúra kódovača s prioriotou backendu

Kompletný kódovač JBIG2 je rozsiahly softvér a jeho najagresívnejšie časti boli historicky zaťažené patentmi a distribuované pod licenciami, ktoré nevyhovujú každému produktu. HotPDF toto napätie rieši oddelením rozhrania od motora. Jednotka HPDFJBIG2 definuje volania, ktoré zvyšok knižnice vykonáva, a obsahuje skromný vstavaný kódovač, aby JBIG2 fungoval hneď po nainštalovaní. Keď potrebujete produkčné kompresné pomery, zaregistrujete silnejší motor a knižnica mu deleguje prácu bez akejkoľvek zmeny vo vašom kóde

Prepínanie sa vykoná jediným registračným volaním. Bez zaregistrovaného backendu kódovač spadne späť na vstavaný postup. Zaregistrujte ho a každé ďalšie kódovanie prebehne cez neho

Diagram švu JBIG2 enkodéra HotPDF v HPDFJBIG2, ktorý odovzdá kódovanie licencovanému registrovanému backendu rešpektujúcemu LossyLevel 0 až 9, keď je nainštalovaný, a inak používa vstavanú bezstratovú generickú oblasť MMR, než zabalí výstup do image XObject JBIG2Decode s voliteľným JBIG2Globals
Hneď z krabice vstavaná MMR cesta odpovedá na každé volanie, zatiaľ čo licencovaný engine prevezme v momente, keď sa zaregistruje cez seam
uses
  HPDFJBIG2;

// Zistite, čo je aktívne, a potom prípadne nainštalujte výkonnejší engine
if not IsJBIG2EncoderBackendAvailable then
  // Produkčný backend nie je prítomný: HotPDF používa vstavanú cestu MMR
  RegisterJBIG2EncoderBackend(MyVendorJBIG2Encode);

// Neskôr, ak sa chcete vrátiť k vstavanému správaniu:
// ClearJBIG2Backends;

Rovnaký háčik existuje pre dekódovanie prostredníctvom RegisterJBIG2DecoderBackend, pričom IsJBIG2DecoderBackendAvailable slúži na jeho overenie. Preto knižnica dodáva malý vstavaný postup plus švík backendu namiesto jedného monolitického kódovača. Vstavaný postup udržuje binárny súbor štíhlym a oslobodeným od licenčných záväzkov, zatiaľ čo švík umožňuje tímu, ktorý si licencoval plný kódovač, zapojiť ho bez toho, aby sa vôbec dotýkal vrstvy zápisu PDF

Čo možnosti kódovania skutočne obchodujú

Kódovanie sa konfiguruje cez TJBIG2EncodeOptions, záznam s poliami Lossless, UseGlobalSegments, UseSymbolDictionary a LossyLevel. Obal priateľský ku komponentom THPDFJBIG2Options zverejňuje Lossless, UseSymbolDictionary a LossyLevel, aby ich bolo možné nastaviť z Inšpektora objektov, a interne ich prevádza na záznam. Tri zámery riadia nastavenia

Bezstratová rekonštrukcia zachováva každý pixel. Nastavte Lossless na True a nechajte LossyLevel na nule a dekódovaná bitmapa bude bit za bitom identická so vstupom. Toto je jediná bezpečná voľba pre čiarové umenie, technické výkresy a akúkoľvek stránku, kde by chýbajúci pixel mohol zmeniť význam, napríklad podpis alebo pečiatka. Kódovanie slovníka symbolov zapína deduplikáciu s vedomosťou textu a je voľbou, ktorá odlišuje JBIG2 od faxových filtrov. Stratová úroveň, celé číslo od 0 do 9, umožňuje schopnému backendu obchodovať vernosť za veľkosť tým, že skoro identické značky považuje za rovnaký symbol. Nula znamená bezstratové. Vstavaný kódovač rešpektuje len bezstratový postup a ignoruje akúkoľvek nenulovú stratovú úroveň, takže vyššie úrovne sa uplatnia až po zaregistrovaní backendu, ktorý ich implementuje

var
  Options: TJBIG2EncodeOptions;
begin
  Options := DefaultJBIG2EncodeOptions;   // Lossless True, slovník symbolov zapnutý
  Options.Lossless := True;
  Options.LossyLevel := 0;                // 0 zachová každý pixel
  Options.UseSymbolDictionary := True;    // odstráňte duplicitné glyfy
  // Odovzdajte Options backendu alebo ich nechajte niesť v THPDFJBIG2Options
end;

Slovníky symbolov a prečo naskenovaný text vyhráva

Stránka naskenovaného textu nie je naozaj obrázok slov. Je to to isté písmeno e vytlačené niekoľko stokrát, to isté t, tá istá čiarka — každá výskyt je mierne zašumená kópia jedného základného tvaru. Slovník symbolov zachytáva túto štruktúru. Kódovač zhromažďuje odlišné značky na stránke do slovníka, každý tvar uloží raz a potom zaznamená stránku ako zoznam pozícií odkazujúcich na záznamy slovníka. Tisíc výskytov toho istého glyfu stojí jednu uloženú bitmapu plus tisíc lacných umiestnení

Práve tu JBIG2 predbehne CCITT Group 4. Group 4 kóduje každý riadok skenu oproti riadku nad ním bez akéhokoľvek pojmu o glyfe, takže platí plnú cenu každého písmena zakaždým, keď sa písmeno objaví. JBIG2 zaplatí raz. Keď sa rovnaký slovník povýši na stream globálov na úrovni dokumentu, úspora sa znásobuje naprieč viacestránkovým skenovaním, pretože tvary zdieľané stránkou za stránkou sú uložené jedenkrát pre celý súbor. Pri hustom texte nie je rozdiel okrajový. To je dôvod, prečo JBIG2 existuje

Diagram HotPDF porovnávajúci ako CCITT Group 4 účtuje každý výskyt glyfu osobitne, zatiaľ čo JBIG2 uchová každý odlišný tvar raz v slovníku symbolov a umiestni ho lacnou referenciou, povyšujúc zdieľané tvary na tok JBIG2Globals na úrovni dokumentu, takže viacstranové skeny sa uchovajú raz na tvar
Opakované glyfy usadia do slovníka, takže strana fakturuje jednu bitmapu na tvar plus lacné umiestnenia a globals roztiahnu úsporu naprieč stranami

Všeobecná oblasť a MMR pre všetko ostatné

Nie každý dvojúrovňový obrázok je text. Mapy, schémy, technické výkresy a zmiešané stránky obsahujú čiarové umenie, ktoré žiadny slovník nedokáže zhrnúť. Pre tieto prípady JBIG2 kóduje všeobecnú oblasť — obdĺžnik pixelov komprimovaný priamo bez akéhokoľvek trénovania symbolov. Norma umožňuje všeobecnej oblasti používať MMR, modifikované modifikované READ kódovanie, ktoré fax Group 4 už používa a ktoré modeluje každý riadok pixelov oproti riadku nad ním

Toto je postup, ktorý HotPDF dodáva vo svojom vstavanom kódovači. Keď nie je zaregistrovaný žiadny backend a požiadavka je bezstratová, knižnica komprimuje bitmapu ako jedinú MMR všeobecnú oblasť a zabalí ju do štruktúry segmentov JBIG2 požadovanej PDF profilom. Nepotrebuje žiadny slovník, žiadny tréningový prechod ani žiadny druhý obrázok na referenciu, takže je spoľahlivým predvoleným pre čiarové umenie a zmiešaný dvojúrovňový obsah. Na čistom texte sa nevyrovná plnému kódovaču so slovníkom symbolov, ale je vždy správny, vždy bezstratový a vždy prítomný. Povrch kódovača pre neho je jedno volanie

var
  Encoder: THPDFJBIG2Encoder;
  ImageData: TJBIG2ByteArray;
  Scanlines: TJBIG2ScanlineArray;  // jedno bajtové pole na riadok, od najvýznamnejšieho bitu
  W, H: Integer;
begin
  // Scanlines, W a H opisujú 1-bitovú stranu; každý riadok má (W + 7) div 8 bajtov
  Encoder := THPDFJBIG2Encoder.Create;
  try
    if Encoder.EncodeToByteArray(Scanlines, W, H, ImageData) then
      // ImageData teraz obsahuje prúd JBIG2 pripravený pre XObject /JBIG2Decode
      ;
  finally
    Encoder.Free;
  end;
end;

Zapnutie pri vytváraní dokumentu

Pri bežnom používaní sa triedy kódovača priamo nedotýkate. HotPDF sprístupňuje JBIG2 ako voľbu komprimácie obrázkov v dokumente. Enumerácia THPDFImageCompressionType zahŕňa icJBIG2 vedľa možností Flate, JPEG a CCITT, a dokument obsahuje vlastnosť JBIG2Options typu THPDFJBIG2Options, ktorá obsahuje nastavenia používané pri výbere tejto komprimácie. Nakonfigurujte oboje pred pridaním dvojúrovňových obrázkov, ktoré chcete takto komprimovať

var
  Pdf: THotPDF;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.ImageCompressionType := icJBIG2;     // veďte 1-bitové obrázky cez JBIG2
    Pdf.JBIG2Options.Lossless := True;        // zachovajte každý pixel
    Pdf.JBIG2Options.UseSymbolDictionary := True;
    Pdf.JBIG2Options.LossyLevel := 0;
    // Pridajte strany a sem umiestnite naskenované 1-bitové obrázky
  finally
    Pdf.Free;
  end;
end;

Jedna pohodlná funkcia, ktorú stojí za zmienku, je doplnok DBGridHotPDFExport, ktorý vykreslí TDBGrid priamo do PDF. Jeho výstup je prevažne dvojúrovňové čiary a text, takže dokument nakonfigurovaný pre JBIG2 udržiava tieto exporty kompaktné bez akéhokoľvek ďalšieho spracovania z vašej strany. Dve súvisiace témy na tomto blogu sa hlbšie venujú okolitému pracovnému postupu. Ako sa obrázky a písma ukladajú pri vytváraní zostáv nájdete v článku výstup zostavy s písomami a obrázkami v Delphi. Keď komprimovaný dokument musí spĺňať archivačný profil, pravidlá v článku validácia PDF/A, PDF/X a PDF/UA v Delphi vám povedia, ktoré filtre daná úroveň zhody akceptuje. JBIG2 je súčasťou HotPDF Delphi Component pre Delphi a C++Builder, vedľa rozhraní API pre načítanie, úpravu a šifrovanie, ktoré sú pokryté na iných miestach tu