Et skannet medisinsk objektglass, en flis fra en flyfotografering, et filmbilde arkivert med fullt dynamisk område. Dette er bildene som ankommer som JPEG 2000, og de ankommer slik av en grunn. Formatet beholder 12 eller 16 biter per kanal, komprimerer med en wavelet-transformasjon i stedet for blokk-DCT-en som JPEG bruker, og kan kode det samme bildet enten tapsfritt eller med tap fra én kodestrøm. Når et dokument bygget fra disse kildene skal bli en PDF, må bildet reise gjennom et filter som PDF-spesifikasjonen reserverer for nøyaktig denne kodeken
HotPDF v2.228.0 gjenopprettet en fungerende JPEG 2000-dekodingsmotor for den banen. En tidligere versjon hadde levert enheten med stub-funksjoner som returnerte nil, så API-et eksisterte, men dekodet ingenting. Den nåværende motoren binder OpenJPEG 2.5.4 statisk og gjør en JP2- eller J2K-kilde til piksler som HotPDF kan plassere på en side
JPXDecode-filteret i PDF
ISO 32000-1 definerer JPXDecode-filteret i §7.4.9. Et PDF-bilde-XObject navngir komprimeringen sin i strømordbokens /Filter-oppføring, og JPXDecode er verdien som sier at strømdataene er en JPEG 2000-kodestrøm i stedet for basis-JPEG-en som /DCTDecode bærer. Filteret er det som lar en PDF holde wavelet-komprimerte bildedata med høy bitdybde, og det tillater både tapsfrie og tapsbaserte moduser for kodeken, fordi modusen er en egenskap ved selve kodestrømmen og ikke ved innpakningen rundt den
Dette siste poenget er det som er verdt å ta med seg. JPEG 2000 er en enkelt algoritme med et tapsfritt spesialtilfelle, ikke to separate formater. Den reversible 5/3-wavelet-en rekonstruerer de originale prøvene nøyaktig; den irreversible 9/7-wavelet-en bytter denne nøyaktigheten mot en mindre fil. En dekoder behandler begge på samme måte ved lesing, noe som er grunnen til at HotPDF bare trenger én dekodingsbane for å akseptere hva enn en JPXDecode-strøm kaster mot den
Hva dekoderen gjør med pikslene
PDF-bilde-XObjects forventer i det vanlige tilfellet 8 biter per komponent i DeviceGray eller DeviceRGB. JPEG 2000 overskrider rutinemessig dette, og dens komponentmodell er mer generell enn en pakket raster, så dekoderen har tre jobber å gjøre før dataene er brukbare som et vanlig bilde
Først blir komponenter med høy bitdybde resamplet til 8 biter. En 12-biters eller 16-biters prøve skaleres ned til området 0 til 255 slik at resultatet blir en vanlig 8-biters raster. Komponenter med fortegn skiftes først inn i et område uten fortegn. Detaljen er viktig fordi den er tapsbasert i seg selv: en 16-biters gråtoneskanning mister det dype toneområdet sitt i det øyeblikket det blir et 8-biters PDF-bilde, noe som er den riktige byttehandelen for skjerm- og utskriftsutdata, men ikke for re-arkivering
For det andre konverteres et YCbCr-fargerom (kodeken kaller det SYCC) til RGB. JPEG 2000 lagrer ofte farger i et luma-kroma-rom for komprimeringseffektivitet, den samme ideen som basis-JPEG bruker, og dekoderen bruker den standard inverse transformasjonen slik at siden mottar ekte RGB
For det tredje oppsamles nedsamplede komponenter med nearest-neighbor-replikering. Kromakanaler lagres ofte med halv oppløsning, så dekoderen leser hver komponent med sine egne dimensjoner og sin egen samplingsfaktor, og replikerer deretter prøver for å bringe hver kanal opp til full bildestørrelse før interleaving. Nearest-neighbor holder trinnet billig; kromaen den fyller var lavfrekvent til å begynne med, så den synlige kostnaden er liten
JP2-bokser kontra en rå J2K-kodestrøm
En JPEG 2000-fil kommer i to former, og HotPDF oppdager hvilken den leser fra de første bytene i stedet for fra filtypen. En JP2-fil er en boksstrukturert beholder: den åpner med signaturboksen på tolv byte 00 00 00 0C 6A 50 20 20 og pakker inn kodestrømmen sammen med bokser som beskriver fargerom, oppløsning og metadata. En rå J2K-kodestrøm har ingen beholder i det hele tatt og begynner med SOC-markøren FF 4F FF 51. Dekoderen leser disse ledende bytene, gjenkjenner signaturen og velger den matchende OpenJPEG-kodeken for hvert tilfelle
Begge former håndteres fordi begge forekommer i naturen. Opptaksenheter og arkiver som trenger sidemetadataene, sender ut JP2; verktøy som vil ha minst mulig nyttelast, sender ut den bare kodestrømmen. Formattypen er modellert som en enum, TJpeg2000FileType, med medlemmene jtInvalid, jtJP2, jtJ2K og jtJPT. JPT-medlemmet navngir JPIP-strømmingsvarianten; byte-signatur-detektoren løser opp de to formene den kan dekode, JP2 og J2K, og rapporterer alt annet som jtInvalid slik at inndata som ikke støttes, feiler rent i stedet for å produsere søppel
uses
HPDFJpeg2000;
var
Decoder: THPDFJpeg2000Decoder;
Pixels: TJpeg2000ByteArray;
begin
Decoder := THPDFJpeg2000Decoder.Create;
try
if Decoder.LoadFromStream(Input) then // JP2 or J2K, auto-detected
if Decoder.GetImageData(Pixels) then
// Pixels is 8-bit interleaved, ColorComponents channels wide,
// row-major top to bottom: ready for a DeviceGray/DeviceRGB XObject.
ProcessRaster(Decoder.Width, Decoder.Height,
Decoder.ColorComponents, Pixels);
finally
Decoder.Free;
end;
end;
Tapsfri og tapsbasert på kodingssiden
Dekoderen leser begge moduser uten å bli fortalt hvilken det er. Valget blir først en parameter når du går den andre veien og produserer en JPEG 2000-fil, noe HotPDF også kan gjøre gjennom TJpeg2000Bitmap-klassen, en TBitmap-etterkommer som laster og lagrer rasterdata som JP2. To egenskaper styrer utdataene. LosslessCompression er en boolsk verdi som velger den reversible wavelet-en når den er sann; CompressionQuality er en TJpeg2000QualityRange, et heltall fra 1 til 100 der 1 er lite og stygt og 100 er stort og trofast. Standardverdiene lever i navngitte konstanter: Jpeg2000DefaultLosslessCompression er False og Jpeg2000DefaultLossyQuality er 80
Avgjørelsen er en innholdsavgjørelse. Tapsfri passer til en hovedkopi, en medisinsk eller juridisk skanning, alt som kan bli kodet på nytt senere og ikke må akkumulere generasjonstap. Tapsbasert med kvalitet 80 passer for et bilde på vei til skjerm eller utskrift, der wavelet-ens grasiøse degradering gir en merkbart mindre fil uten artefakter en leser ville lagt merke til. Det er ett CMYK-forbehold å flagge: punktgrafikken eksponerer SetCMYK for å markere firekanals data som CMYK i stedet for RGBA, noe som betyr noe for utskriftspipeliner som holder separasjoner intakte
uses
HPDFJpeg2000;
var
Bmp: TJpeg2000Bitmap;
begin
Bmp := TJpeg2000Bitmap.Create;
try
Bmp.LoadFromStream(Source); // decode an existing JP2/J2K
Bmp.LosslessCompression := True; // reversible 5/3 wavelet
// or, for a smaller lossy file:
// Bmp.LosslessCompression := False;
// Bmp.CompressionQuality := 80; // matches the default
Bmp.SaveToStream(Output); // always writes a JP2 file
finally
Bmp.Free;
end;
end;
Hvorfor det ikke er noen decode-on-load-filterpipeline
Én arkitektonisk kjensgjerning former hvordan du bruker noe av dette, og det er lett å anta det motsatte. HotPDF har ikke noe generelt decode-on-load-bildefilter. Når du åpner en PDF som allerede inneholder et JPXDecode-bilde, dekoder ikke motoren den strømmen. Den beholder JPEG 2000-bytene nøyaktig slik de er, slik at en sidekopi eller en dokumentsammenslåing bærer bildet gjennom urørt, byte for byte. Dekoderen har et enkelt inngangspunkt, og det er på opprettelsessiden: den filbaserte AddImage, sendt ut av filtypen for å håndtere kildene .jp2, .j2k, .jpt og .jpc
Denne oppdelingen er den riktige utformingen snarere enn en begrensning. Å dekode en innebygd JPX-strøm ved lasting, bare for å kode den på nytt ved lagring, ville konvertere et tapsfritt arkivert bilde til et tapsbasert bilde og blåse opp hver sammenslåing, alt for et bilde du bare mente å flytte fra én PDF til en annen. Å sende strømmen gjennom ordrett er en tapsfri operasjon og en rask operasjon. Dekodingen utsettes til det eneste øyeblikket den virkelig kreves: når du gir motoren en JPEG 2000-fil fra disk og ber den om å rastrere bildet for plassering på en ny side. På det tidspunktet må filen bli til piksler, og dekoderen kjører
Registrere støtte og plassere et bilde
Registrering av JPEG 2000-bilder er valgfritt bak kompileringsbryteren HPDF_REGISTER_JPEG2000_PICTURE, som er av som standard. Årsaken er en reell konflikt, ikke forsiktighet: å registrere filformatene jp2, j2k og jpc globalt med TPicture kan forstyrre BLOB-formatdeteksjonen som ReportBuilders TppDBImage er avhengig av. Definer bryteren når den integrasjonen ikke er i spill, og filformatene registreres slik at TPicture gjenkjenner dem; la den være udefinert og uansett dekoder AddImage-utvidelsesutsendelsen JPEG 2000-filer direkte, fordi den banen ikke går gjennom TPicture i det hele tatt
Når dette er forstått, er plassering av et JPEG 2000-bilde den samme rytmen med tre kall som ethvert annet HotPDF-bilde. Gi AddImage en .jp2-bane og en komprimeringstype for hvordan bildet skal lagres i utdataene, og posisjoner deretter den returnerte bildeindeksen på siden med ShowImage
var
Pdf: THotPDF;
ImgIndex: Integer;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.BeginDoc;
Pdf.AddPage;
// The .jp2 source is decoded through the OpenJPEG backend, then
// re-embedded with the compression you request here.
ImgIndex := Pdf.AddImage('Scan_16bit.jp2', icJpeg);
// x, y, width, height in points; final 0 is the rotation angle.
Pdf.ShowImage(ImgIndex, 72, 72, 400, 300, 0);
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
Komprimeringen du sender til AddImage, styrer hvordan det dekodede bildet lagres på nytt, ikke hvordan det ble lest. En JPEG 2000-fil dekodet til en punktgrafikk kan gå tilbake ut som en DCTDecode-JPEG, en Flate-raster eller et annet støttet filter, avhengig av hva som passer dokumentet. Dekodingen fra JP2 eller J2K skjer uansett først, så det samme kallet godtar en wavelet-komprimert kilde og bygger den inn i den formen resten av pipelinen din forventer
For et bredere bilde av hvordan bilder og skrifter lander i genererte utdata, se våre notater om rapportutdata med skrifter og bilder. Når dokumentet du setter sammen, gjenbruker innhold fra eksisterende PDF-er, pares passthrough-oppførselen beskrevet her med sammenslåings- og revisjonsmekanikkene i objektstrømmer og inkrementelle oppdateringer. JPEG 2000-dekodingsmotoren leveres som en del av HotPDF Component for Delphi og C++Builder, sammen med bilde-, skrift- og dokument-API-ene som dekkes andre steder på denne bloggen