Salinan pindaian medis, ubin survei udara, bingkai film yang diarsipkan pada rentang dinamis penuh. Gambar-gambar ini sering kali hadir dalam format JPEG 2000, dan tentunya karena suatu alasan. Format ini menyimpan 12 atau 16 bit per saluran, dikompresi menggunakan transformasi wavelet alih-alih blok DCT seperti yang digunakan oleh JPEG biasa, serta dapat mengodekan gambar yang sama baik secara nirkurang (lossless) maupun kerugian (lossy) dari satu aliran kode. Saat dokumen yang dibuat dari sumber-sumber ini perlu menjadi PDF, gambarnya harus melalui filter yang secara spesifik disediakan oleh spesifikasi PDF untuk kodek ini
HotPDF v2.228.0 memulihkan mesin dekode JPEG 2000 yang berfungsi untuk jalur tersebut. Rilis versi sebelumnya telah menyertakan unit tersebut dengan fungsi rintisan yang mengembalikan nilai nil, sehingga API tersebut memang ada tetapi tidak dapat mendekode apa pun. Mesin saat ini mengikat OpenJPEG 2.5.4 secara statis dan mengubah sumber JP2 atau J2K menjadi piksel yang dapat diletakkan oleh HotPDF pada halaman
Filter JPXDecode dalam PDF
ISO 32000-1 mendefinisikan filter JPXDecode pada §7.4.9. Objek gambar XObject PDF menamai kompresinya di entri /Filter pada kamus aliran, dan JPXDecode adalah nilai yang menyatakan bahwa data aliran merupakan aliran kode JPEG 2000, bukan JPEG dasar yang dibawa oleh /DCTDecode. Filter ini memungkinkan PDF menampung data gambar terkompresi wavelet dengan kedalaman bit yang tinggi, serta dapat menerima mode nirkurang maupun kerugian dari kodek tersebut, karena mode tersebut merupakan properti dari aliran kode itu sendiri dan bukan berasal dari pembungkus yang mengelilinginya
Poin terakhir tersebut adalah hal yang patut diperhatikan. JPEG 2000 merupakan algoritma tunggal yang memiliki kasus nirkurang khusus, dan bukannya merupakan dua format terpisah. Wavelet 5/3 yang dapat dibalik (reversible) merekonstruksi sampel aslinya dengan tepat; sedangkan wavelet 9/7 yang tidak dapat dibalik (irreversible) mengorbankan ketepatan tersebut demi mendapatkan ukuran berkas yang lebih kecil. Dekoder akan memperlakukan keduanya dengan cara yang sama pada saat dibaca, sehingga HotPDF hanya membutuhkan satu jalur dekode untuk dapat menerima apa pun yang dilemparkan oleh aliran JPXDecode kepadanya
Apa yang dilakukan oleh dekoder terhadap piksel
Kasus umum dari objek gambar XObject PDF mengharapkan 8 bit per komponen dalam ruang warna DeviceGray atau DeviceRGB. Format JPEG 2000 secara rutin melampaui batasan ini, dan model komponennya lebih umum dibandingkan raster kemasan, sehingga dekoder memiliki tiga tugas yang harus diselesaikan sebelum datanya siap digunakan sebagai gambar biasa
Pertama, komponen berkedalaman bit tinggi disampel ulang menjadi 8 bit. Sampel 12-bit atau 16-bit diperkecil ukurannya ke rentang 0 hingga 255 sehingga hasilnya menjadi raster 8-bit biasa. Komponen bertanda akan digeser terlebih dahulu ke dalam rentang tak bertanda. Detail ini penting karena pada hakikatnya proses ini bersifat kerugian: pindaian skala abu-abu 16-bit akan kehilangan jangkauan nada dalamnya saat ia menjadi gambar PDF 8-bit. Ini merupakan kompromi yang tepat untuk output tampilan layar maupun cetak, tetapi bukan untuk pengarsipan ulang
Kedua, ruang warna YCbCr (yang oleh kodek disebut SYCC) dikonversi menjadi RGB. JPEG 2000 sering kali menyimpan warna dalam ruang luma-chroma demi alasan efisiensi kompresi, sebuah gagasan serupa yang juga digunakan oleh JPEG dasar, dan dekoder akan menerapkan fungsi transformasi inversi standar sehingga halaman akan menerima warna RGB murni
Ketiga, komponen bersubsampel disampel ulang dengan replikasi tetangga terdekat. Saluran chroma sering kali disimpan dengan resolusi setengah, sehingga dekoder akan membaca masing-masing komponen pada dimensinya dan dengan faktor samplingnya sendiri, lalu mereplikasi sampel tersebut guna menaikkan ukuran tiap saluran agar sesuai dengan ukuran gambar penuh sebelum dilakukan penyisipan gilir. Penggunaan tetangga terdekat akan membuat langkah ini menjadi lebih murah; mengingat chroma yang diisinya secara inheren berfrekuensi rendah, biaya yang terlihat akan menjadi sangat kecil
Kotak JP2 melawan aliran kode J2K mentah
Berkas JPEG 2000 hadir dalam dua wujud, dan HotPDF mendeteksi mana yang sedang dibacanya melalui bita-bita awal dan bukan dari ekstensi berkasnya. Berkas JP2 adalah penampung terstruktur kotak: wujud ini dibuka dengan kotak tanda tangan dua belas bita 00 00 00 0C 6A 50 20 20 dan membungkus aliran kode yang bersanding dengan berbagai kotak pendeskripsi ruang warna, resolusi, serta metadata. Aliran kode J2K mentah tidak membawa penampung apa pun dan diawali dengan penanda SOC FF 4F FF 51. Dekoder akan membaca bita-bita awal tersebut, mengenali tanda tangannya, lalu memilih kodek OpenJPEG yang cocok untuk tiap-tiap kasus
Kedua wujud tersebut didukung karena memang keduanya digunakan di dunia nyata. Perangkat tangkapan dan arsip yang membutuhkan metadata sampingan akan memancarkan JP2; sementara berbagai perkakas yang menginginkan muatan berukuran sekecil mungkin akan memancarkan aliran kode murni. Tipe formatnya dimodelkan sebagai enum, TJpeg2000FileType, dengan anggotanya yaitu jtInvalid, jtJP2, jtJ2K, dan jtJPT. Anggota JPT menamai varian aliran JPIP; detektor bita tanda tangan akan meresolusi kedua wujud yang dapat didekodenya, yaitu JP2 dan J2K, lalu melaporkan apa pun sisanya sebagai jtInvalid sehingga masukan yang tak didukung akan digagalkan secara bersih alih-alih menghasilkan sampah
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;
Nirkurang dan kerugian pada sisi enkripsi
Dekoder membaca kedua mode tanpa perlu diberitahu mode mana yang sedang diproses. Pemilihan ini baru akan menjadi parameter ketika Anda mengambil langkah sebaliknya untuk menghasilkan berkas JPEG 2000, yang dapat dilakukan oleh HotPDF melalui kelas TJpeg2000Bitmap, sebuah turunan dari TBitmap yang akan memuat dan menyimpan data raster sebagai JP2. Terdapat dua properti yang mengatur output-nya. LosslessCompression merupakan boolean yang memilih wavelet yang dapat dibalik saat bernilai benar; sedangkan CompressionQuality merupakan TJpeg2000QualityRange, bilangan bulat dari 1 hingga 100 dengan angka 1 berarti kecil dan kurang baik kualitasnya, sementara 100 berarti besar dan sesuai aslinya. Bawaannya berada di konstanta bernama: Jpeg2000DefaultLosslessCompression yaitu False dan Jpeg2000DefaultLossyQuality yaitu 80
Keputusan tersebut adalah keputusan menyangkut konten. Opsi nirkurang cocok untuk salinan master, pindaian rekam medis maupun dokumen hukum, serta hal apa pun yang suatu saat kelak mungkin akan dikodekan kembali dan karenanya dilarang mengalami penurunan kualitas yang menumpuk seiring waktu pengarsipan secara regeneratif. Opsi kerugian pada kualitas 80 cocok untuk gambar yang ditujukan untuk keperluan presentasi layar maupun kualitas produk cetak, dengan kompromi wavelet perlahan menurun yang tetap halus guna mendapatkan berkas yang tampak nyata lebih kecil skalanya tanpa ada penampakan artifak aneh yang sekiranya dapat disadari secara kentara oleh orang yang memerhatikan dokumen. Terdapat satu hal mengenai CMYK yang wajib ditandai: bitmap tersebut membuka metode pengaturan SetCMYK untuk mengidentifikasikan data-data gambar berbasis empat kanal format sebagai model tipe CMYK bukan format gambar tipe RGBA. Format CMYK ini berperan dalam proses alur percetakan dalam hal mempertahankan nilai kedetailan warnanya tanpa terjadi modifikasi
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;
Alasan tidak adanya pipa pemrosesan filter dekode-saat-dimuat
Satu fakta arsitektural membentuk cara Anda menggunakan semua hal ini, dan memang cukup mudah untuk mengasumsikan sebaliknya. HotPDF tidak memiliki filter gambar dekode-saat-dimuat yang bersifat umum. Ketika Anda membuka PDF yang sudah mengandung gambar JPXDecode, mesin ini tidak akan mendekode aliran tersebut. Ia menyimpan susunan bita JPEG 2000 sama persis seperti aslinya, sehingga tugas menyalin halaman atau menggabungkan dokumen akan turut menyertakan gambar tersebut secara utuh tanpa modifikasi apa pun. Titik masuk untuk fungsi dekoder ini hanya terdapat pada satu tempat, yaitu di sisi pembuatan konten: dengan fungsi berbasis berkas bernama AddImage, ia diberangkatkan berdasarkan pada ekstensi berkasnya guna menangani berbagai sumber masukan, seperti .jp2, .j2k, .jpt, dan .jpc
Pemisahan ini adalah desain yang benar, bukan sebuah batasan. Mendekode aliran JPX yang disematkan saat dimuat hanya untuk mengodekannya kembali saat disimpan akan mengubah gambar arsip nirkurang menjadi gambar kerugian serta memperbesar ukuran setiap penggabungan, padahal Anda hanya ingin memindahkan gambar dari satu PDF ke PDF lainnya. Meneruskan aliran secara persis apa adanya adalah operasi nirkurang yang berjalan cepat. Proses dekode ditunda hingga saat ia benar-benar dibutuhkan: ketika Anda menyerahkan berkas JPEG 2000 dari penyimpanan ke mesin tersebut dan memintanya melakukan rasterisasi gambar untuk diletakkan di halaman yang baru. Pada titik itulah berkas tersebut harus berubah wujud menjadi sekumpulan piksel, dan dekoder pun akan dijalankan
Mendaftarkan dukungan dan meletakkan gambar
Pendaftaran gambar JPEG 2000 bersifat opsional (opt-in) di balik sakelar kompilasi HPDF_REGISTER_JPEG2000_PICTURE, yang dinonaktifkan secara bawaan. Alasannya adalah terjadinya konflik nyata, bukan kehati-hatian: mendaftarkan format berkas jp2, j2k, dan jpc secara global dengan TPicture dapat mengganggu deteksi format BLOB yang diandalkan oleh TppDBImage milik ReportBuilder. Tetapkan sakelar tersebut jika integrasi tersebut tidak sedang digunakan, dan format berkas akan terdaftar sehingga TPicture dapat mengenalinya; biarkan tidak ditetapkan, dan fitur pengalihan ekstensi milik AddImage akan tetap mendekode berkas JPEG 2000 secara langsung, karena jalur tersebut sama sekali tidak melalui TPicture
Dengan memahaminya, proses meletakkan gambar JPEG 2000 merupakan ritme tiga panggilan yang sama dengan gambar HotPDF lainnya. Berikan jalur berkas .jp2 dan jenis kompresi untuk menentukan cara penyimpanan gambar di bagian hasil keluaran akhir dokumen ke AddImage, lalu letakkan posisi indeks gambar kembalian fungsi ke bidang halaman dengan 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;
Kompresi yang Anda berikan ke AddImage mengontrol bagaimana gambar yang telah didekode disimpan kembali, bukan bagaimana ia dibaca. Berkas JPEG 2000 yang telah didekode menjadi bitmap dapat dihasilkan kembali sebagai JPEG berfilter DCTDecode, raster Flate, atau filter lainnya yang didukung, menyesuaikan mana yang cocok untuk dokumen tersebut. Dekode dari JP2 atau J2K akan terjadi lebih dulu terlepas dari semua itu, sehingga panggilan yang sama akan menerima sumber gambar terkompresi wavelet dan menyematkannya dalam wujud apa pun yang diharapkan oleh jalur Anda
Untuk mengetahui gambaran yang lebih luas mengenai bagaimana gambar dan fon diletakkan di bagian hasil keluaran, lihat catatan kami tentang output laporan menggunakan fon dan gambar di Delphi. Saat dokumen yang terkompresi harus memenuhi profil kearsipan, aturan yang ada pada validasi PDF/A, PDF/X, dan PDF/UA di Delphi memberi tahu Anda filter mana yang diterima oleh tingkat kesesuaian tertentu. Mesin dekode JPEG 2000 ini hadir sebagai bagian dari Komponen HotPDF untuk Delphi dan C++Builder, di samping pemuatan gambar dan fon, serta API dokumen yang dibahas di tempat lain di blog ini