Technický článok

Pridávanie obrázkov JPEG 2000 do PDF v Delphi s HotPDF

Naskenovaný medicínsky preparat, dlaždica leteckého prieskumu, filmový záber archivovaný v plnom dynamickom rozsahu. To sú obrázky, ktoré prichádzajú vo formáte JPEG 2000, a prichádzajú tak z dobrého dôvodu. Formát uchováva 12 alebo 16 bitov na kanál, komprimuje vlnkovou transformáciou namiesto blokovej DCT, ktorú používa JPEG, a dokáže zakódovať ten istý obrázok bezstratovo alebo stratovo z jedného kódového toku. Keď sa dokument zostavený z takýchto zdrojov musí stať súborom PDF, obrázok musí prejsť filtrom, ktorý špecifikácia PDF vyhradila práve pre tento kodek

HotPDF v2.228.0 obnovil funkčný dekódovací modul JPEG 2000 pre tento zámer. Staršia verzia bola dodaná s jednotkou obsahujúcou stub funkcie, ktoré vracali nil, takže API existovalo, ale nič nedekódovalo. Súčasný modul staticky viaže OpenJPEG 2.5.4 a premieňa zdroj JP2 alebo J2K na pixely, ktoré HotPDF dokáže umiestniť na stránku

Filter JPXDecode v PDF

ISO 32000-1 definuje filter JPXDecode v §7.4.9. PDF obrazový XObject uvádza svoju kompresiu v zázname /Filter slovníka toku, pričom JPXDecode je hodnota, ktorá hovorí, že dáta toku sú kódový tok JPEG 2000, a nie bežný JPEG, ktorý nesie /DCTDecode. Filter umožňuje PDF uchovávať vlnkovo komprimované obrazové dáta s vysokou bitovou hĺbkou a prijíma bezstratový aj stratový režim kodeku, pretože režim je vlastnosťou samotného kódového toku a nie obalu okolo neho

Tento posledný bod stojí za zapamätanie. JPEG 2000 je jeden algoritmus s bezstratovým špeciálnym prípadom, nie dva samostatné formáty. Reverzibilná vlnka 5/3 rekonštruuje pôvodné vzorky presne; ireverzibilná vlnka 9/7 vymieňa túto presnosť za menší súbor. Dekodér sa správa k obom rovnako pri čítaní, a preto HotPDF potrebuje iba jednu dekódovaciu cestu na prijatie čohokoľvek, čo prúd JPXDecode predloží

Čo dekodér robí s pixelmi

PDF obrazové XObjecty v bežnom prípade očakávajú 8 bitov na komponent v DeviceGray alebo DeviceRGB. JPEG 2000 toto bežne presahuje a jeho model komponentov je všeobecnejší ako bežný rastrový formát, takže dekodér musí vykonať tri úlohy skôr, než sú dáta použiteľné ako normálny obrázok

Po prvé, komponenty s vysokou bitovou hĺbkou sú prevzorkované na 8 bitov. 12-bitová alebo 16-bitová vzorka sa zmenší na rozsah 0 až 255, takže výsledkom je bežný 8-bitový raster. Znamienkové komponenty sa najprv posunú do rozsahu bez znamienka. Na tomto detaile záleží, pretože sám o sebe je stratový: 16-bitové čiernobiele skenovanie stratí svoju hlbokú tónovú škálu v okamihu, keď sa stane 8-bitovým obrázkom PDF, čo je správna výmena pre výstup na obrazovke a tlač, ale nie pre rearchiváciu

Po druhé, farebný priestor YCbCr (kodek ho nazýva SYCC) sa konvertuje do RGB. JPEG 2000 často ukladá farbu v priestore jas-chroma pre efektivitu kompresie, rovnakú myšlienku, akú používa bežný JPEG, a dekodér aplikuje štandardnú inverznú transformáciu, takže stránka dostane skutočné RGB

Po tretie, podvzorkované komponenty sú prevzorkované nahor replikáciou najbližšieho suseda. Chroma kanály sú často uložené v polovičnom rozlíšení, takže dekodér číta každý komponent v jeho vlastných rozmeroch a vlastnom vzorkovacom faktore, potom replikuje vzorky, aby dostal každý kanál na plnú veľkosť obrázka pred prekladaním. Metóda najbližšieho suseda udržuje krok lacný; chroma, ktorú vypĺňa, bola od začiatku nízkofrekvenčná, takže viditeľné náklady sú malé

Boxy JP2 vs. surový kódový tok J2K

Súbor JPEG 2000 existuje v dvoch podobách a HotPDF zisťuje, ktorú číta, z prvých bajtov, nie z prípony súboru. Súbor JP2 je kontajner so štruktúrou boxov: otvára sa dvanásťbajtovým podpisovým boxom 00 00 00 0C 6A 50 20 20 a obklopuje kódový tok spolu s boxmi, ktoré popisujú farebný priestor, rozlíšenie a metadáta. Surový kódový tok J2K nemá žiadny kontajner a začína markérom SOC FF 4F FF 51. Dekodér číta tieto úvodné bajty, rozpozná podpis a vyberie zodpovedajúci kodek OpenJPEG pre každý prípad

Obe podoby sú spracované, pretože obe sa vyskytujú v praxi. Zariadenia na snímanie a archívy, ktoré potrebujú vedľajšie metadáta, vydávajú JP2; nástroje, ktoré chcú najmenšiu možnú záťaž, vydávajú holý kódový tok. Typ formátu je modelovaný ako enumerácia TJpeg2000FileType s členmi jtInvalid, jtJP2, jtJ2K a jtJPT. Člen JPT označuje variantu streamovania JPIP; detektor bajt-podpisu rozlišuje dve podoby, ktoré dokáže dekódovať, JP2 a J2K, a čokoľvek iné hlási ako jtInvalid, aby nepodporovaný vstup zlyhal čisto namiesto generovania neplatných dát

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;

Bezstratové a stratové kódovanie na strane enkodéra

Dekodér číta oba režimy bez toho, aby bol informovaný o tom, ktorý to je. Výber sa stáva parametrom až vtedy, keď idete opačnou cestou a vytvárate súbor JPEG 2000, čo HotPDF dokáže tiež prostredníctvom triedy TJpeg2000Bitmap, potomka TBitmap, ktorý načítava a ukladá rastrové dáta ako JP2. Výstup riadia dve vlastnosti. LosslessCompression je logická hodnota, ktorá pri hodnote true vyberá reverzibilnú vlnku; CompressionQuality je TJpeg2000QualityRange, celé číslo od 1 do 100, kde 1 je malé a nekvalitné a 100 je veľké a verné. Predvolené hodnoty sú v pomenovaných konštantách: Jpeg2000DefaultLosslessCompression je False a Jpeg2000DefaultLossyQuality je 80

Rozhodnutie je obsahové. Bezstratové kódovanie je vhodné pre hlavnú kópiu, medicínske alebo právne skenovanie, čokoľvek, čo môže byť neskôr prenkódované a nesmie hromadiť generačné straty. Stratové pri kvalite 80 je vhodné pre obrázok určený pre obrazovku alebo tlač, kde plynulá degradácia vlnky poskytuje výrazne menší súbor bez artefaktu, ktorý by čitateľ zachytil. Je tu jedna výhrada CMYK, ktorú treba uviesť: bitmapa poskytuje SetCMYK na označenie štvorkanálových dát ako CMYK namiesto RGBA, čo je dôležité pre tlačové potrubia, ktoré zachovávajú separácie

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;

Prečo neexistuje pipeline filtra dekódovania pri načítaní

Jeden architektonický fakt určuje spôsob použitia všetkého tohto a ľahko sa predpokladá opak. HotPDF nemá všeobecný filter obrazového dekódovania pri načítaní. Keď otvoríte PDF, ktorý už obsahuje obrázok JPXDecode, motor tento tok nedekóduje. Udržiava bajty JPEG 2000 presne také, aké sú, takže kopírovanie stránky alebo zlúčenie dokumentu prenáša obrázok bez zmeny, bajt po bajte. Dekodér má jeden vstupný bod a je na strane vytvárania: súborový AddImage, odoslaný podľa prípony súboru na spracovanie zdrojov .jp2, .j2k, .jpt a .jpc

Toto rozdelenie je správnym dizajnom, nie obmedzením. Dekódovanie vloženého toku JPX pri načítaní, len aby sa znova zakódoval pri ukladaní, by premenilo bezstratovo archivovaný obrázok na stratový a nafúklo by každé zlúčenie, a to všetko pre obrázok, ktorý ste chceli iba presunúť z jedného PDF do druhého. Priechod toku bez zmeny je bezstratová operácia a rýchla. Dekódovanie sa odkladá na jediný okamih, kedy je skutočne nevyhnutné: keď odovzdáte motoru súbor JPEG 2000 z disku a požiadate ho o rasterizáciu tohto obrázka pre umiestnenie na novú stránku. V tom okamihu sa súbor musí stať pixelmi a dekodér sa spustí

Registrácia podpory a umiestnenie obrázka

Registrácia obrázkov JPEG 2000 je dobrovoľná za prepínačom kompilácie HPDF_REGISTER_JPEG2000_PICTURE, ktorý je predvolene vypnutý. Dôvodom je skutočný konflikt, nie opatrnosť: globálna registrácia formátov súborov jp2, j2k a jpc s TPicture môže interferovať s detekciou formátu BLOB, na ktorú sa spolieha TppDBImage komponentu ReportBuilder. Definujte prepínač, keď táto integrácia nie je aktívna, a formáty súborov sa zaregistrujú, aby ich TPicture rozoznalo; nechajte ho nedefinovaný a odosielanie rozšírení AddImage stále dekóduje súbory JPEG 2000 priamo, pretože táto cesta vôbec neprechádza cez TPicture

S týmto pochopením je umiestnenie obrázka JPEG 2000 rovnaký rytmus troch volaní ako pri akomkoľvek inom obrázku HotPDF. Odovzdajte AddImage cestu .jp2 a typ kompresie pre spôsob uloženia obrázka vo výstupe, potom umiestnite vrátený index obrázka na stránku pomocou 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;

Kompresia, ktorú odovzdáte do AddImage, riadi spôsob opätovného uloženia dekódovaného obrázka, nie spôsob jeho načítania. Súbor JPEG 2000 dekódovaný do bitmapy môže byť opätovne vydaný ako DCTDecode JPEG, Flate raster alebo iný podporovaný filter, podľa toho, čo vyhovuje dokumentu. Dekódovanie z JP2 alebo J2K prebehne najprv bez ohľadu na to, takže rovnaké volanie prijme vlnkovo komprimovaný zdroj a vloží ho do akejkoľvek formy, ktorú zvyšok vášho pipeline očakáva

Pre širší prehľad o tom, ako obrázky a písma pristanú v generovanom výstupe, si pozrite naše poznámky o výstupe správ s písmami a obrázkami. Keď dokument, ktorý zostavujete, opätovne používa obsah z existujúcich PDF, správanie priechodu opísané tu sa spáruje s mechanikou zlúčenia a revízie v objektových tokoch a prírastkových aktualizáciách. Dekódovací modul JPEG 2000 sa dodáva ako súčasť HotPDF Component pre Delphi a C++Builder, spolu s obrázkovými, písmovými a dokumentovými API pokrytými inde na tomto blogu