Egy beszkennelt orvosi tárgylemez, egy légifotó-mozaik, egy teljes dinamikatartományban archivált filmkocka. Ezek azok a képek, amelyek JPEG 2000 formátumban érkeznek, és nem véletlenül érkeznek így. A formátum csatornánként 12 vagy 16 bitet tart meg, a JPEG által használt blokk DCT helyett wavelet transzformációval tömörít, és ugyanazt a képet veszteségmentesen vagy veszteségesen is képes kódolni egyetlen kódfolyamból. Amikor az ezen forrásokból felépülő dokumentumnak PDF-fé kell válnia, a képnek át kell haladnia azon a szűrőn, amelyet a PDF specifikáció pontosan ehhez a kodekhez tart fenn
A HotPDF v2.228.0 visszaállított egy működő JPEG 2000 dekódoló motort ehhez az útvonalhoz. Egy korábbi build olyan csonkfüggvényekkel szállította az egységet, amelyek nil értéket adtak vissza, így az API létezett, de nem dekódolt semmit. A jelenlegi motor az OpenJPEG 2.5.4-et köti statikusan, és a JP2 vagy J2K forrást pixelekké alakítja, amelyeket a HotPDF elhelyezhet az oldalon
A JPXDecode szűrő a PDF-ben
Az ISO 32000-1 a §7.4.9-es pontban határozza meg a JPXDecode szűrőt. Egy PDF kép XObject a folyam szótárának /Filter bejegyzésében nevezi meg a tömörítését, és a JPXDecode az az érték, amely jelzi, hogy a folyamadatok JPEG 2000 kódfolyamot alkotnak a /DCTDecode által hordozott alap JPEG helyett. A szűrő teszi lehetővé, hogy egy PDF nagy bitmélységű wavelet tömörítésű képadatokat tároljon, és befogadja a kodek veszteségmentes és veszteséges módját is, mivel a mód magának a kódfolyamnak a tulajdonsága, és nem a körülötte lévő burkolóé
Ezt az utolsó pontot érdemes megjegyezni. A JPEG 2000 egyetlen algoritmus egy veszteségmentes speciális esettel, nem pedig két külön formátum. A megfordítható 5/3 wavelet pontosan rekonstruálja az eredeti mintákat; a visszafordíthatatlan 9/7 wavelet ezt a pontosságot cseréli el egy kisebb fájlért. Egy dekóder beolvasáskor mindkettőt ugyanúgy kezeli, ezért a HotPDF-nek csak egyetlen dekódolási útvonalra van szüksége ahhoz, hogy elfogadja, amit egy JPXDecode folyam elé vet
Mit tesz a dekóder a pixelekkel
A PDF kép XObject objektumok az általános esetben komponensenként 8 bitet várnak el DeviceGray vagy DeviceRGB színterekben. A JPEG 2000 rutinszerűen meghaladja ezt, és a komponensmodellje általánosabb, mint egy csomagolt raszter, így a dekódernek három feladata van, mielőtt az adatok normál képként felhasználhatók lennének
Először is, a nagy bitmélységű komponenseket 8 bitre mintavételezik át. Egy 12 vagy 16 bites mintát a 0 és 255 közötti tartományra méreteznek le, így az eredmény egy hagyományos 8 bites raszter lesz. Az előjeles komponenseket először az előjel nélküli tartományba tolják el. A részlet azért fontos, mert önmagában véve veszteséges: egy 16 bites szürkeárnyalatos szkennelés elveszíti mély tónustartományát abban a pillanatban, amint egy 8 bites PDF képpé válik, ami megfelelő csere a képernyős és a nyomtatási kimenethez, de nem az újraarchiváláshoz
Másodszor, egy YCbCr (a kodek SYCC-nek nevezi) színteret RGB-re alakítanak. A JPEG 2000 a tömörítési hatékonyság érdekében gyakran luma-chroma térben tárolja a színeket, ami ugyanaz az elképzelés, amit az alap JPEG használ, és a dekóder alkalmazza a szabványos inverz transzformációt, hogy az oldal valódi RGB-t kapjon
Harmadszor, az alulmintavételezett komponenseket a legközelebbi szomszédos replikációval felülmintavételezik. A chroma csatornákat gyakran félfelbontásban tárolják, ezért a dekóder minden komponenst a saját méretével és a saját mintavételi tényezőjével olvas be, majd a minták replikálásával az összefésülés előtt minden csatornát a teljes képméretre hoz fel. A legközelebbi szomszédos eljárás olcsón tartja a lépést; az általa kitöltött chroma eleve alacsony frekvenciájú volt, így a látható költség kicsi
JP2 dobozok szemben a nyers J2K kódfolyammal
A JPEG 2000 fájl két formában érkezik, és a HotPDF inkább az első bájtokból ismeri fel, hogy melyiket olvassa, mint a fájlkiterjesztésből. A JP2 fájl egy doboz-strukturált tároló: a tizenkét bájtos 00 00 00 0C 6A 50 20 20 aláírási dobozzal nyílik meg, és a kódfolyamot a színteret, a felbontást és a metaadatokat leíró dobozok mellé csomagolja. Egy nyers J2K kódfolyam egyáltalán nem hordoz tárolót, és a FF 4F FF 51 SOC jelölővel kezdődik. A dekóder beolvassa ezeket a kezdő bájtokat, felismeri az aláírást, és minden egyes esethez kiválasztja a megfelelő OpenJPEG kodeket
Mindkét formát kezeli, mert mindkettő előfordul a vadonban. A rögzítőeszközök és archívumok, amelyeknek szükségük van a kiegészítő metaadatokra, JP2-t bocsátanak ki; a lehető legkisebb terhet akaró eszközök a puszta kódfolyamot bocsátják ki. A formátumtípus a TJpeg2000FileType enumerációként van modellezve, a jtInvalid, jtJP2, jtJ2K és jtJPT tagokkal. A JPT tag a JPIP streaming változatot nevezi meg; a bájt-aláírás érzékelő feloldja a két általa dekódolható formát, a JP2-t és a J2K-t, és minden mást jtInvalid formátumként jelent, így egy nem támogatott bemenet tisztán meghiúsul, ahelyett, hogy szemetet termelne
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;
Veszteségmentes és veszteséges kódolási oldalon
A dekóder mindkét módot beolvassa anélkül, hogy megmondanák neki, melyik az. A választás csak akkor válik paraméterré, amikor a másik irányba haladunk, és egy JPEG 2000 fájlt állítunk elő, amit a HotPDF a TJpeg2000Bitmap osztályon keresztül is képes megtenni, amely egy olyan TBitmap leszármazott, amely raszteradatokat tölt be és ment JP2 formátumban. Két tulajdonság szabályozza a kimenetet. A LosslessCompression egy logikai érték, amely igaz értéknél a megfordítható waveletet választja; a CompressionQuality egy TJpeg2000QualityRange, egy 1 és 100 közötti egész szám, ahol az 1 kicsi és csúnya, a 100 pedig nagy és hűséges. Az alapértelmezések megnevezett állandókban élnek: a Jpeg2000DefaultLosslessCompression False, a Jpeg2000DefaultLossyQuality pedig 80
A döntés egy tartalomfüggő döntés. A veszteségmentes mód illik a mesterpéldányokhoz, az orvosi vagy jogi szkennelésekhez, és mindenhez, ami később újrakódolható, és nem halmozhat fel generációs veszteséget. A 80-as minőségű veszteséges mód a képernyőre vagy nyomtatásra szánt képekhez illik, ahol a wavelet kecses degradációja érezhetően kisebb fájlt eredményez anélkül, hogy az olvasó által észrevehető műterméket hozna létre. Egy CMYK kikötést érdemes megjegyezni: a bittérkép kiteszi a SetCMYK metódust, hogy a négycsatornás adatokat CMYK-ként jelölje meg az RGBA helyett, ami a szétválasztásokat érintetlenül hagyó nyomdai csővezetékek esetében számít
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;
Miért nincs betöltéskori dekódolási szűrőcsővezeték
Egy építészeti tény határozza meg, hogy hogyan használja mindezt, és könnyű az ellenkezőjét feltételezni. A HotPDF-ben nincs általános betöltéskori képdekódoló szűrő. Amikor megnyit egy PDF-et, amely már tartalmaz JPXDecode képet, a motor nem dekódolja azt a folyamot. Pontosan úgy tartja meg a JPEG 2000 bájtokat, ahogy vannak, így egy oldalmásolat vagy egy dokumentumegyesítés érintetlenül, bájtról bájtra viszi át a képet. A dekódernek egyetlen belépési pontja van, és az a létrehozási oldalon található: a fájlalapú AddImage, amelyet fájlkiterjesztés szerint küldenek a .jp2, .j2k, .jpt és .jpc források kezelésére
Ez a felosztás inkább a helyes kialakítás, mintsem egy korlátozás. Egy beágyazott JPX folyam betöltéskori dekódolása, majd a mentéskori újrakódolása egy veszteségmentesen archivált képet veszteségessé alakítana, és minden egyesítés méretét felduzzasztaná, mindezt egy olyan kép miatt, amelyet csak egy PDF-ből egy másikba akart áthelyezni. A folyam szó szerinti átengedése veszteségmentes és gyors művelet. A dekódolás addig a pillanatig halasztódik, amíg az valóban szükséges lesz: amikor átad a motornak egy JPEG 2000 fájlt a lemezről, és arra kéri, hogy raszterezze a képet egy új oldalon történő elhelyezéshez. Ezen a ponton a fájlnak pixelekké kell válnia, és a dekóder lefut
Támogatás regisztrálása és kép elhelyezése
A JPEG 2000 képregisztráció opcionális a HPDF_REGISTER_JPEG2000_PICTURE fordítási kapcsoló mögött, amely alapértelmezés szerint ki van kapcsolva. Ennek oka egy valós konfliktus, nem pedig az óvatosság: a jp2, j2k és jpc fájlformátumok globális regisztrálása a TPicture rendszerrel megzavarhatja a BLOB formátumészlelést, amelyre a ReportBuilder TppDBImage támaszkodik. Definiálja a kapcsolót, ha ez az integráció nincs játékban, és a fájlformátumok úgy regisztrálódnak, hogy a TPicture felismerje őket; hagyja definiálatlanul, és az AddImage kiterjesztés elküldése még mindig közvetlenül dekódolja a JPEG 2000 fájlokat, mivel az az útvonal egyáltalán nem megy keresztül a TPicture osztályon
Ezt megértve, egy JPEG 2000 kép elhelyezése ugyanaz a háromhívásos ritmus, mint bármely más HotPDF képé. Adjon át az AddImage számára egy .jp2 útvonalat és egy tömörítési típust arról, hogyan tárolódjon a kép a kimenetben, majd a ShowImage metódussal pozicionálja a visszatérő képindexet az oldalon
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;
Az AddImage számára átadott tömörítés szabályozza, hogyan tárolódik újra a dekódolt kép, és nem azt, hogyan olvasták be. Egy bittérképpé dekódolt JPEG 2000 fájl visszamehet DCTDecode JPEG-ként, Flate raszterként vagy más támogatott szűrőként, amelyik megfelel a dokumentumnak. A dekódolás a JP2-ből vagy J2K-ból ettől függetlenül először történik, így ugyanaz a hívás elfogadja a wavelet tömörítésű forrást, és olyan formában ágyazza be, amilyet a csővezeték többi része vár
Arról az átfogóbb képről, hogy a képek és a betűtípusok hogyan landolnak a generált kimenetben, lásd a jelentéskészítés betűtípusokkal és képekkel Delphiben szóló megjegyzéseinket. Amikor az Ön által összeállított dokumentum meglévő PDF-ekből származó tartalmat használ fel újra, az itt leírt átengedési viselkedés az objektumfolyamok és növekményes frissítések című cikkben található egyesítési és revíziós mechanikával párosul. A JPEG 2000 dekódoló motor a HotPDF Component részeként érkezik a Delphi és a C++Builder rendszerekhez, a blogon máshol tárgyalt kép, betűtípus és dokumentum API-k mellett