Een gescand contract is een paar honderd dots per inch (dpi) van zwarte inkt op wit papier. Opgeslagen als een één-bit-per-pixel bitmap is het al klein, maar honderd van dergelijke pagina's blazen een PDF nog steeds op tot iets wat u niet meer zou e-mailen. Het juiste filter verandert de rekensom. JBIG2 is de compressie met de hoogste verhouding die ISO 32000-1 definieert voor bi-level afbeeldingen, en op een stapel gescande tekst halveert het routinematig wat CCITT Group 4 produceert. Dit is het filter om naar te grijpen wanneer de invoer is gefaxt, gescand of anderszins is gereduceerd tot twee kleuren, en HotPDF kan het rechtstreeks naar een PDF schrijven
Het formaat verdient deze verhouding met twee ideeën die een generieke afbeeldingscodec niet heeft. Het modelleert hoe opeenvolgingen van zwart afsteken tegen een witte achtergrond, en het merkt op dat een gescande pagina voornamelijk dezelfde paar honderd glyph-vormen duizenden keren herhaald is. Het begrijpen van beide is wat u in staat stelt de codeeropties weloverwogen te kiezen in plaats van te gissen
Waar JBIG2 in de PDF-specificatie zit
ISO 32000-1 somt JBIG2Decode op onder de streamfilters in §7.4.7, beschikbaar vanaf PDF 1.4. Het is slechts op één plaats van toepassing: image XObjects waarvan /BitsPerComponent 1 is en waarvan de kleurruimte naar één enkel kanaal oplost. Dat is precies de bedoeling. JBIG2 is een bi-level codec, dus hij concurreert nooit met DCT of JPXDecode op foto's. Hij concurreert met CCITTFaxDecode, de Group 3- en Group 4-faxfilters, op precies het soort tweekleuren-pagina dat een documentscanner produceert
De decoder verwerkt de ingebedde JBIG2-organisatie die de standaard het PDF-profiel noemt, waarbij elke afbeeldingsstream een reeks segmenten bevat in plaats van een kale bitstream. Een optionele /JBIG2Globals-stream bevat segmenten die worden gedeeld door meerdere afbeeldingen in hetzelfde document, wat het mechanisme is waarmee herhaalde content eenmalig voor een heel bestand kan worden opgeslagen in plaats van één keer per pagina. HotPDF zendt de per-afbeelding stream standaard uit en houdt het globals-kanaal vrij tenzij een backend erom vraagt
De backend-first encoder-architectuur
Een complete JBIG2-encoder is een groot stuk software, en de meest agressieve onderdelen ervan zijn van oudsher belast met patenten en verzonden onder licenties die niet bij elk product passen. HotPDF lost die spanning op door de interface van de engine te scheiden. De unit HPDFJBIG2 definieert de aanroepen die de rest van de bibliotheek doet, en er wordt een bescheiden ingebouwde encoder meegeleverd zodat JBIG2 direct uit de doos werkt. Wanneer u ratio's van productiekwaliteit nodig hebt, registreert u een sterkere engine waarnaar de bibliotheek vervolgens delegeert, zonder dat uw aanroepende code verandert
De schakelaar is een enkele registratie-aanroep. Als er geen backend geregistreerd is, valt de encoder terug op het ingebouwde pad. Registreer er een en elke daaropvolgende codering loopt erdoorheen
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;
Dezelfde "haak" bestaat voor decodering via RegisterJBIG2DecoderBackend, met IsJBIG2DecoderBackendAvailable om deze te peilen. Dit is de reden waarom een bibliotheek een klein ingebouwd pad plus een backend-naad levert in plaats van één monolithische encoder. Het ingebouwde pad houdt de binary slank en vrij van licentieverwikkelingen, terwijl de naad het een team dat een volledige encoder in licentie heeft genomen, in staat stelt deze in te pluggen zonder de PDF-schrijflaag ook maar aan te raken
Wat de codeeropties daadwerkelijk uitwisselen
Codering wordt geconfigureerd via TJBIG2EncodeOptions, een record met de velden Lossless, UseGlobalSegments, UseSymbolDictionary en LossyLevel. De componentvriendelijke wrapper THPDFJBIG2Options publiceert Lossless, UseSymbolDictionary en LossyLevel zodat ze vanuit de Object Inspector kunnen worden ingesteld, en deze converteert ze intern naar de record. Drie intenties sturen de instellingen aan
Verliesvrije reconstructie behoudt elke pixel. Stel Lossless in op True en laat LossyLevel op nul staan, en de gedecodeerde bitmap is bit-voor-bit identiek aan de invoer. Dit is de enige veilige keuze voor lijnkunst, technische tekeningen en elke pagina waar een weggevallen pixel de betekenis zou kunnen veranderen, zoals een handtekening of een stempel. Symboolwoordenboekcodering schakelt tekstbewuste deduplicatie in en is de optie die JBIG2 onderscheidt van de faxfilters. Het lossy-niveau, een geheel getal van 0 tot 9, stelt een capabele backend in staat getrouwheid in te ruilen voor grootte door bijna identieke markeringen als hetzelfde symbool te behandelen. Nul betekent verliesvrij. De ingebouwde encoder respecteert alleen het verliesvrije pad en negeert elk lossy-niveau ongelijk aan nul, dus de hogere niveaus treden pas in werking zodra een backend is geregistreerd die ze implementeert
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;
Symboolwoordenboeken en waarom tekstscans winnen
Een pagina met gescande tekst is niet echt een afbeelding van woorden. Het is dezelfde letter e die enkele honderden keren is afgedrukt, dezelfde t, dezelfde komma, waarbij elke instantie een ietwat luidruchtige kopie is van één onderliggende vorm. Een symboolwoordenboek legt die structuur vast. De encoder verzamelt de verschillende markeringen op de pagina in een woordenboek, slaat elke vorm één keer op en registreert vervolgens de pagina als een lijst met posities die verwijzen naar lemma's in het woordenboek. Duizend keer voorkomen van dezelfde glyph kost één opgeslagen bitmap plus duizend goedkope plaatsingen
Dit is precies waar JBIG2 CCITT Group 4 voorbijstreeft. Group 4 codeert elke scanlijn tegen de lijn erboven zonder notie van een glyph, dus het betaalt de volledige kosten van elke letter elke keer dat de letter verschijnt. JBIG2 betaalt één keer. Wanneer hetzelfde woordenboek wordt gepromoveerd naar de globals-stream op documentniveau, stapelt de besparing zich op over een scan van meerdere pagina's, omdat de vormen die gedeeld worden door pagina na pagina eenmalig voor het hele bestand worden opgeslagen. Op compacte tekst is het verschil niet marginaal. Het is de reden dat JBIG2 bestaat
Generieke regio en MMR voor al het andere
Niet elke bi-level afbeelding is tekst. Kaarten, schema's, technische tekeningen en gemengde pagina's bevatten lijnkunst die geen enkel woordenboek kan samenvatten. Daarvoor codeert JBIG2 een generieke regio, een rechthoek van pixels die direct is gecomprimeerd zonder enige symbooltraining. De standaard staat toe dat een generieke regio MMR gebruikt, de 'modified modified READ'-codering die Group 4 fax al gebruikt, die elke rij pixels modelleert ten opzichte van de rij erboven
Dit is het pad dat HotPDF in de ingebouwde encoder levert. Wanneer er geen backend is geregistreerd en de aanvraag verliesvrij is, comprimeert de bibliotheek de bitmap als een enkele generieke MMR-regio en wikkelt deze in de JBIG2-segmentstructuur die het PDF-profiel vereist. Er is geen woordenboek, geen trainingsstap en geen tweede afbeelding om naar te verwijzen nodig, dus het is de betrouwbare standaard voor lijnkunst en gemengde bi-level content. Het zal een volledige symboolwoordenboekencoder op pure tekst niet evenaren, maar het is altijd correct, altijd verliesvrij en altijd aanwezig. Het encoderoppervlak ervoor is één aanroep
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;
Het inschakelen wanneer u een document bouwt
Voor dagelijks gebruik raakt u de encoder-klasse niet rechtstreeks aan. HotPDF stelt JBIG2 beschikbaar als een afbeeldingscompressiekeuze op het document. De enumeratie THPDFImageCompressionType bevat icJBIG2 naast de Flate-, JPEG- en CCITT-opties, en het document bevat een eigenschap JBIG2Options van het type THPDFJBIG2Options die de instellingen bevat die worden gebruikt wanneer die compressie is geselecteerd. Configureer beide voordat u de bi-level afbeeldingen toevoegt die u op deze manier wilt comprimeren
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;
Eén gemak dat het vermelden waard is, is de DBGridHotPDFExport-add-on, die een TDBGrid rechtstreeks naar een PDF rendert. De uitvoer ervan bestaat voornamelijk uit bi-level regels en tekst, dus een document dat voor JBIG2 is geconfigureerd, houdt die exports compact zonder dat u hier extra handelingen voor hoeft te verrichten. Twee gerelateerde onderwerpen op deze blog gaan dieper in op de omliggende workflow. Zie rapportuitvoer met lettertypen en afbeeldingen in Delphi voor de manier waarop afbeeldingen en lettertypen worden neergelegd wanneer u rapporten bouwt. Wanneer een gecomprimeerd document moet voldoen aan een archiveringsprofiel, vertellen de regels in PDF/A-, PDF/X- en PDF/UA-validatie in Delphi u welke filters een bepaald conformiteitsniveau accepteert. JBIG2 wordt meegeleverd als onderdeel van de HotPDF Component voor Delphi en C++Builder, naast de API's voor laden, bewerken en versleutelen die hier elders worden behandeld