Un contract scanat este câteva sute de puncte pe inch de cerneală neagră pe hârtie albă. Stocat ca bitmap de un bit per pixel este deja mic, totuși o sută de astfel de pagini umflă un PDF dincolo de orice ați trimite prin email. Filtrul potrivit schimbă aritmetica. JBIG2 este compresia cu cel mai mare raport pe care ISO 32000-1 o definește pentru imagini bitonale, și pe un set de text scanat înjumătățește în mod obișnuit ceea ce produce CCITT Group 4. Acesta este filtrul la care să apelați când intrarea este transmisă prin fax, scanată sau altfel redusă la două culori, iar HotPDF îl poate scrie direct într-un PDF
Formatul câștigă raportul cu două idei pe care un codec generic de imagini nu le are. Modelează cum șirurile negre stau pe un fundal alb, și observă că o pagină scanată este în mare parte aceleași câteva sute de forme de glife repetate de mii de ori. Înțelegerea ambelor este ceea ce vă permite să alegeți deliberat opțiunile de codare în loc să ghiciți
Locul JBIG2 în specificația PDF
ISO 32000-1 listează JBIG2Decode printre filtrele de flux din §7.4.7, disponibil începând cu PDF 1.4. Se aplică unui singur loc: XObjects de imagine al căror /BitsPerComponent este 1 și al căror spațiu de culoare se rezolvă la un singur canal. Acesta este scopul întreg. JBIG2 este un codec bitonal, deci nu concurează niciodată cu DCT sau JPXDecode la fotografii. Concurează cu CCITTFaxDecode, filtrele fax Group 3 și Group 4, exact pe tipul de pagină bitonală pe care o produce un scanner de documente
Decodificatorul consumă organizarea JBIG2 încorporată pe care standardul o numește profilul PDF, unde fiecare flux de imagine conține o secvență de segmente mai degrabă decât un bitstream simplu. Un flux opțional /JBIG2Globals transportă segmente partajate între mai multe imagini din același document, care este mecanismul ce permite conținutului repetat să fie stocat o singură dată pentru un întreg fișier mai degrabă decât o dată per pagină. HotPDF emite fluxul per-imagine implicit și ține canalul global liber dacă un backend nu îl solicită
Arhitectura encoder cu backend-first
Un encoder JBIG2 complet este o bucată mare de software, iar cele mai agresive părți au fost istoric împovărate de brevete și livrate sub licențe care nu sunt potrivite pentru fiecare produs. HotPDF rezolvă această tensiune separând interfața de motor. Unitatea HPDFJBIG2 definește apelurile pe care restul bibliotecii le face, și livrează un encoder integrat modest astfel încât JBIG2 funcționează imediat. Când aveți nevoie de rapoarte de calitate de producție înregistrați un motor mai puternic și biblioteca îi deleagă, fără nicio modificare a codului dvs. de apel
Comutarea este un singur apel de înregistrare. Fără niciun backend înregistrat, encoderul cade înapoi pe calea sa integrată. Înregistrați unul și fiecare codare ulterioară rulează prin acesta
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;
Același hook există pentru decodare prin RegisterJBIG2DecoderBackend, cu IsJBIG2DecoderBackendAvailable pentru a-l sonda. Acesta este motivul pentru care o bibliotecă livrează o cale integrată mică plus o joncțiune de backend mai degrabă decât un encoder monolitic. Calea integrată menține binarul compact și lipsit de complicații de licență, în timp ce joncțiunea permite unei echipe care a licențiat un encoder complet să îl conecteze fără a atinge deloc stratul de scriere PDF
Ce schimbă de fapt opțiunile de codare
Codarea este configurată prin TJBIG2EncodeOptions, o înregistrare cu câmpurile Lossless, UseGlobalSegments, UseSymbolDictionary, și LossyLevel. Wrapper-ul prietenos cu componente THPDFJBIG2Options publică Lossless, UseSymbolDictionary, și LossyLevel astfel încât să poată fi setate din Object Inspector, și convertește intern la înregistrare. Trei intenții conduc setările
Reconstrucția fără pierderi păstrează fiecare pixel. Setați Lossless la True și lăsați LossyLevel la zero, iar bitmap-ul decodat este identic bit-cu-bit cu intrarea. Aceasta este singura alegere sigură pentru grafică de linie, desene tehnice, și orice pagină unde un pixel eliminat ar putea schimba înțelesul, precum o semnătură sau o ștampilă. Codarea cu dicționar de simboluri activează deduplicarea conștientă de text și este opțiunea care separă JBIG2 de filtrele fax. Nivelul lossy, un întreg de la 0 la 9, permite unui backend capabil să schimbe fidelitatea pentru dimensiune tratând marcajele aproape identice ca același simbol. Zero înseamnă fără pierderi. Encoderul integrat onorează numai calea fără pierderi și ignoră orice nivel lossy diferit de zero, deci nivelurile superioare intră în vigoare numai odată ce un backend care le implementează este înregistrat
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;
Dicționarele de simboluri și de ce scanările de text câștigă
O pagină de text scanat nu este cu adevărat o imagine de cuvinte. Este aceeași literă e tipărită de câteva sute de ori, același t, aceeași virgulă, fiecare instanță o copie ușor zgomotoasă a unei forme de bază. Un dicționar de simboluri capturează această structură. Encoderul colectează marcajele distincte de pe pagină într-un dicționar, stochează fiecare formă o dată, și apoi înregistrează pagina ca o listă de poziții care fac referire la intrările din dicționar. O mie de apariții ale aceluiași glif costă un bitmap stocat plus o mie de plasamente ieftine
Acesta este exact locul unde JBIG2 depășește CCITT Group 4. Group 4 codifică fiecare linie de scanare față de linia de deasupra fără nicio noțiune de glifă, deci plătește costul complet al fiecărei litere de fiecare dată când apare litera. JBIG2 plătește o singură dată. Când același dicționar este promovat la fluxul global la nivel de document, economia se cumulează pe o scanare multi-pagină, deoarece formele partajate pagină după pagină sunt stocate o singură dată pentru întregul fișier. Pe text dens diferența nu este marginală. Este motivul pentru care există JBIG2
Regiuni generice și MMR pentru orice altceva
Nu fiecare imagine bitonală este text. Hărțile, schemele, desenele tehnice și paginile mixte au grafică de linie pe care niciun dicționar nu o poate rezuma. Pentru acestea, JBIG2 codifică o regiune generică, un dreptunghi de pixeli comprimat direct fără niciun antrenament de simboluri. Standardul permite unei regiuni generice să folosească MMR, codarea modified modified READ pe care faxul Group 4 o folosește deja, care modelează fiecare rând de pixeli față de rândul de deasupra
Aceasta este calea pe care HotPDF o livrează în encoderul său integrat. Când niciun backend nu este înregistrat și solicitarea este fără pierderi, biblioteca comprimă bitmap-ul ca o singură regiune generică MMR și o împachetează în structura de segment JBIG2 pe care profilul PDF o cere. Nu necesită niciun dicționar, nicio trecere de antrenament și nicio a doua imagine la care să facă referire, deci este implicit-ul fiabil pentru grafică de linie și conținut bitonal mixt. Nu va egala un encoder complet cu dicționar de simboluri pe text pur, dar este întotdeauna corect, întotdeauna fără pierderi și întotdeauna prezent. Suprafața encoder pentru acesta este un singur apel
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;
Activarea când construiți un document
Pentru utilizarea zilnică nu atingeți direct clasa encoder. HotPDF expune JBIG2 ca opțiune de compresie a imaginilor pe document. Enumerarea THPDFImageCompressionType include icJBIG2 alături de opțiunile Flate, JPEG și CCITT, iar documentul poartă o proprietate JBIG2Options de tip THPDFJBIG2Options care conține setările folosite când este selectată compresia respectivă. Configurați ambele înainte de a adăuga imaginile bitonale pe care doriți să le comprimați în acest fel
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;
Un plus de comoditate de menționat este add-on-ul DBGridHotPDFExport, care redă un TDBGrid direct în PDF. Ieșirea sa constă în mare parte din linii bitonale și text, deci un document configurat pentru JBIG2 menține acele exporturi compacte fără nicio gestionare suplimentară din partea dvs. Două subiecte conexe pe acest blog aprofundează fluxul de lucru înconjurător. Pentru cum sunt amplasate imaginile și fonturile când construiți rapoarte, consultați ieșire de rapoarte cu fonturi și imagini în Delphi. Când un document comprimat trebuie să satisfacă un profil de arhivare, regulile din validarea PDF/A, PDF/X și PDF/UA în Delphi vă spun ce filtre acceptă un anumit nivel de conformitate. JBIG2 este livrat ca parte din HotPDF Component pentru Delphi și C++Builder, alături de API-urile de încărcare, editare și criptare acoperite în altă parte pe acest blog