Egy beszkennelt szerződés hüvelykenként néhány száz pontnyi fekete tintát jelent a fehér papíron. Egy bit per pixel bittérképként tárolva már amúgy is kicsi, de száz ilyen oldal még mindig annyira megnövel egy PDF-et, hogy azt már nem lehetne e-mailben elküldeni. A megfelelő szűrő megváltoztatja az aritmetikát. A JBIG2 a legnagyobb arányú tömörítés, amelyet az ISO 32000-1 a kéttónusú képekre meghatároz, és egy halom beolvasott szöveg esetében rutinszerűen megfelezi a CCITT Group 4 eredményét. Ehhez a szűrőhöz kell nyúlni, ha a bemenet faxolt, szkennelt vagy más módon két színre redukált, és a HotPDF képes ezt közvetlenül egy PDF-be írni
A formátum ezt az arányt két olyan ötlettel éri el, amellyel egy általános képkodek nem rendelkezik. Modellezi, hogyan helyezkednek el a fekete vonalak a fehér háttéren, és észreveszi, hogy egy szkennelt oldal nagyrészt ugyanabból a néhány száz glifaformából áll, több ezerszer ismétlődve. Mindkettő megértése teszi lehetővé, hogy a kódolási beállításokat találgatás helyett tudatosan válasszuk ki
Hol helyezkedik el a JBIG2 a PDF specifikációban
Az ISO 32000-1 a JBIG2Decode szűrőt a §7.4.7-es pontban a streamszűrők között sorolja fel, amely a PDF 1.4-től kezdve érhető el. Csak egyetlen helyen alkalmazható: azokon a kép XObject objektumokon, amelyeknél a /BitsPerComponent értéke 1, és amelyek színtere egyetlen csatornára oldható fel. Pontosan ez a lényeg. A JBIG2 egy kéttónusú kodek, így a fényképeken soha nem versenyez a DCT vagy a JPXDecode eljárással. A CCITTFaxDecode szűrővel, azaz a Group 3 és Group 4 faxszűrőkkel versenyez pontosan azokon a kéttónusú oldalakon, amelyeket a dokumentumszkennerek állítanak elő
A dekóder a szabvány által PDF profilnak nevezett beágyazott JBIG2 szervezést használja, ahol minden képfolyam szegmensek sorozatát tartalmazza egy puszta bitfolyam helyett. Egy opcionális /JBIG2Globals folyam olyan szegmenseket hordoz, amelyeken ugyanazon dokumentum több képe osztozik, és ez az a mechanizmus, amely lehetővé teszi, hogy az ismétlődő tartalmat oldalanként egyszer helyett egy egész fájlra vonatkozóan csak egyszer tárolják. A HotPDF alapértelmezés szerint a képenkénti folyamot bocsátja ki, és szabadon hagyja a globális csatornát, kivéve, ha egy backend azt kéri
A backend-első kódoló architektúra
Egy teljes JBIG2 kódoló egy nagyméretű szoftver, és a legagresszívebb részeit történelmileg szabadalmak terhelték, és olyan licencek alatt szállították, amelyek nem minden termékhez illenek. A HotPDF ezt a feszültséget az interfész és a motor szétválasztásával oldja meg. A HPDFJBIG2 egység meghatározza azokat a hívásokat, amelyeket a könyvtár többi része végez, és egy szerény beépített kódolóval érkezik, így a JBIG2 a dobozból kivéve azonnal működik. Ha termelési szintű arányokra van szükség, regisztrálni kell egy erősebb motort, és a könyvtár arra delegálja a feladatot, anélkül, hogy a hívókódot meg kellene változtatni
A váltás egyetlen regisztrációs hívás. Ha nincs backend regisztrálva, a kódoló visszatér a beépített útvonalra. Ha regisztrál egyet, akkor minden további kódolás azon fut keresztül
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;
Ugyanez a horog létezik a dekódoláshoz a RegisterJBIG2DecoderBackend híváson keresztül, az IsJBIG2DecoderBackendAvailable segítségével történő lekérdezéssel. Ez az oka annak, hogy egy könyvtár egyetlen monolitikus kódoló helyett egy kis beépített útvonalat és egy backend varratot szállít. A beépített útvonal karcsú és licenckötöttségektől mentes bináris fájlt eredményez, míg a varrat lehetővé teszi, hogy a teljes kódolót licencelő csapat a PDF író réteg érintése nélkül csatlakoztassa azt
Mit is cserélnek valójában a kódolási opciók
A kódolás a TJBIG2EncodeOptions rekordokon keresztül konfigurálható, amely a Lossless, UseGlobalSegments, UseSymbolDictionary és LossyLevel mezőket tartalmazza. A komponensbarát THPDFJBIG2Options burkoló közzéteszi a Lossless, UseSymbolDictionary és LossyLevel mezőket, így azok az Object Inspector felületéről beállíthatók, és a belső működés során rekorddá alakulnak át. Három szándék vezérli a beállításokat
A veszteségmentes helyreállítás minden pixelt megtart. Állítsa a Lossless értéket True értékre, és hagyja a LossyLevel értéket nullán, és a dekódolt bittérkép bitről bitre azonos lesz a bemenettel. Ez az egyetlen biztonságos választás a vonalrajzok, műszaki rajzok és minden olyan oldal esetében, ahol egy kieső pixel megváltoztathatja a jelentést, mint például egy aláírás vagy egy bélyegző esetében. A szimbólumszótár kódolás bekapcsolja a szövegtudatos duplikáció kiszűrést, és ez az a funkció, amely megkülönbözteti a JBIG2 kodeket a faxszűrőktől. A veszteséges szint, amely egy 0 és 9 közötti egész szám, lehetővé teszi a megfelelő backend számára a pontosság és a méret közötti cserét a közel azonos jelzések azonos szimbólumként való kezelésével. A nulla veszteségmenteset jelent. A beépített kódoló csak a veszteségmentes utat tiszteli, és figyelmen kívül hagyja a nem nulla veszteséges szintet, így a magasabb szintek csak akkor lépnek érvénybe, ha egy azokat implementáló backend regisztrálva van
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;
Szimbólumszótárak és a szövegszkennelések előnyei
Egy beszkennelt szöveges oldal valójában nem szavak képe. Ez ugyanaz az e betű többszázszor kinyomtatva, ugyanaz a t, ugyanaz a vessző, minden egyes példány egy alapforma kissé zajos másolata. Egy szimbólumszótár rögzíti ezt a struktúrát. A kódoló összegyűjti az oldalon lévő különböző jeleket egy szótárba, minden alakzatot egyszer tárol, majd rögzíti az oldalt pozíciók listájaként, amelyek a szótárbejegyzésekre hivatkoznak. Ugyanannak a glifának ezer előfordulása egy tárolt bittérképbe és ezer olcsó elhelyezésbe kerül
Pontosan ez az, ahol a JBIG2 megelőzi a CCITT Group 4 formátumot. A Group 4 formátum minden pásztázási vonalat a felette lévő vonalhoz kódol a glifák fogalma nélkül, így minden egyes betű minden megjelenésekor megfizeti annak teljes költségét. A JBIG2 egyszer fizet. Amikor ugyanezt a szótárat előléptetik a dokumentumszintű globális folyamra, a megtakarítás többszöröződik egy többoldalas szkennelés során, mivel az oldalakon megosztott formákat az egész fájl számára csak egyszer tárolják. Sűrű szöveg esetén a különbség nem marginális. Ez az oka a JBIG2 létezésének
Általános régió és MMR minden máshoz
Nem minden kéttónusú kép szöveg. A térképek, vázlatok, műszaki rajzok és vegyes oldalak olyan vonalas grafikákkal rendelkeznek, amelyeket egyetlen szótár sem tud összefoglalni. Ezekhez a JBIG2 egy általános régiót kódol, amely a pixelek olyan téglalapja, amelyet közvetlenül tömörítenek szimbólumképzés nélkül. A szabvány lehetővé teszi, hogy egy általános régió az MMR formátumot használja, vagyis azt a módosított módosított READ kódolást, amelyet a Group 4 fax már használ, és amely a pixelek minden sorát a felette lévő sorhoz modellezi
Ezt az útvonalat a HotPDF a beépített kódolójában szállítja. Ha nincs backend regisztrálva, és a kérés veszteségmentes, a könyvtár egyetlen MMR általános régióként tömöríti a bittérképet, és a PDF profil által megkövetelt JBIG2 szegmensstruktúrába csomagolja. Nincs szüksége szótárra, betanításra, sem második hivatkozási képre, így megbízható alapértelmezett választás vonalrajzokhoz és vegyes kéttónusú tartalmakhoz. Tiszta szöveg esetén nem fog egyezni egy teljes szimbólumszótár kódolóval, de mindig helyes, mindig veszteségmentes, és mindig jelen van. A kódoló felülete ehhez egyetlen hívás
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;
Bekapcsolás dokumentum építésekor
A mindennapi használathoz nem kell közvetlenül megérintenie a kódoló osztályt. A HotPDF a JBIG2 formátumot a dokumentumon kép tömörítési választásként teszi elérhetővé. A THPDFImageCompressionType felsorolás a Flate, JPEG és CCITT opciók mellett tartalmazza a icJBIG2 opciót, és a dokumentum egy THPDFJBIG2Options típusú JBIG2Options tulajdonsággal rendelkezik, amely a tömörítés kiválasztásakor használt beállításokat tartalmazza. Konfigurálja mindkettőt, mielőtt hozzáadná az ezen a módon tömöríteni kívánt kéttónusú képeket
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;
Érdemes megjegyezni a DBGridHotPDFExport kiegészítőt, amely egy TDBGrid rácsot közvetlenül egy PDF-be jelenít meg. Kimenete nagyrészt kéttónusú szabályokból és szövegből áll, így a JBIG2 formátumra konfigurált dokumentum minden extra beavatkozás nélkül tartja tömören ezeket az exportálásokat. Ezen a blogon két kapcsolódó téma mélyebben foglalkozik a környező munkafolyamattal. Arról, hogy a képek és a betűtípusok hogyan kerülnek elhelyezésre jelentések építésekor, lásd a jelentéskészítés betűtípusokkal és képekkel Delphiben című részt. Ha egy tömörített dokumentumnak meg kell felelnie egy archiválási profilnak, a PDF/A, PDF/X és PDF/UA validáció Delphiben szabályai megmondják, hogy egy adott megfelelőségi szint mely szűrőket fogadja el. A JBIG2 a HotPDF Component részeként érkezik a Delphi és a C++Builder rendszerekhez, a máshol itt tárgyalt betöltési, szerkesztési és titkosítási API-k mellett