Technical Article

LUT Warna 3D di PDF dengan Fungsi Sampel Tipe 0

Fungsi PDF adalah salah satu sudut spesifikasi yang lebih jarang dibahas. Kebanyakan pengembang menemukannya sekali, sebagai hal yang dibutuhkan oleh arsir aksial Tipe 2 untuk memudar di antara dua warna, dan tidak pernah melihatnya lagi. Sangat disayangkan, karena mesin fungsi tersebut adalah evaluator tujuan umum kecil yang digunakan kembali oleh format untuk pengarsiran, fungsi transfer, fungsi spot halftone, warna tint pemisahan, dan kurva transfer soft-mask. Dari empat jenis fungsi, Tipe 0 adalah yang paling kuat dan paling tidak dipahami. Ini adalah fungsi sampel (sampled function): kisi multidimensi dari nilai keluaran yang diinterpolasi oleh pembaca. Karena kisi tersebut dapat menampung angka berapa pun yang Anda masukkan, fungsi Tipe 0 dapat mengekspresikan pemetaan nonlinier arbitrer, yang merupakan bentuk persis dari tabel pencarian warna (color lookup table).

Artikel ini membahas kamus Tipe 0 sebagaimana didefinisikan ISO 32000-1 dalam §7.10.2, kemudian menunjukkan dua kasus yang paling penting dalam pipeline dokumen: LUT koreksi warna RGB-ke-RGB tiga masukan, dan transformasi tint warna spot satu masukan. Pembangun fungsi sampel yang sama melayani keduanya, dan perbedaan di antara keduanya sepenuhnya adalah pertanyaan tentang berapa banyak masukan yang dimiliki kisi tersebut.

Fungsi sampel adalah kisi yang diinterpolasi pembaca

Fungsi Tipe 0 memetakan vektor m-masukan ke vektor n-keluaran dengan menyimpan sampel pada kisi teratur dan menginterpolasi di antaranya. ISO 32000-1 §7.10.2 mencantumkan kunci-kunci yang menggambarkan kisi tersebut. /Domain menyimpan dua angka per masukan, batas bawah dan atas dari setiap sumbu masukan. /Range menyimpan dua angka per komponen keluaran. /Size adalah array dari m integer yang memberikan jumlah sampel di sepanjang setiap sumbu masukan, sehingga kisi yang memiliki dua belas sampel di setiap sisinya dalam tiga dimensi memiliki /Size [12 12 12] dan menyimpan 1.728 titik kisi. /BitsPerSample menetapkan presisi dari setiap nilai yang disimpan; HotPDF menerima 1, 2, 4, 8, 12, 16, 24, dan 32 bit, cocok dengan nilai yang diizinkan Tabel 38.

Aliran sampel dibaca dalam urutan yang tetap. Dimensi masukan pertama berubah paling cepat, lalu yang kedua, dan seterusnya, dan pada setiap titik kisi, komponen keluaran n disimpan secara berurutan. Untuk tabel RGB-ke-RGB, itu adalah tiga byte per titik kisi pada delapan bit, dengan urutan keluaran-merah (red-output), keluaran-hijau (green-output), keluaran-biru (blue-output), menyapu masukan merah terlebih dahulu. Dua kunci lagi memetakan dunia kontinu ke kisi integer. /Encode memetakan setiap masukan dari interval /Domain miliknya ke rentang indeks sampel 0 hingga Size[i] - 1, dan /Decode memetakan kembali integer mentah yang disimpan ke interval /Range. Ketika Anda membiarkannya pada nilai default-nya, masukan yang membentang [0 1] lands dengan bersih di kisi penuh dan byte tersimpan bernilai 255 didekodekan ke bagian atas rentang keluarannya, yang merupakan apa yang diinginkan oleh LUT warna ternormalisasi [0,1].

Orde 1 versus Orde 3

Di antara titik-titik kisi, pembaca harus melakukan interpolasi, dan /Order memilih caranya. /Order 1 adalah interpolasi multilinier: linier di sepanjang satu sumbu, bilinier di dua sumbu, trilinier di tiga sumbu. Cara ini cepat, persis dengan apa yang dilakukan perangkat keras di sebagian besar pembaca, dan untuk transformasi warna yang halus, biasanya tidak dapat dibedakan dari cara yang lebih rumit. /Order 3 meminta interpolasi cubic-spline, yang mencocokkan kurva yang lebih halus melalui sampel dengan konsekuensi lebih banyak pekerjaan dan area pendukung yang lebih luas di sekitar setiap titik yang dievaluasi.

Komprominya adalah kepadatan kisi versus kehalusan kurva. Orde kubik membuktikan kegunaannya saat kisi kasar dan pemetaan memiliki kelengkungan yang terlihat, karena garis lurus di antara dua sampel yang berjauhan dapat meratakan kurva nada (tone curve) dengan cara yang tertangkap mata pada gradien. Setelah kisi padat, segmen-segmen tersebut cukup pendek sehingga interpolasi linier mengikuti kurva dengan erat dan orde kubik hanya membawa sedikit manfaat. Aturan praktisnya adalah menggunakan /Order 3 hanya dengan kisi kecil atau transformasi curam, dan sebaliknya membiarkannya pada default linier. Perhatikan bahwa /Order hanya berlaku untuk fungsi Tipe 0, dan HotPDF menolak nilai apa pun selain 1 atau 3.

LUT 3D: tiga masukan, tiga keluaran

Koreksi warna RGB-ke-RGB adalah kasus klasik untuk kisi tiga masukan, yaitu LUT 3D klasik yang digunakan dalam penilaian warna (color grading) dan pencocokan perangkat. Setiap sumbu kubus adalah satu saluran masukan, setiap titik kisi menyimpan tiga nilai RGB yang dikoreksi untuk koordinat masukan tersebut, dan pembaca menginterpolasi secara trilinier sampel sudut di sekitar warna apa pun yang masuk. Tiga masukan tidak dapat dihindari di sini karena warna merah yang dikoreksi dapat bergantung pada masukan hijau dan biru, bukan hanya pada masukan merah; kurva per saluran tidak dapat mengekspresikan interferensi saluran (channel crosstalk), tetapi kubus dapat melakukannya.

HotPDF membangun aliran Tipe 0 melalui RegisterSampledFunction, yang mengambil /Domain, /Range, /Size, /BitsPerSample, and byte sampel secara langsung dan mengembalikan objek fungsi. Untuk kubus ternormalisasi standar, Anda meneruskan batas [0,1] pada ketiga sumbu masukan dan ketiga keluaran, ukuran N x N x N, dan tabel sampel yang diratakan. Pembangun memvalidasi bahwa jumlah byte cocok dengan kisi: untuk kedalaman yang selaras dengan byte (byte-aligned), pembangun mengharapkan hasil perkalian dari OutputCount x (BitsPerSample div 8) x produk ukuran, dan memunculkan error jika array memiliki panjang yang salah, sehingga stride yang salah hitung akan gagal dengan jelas pada pendaftaran alih-alih merender sebagai sampah nanti.

const
  N = 17;  // 17 x 17 x 17 cube, the common ICC LUT resolution
var
  LutFn: THPDFStreamObject;
  Samples: TBytes;
begin
  // Fill Samples with N*N*N grid points, 3 bytes each (R,G,B output),
  // red input varying fastest. Build the corrected triple for each
  // grid coordinate with your ICC-managed conversion, then store it.
  SetLength(Samples, N * N * N * 3);
  BuildCorrectedCube(Samples, N);   // your color-managed fill

  LutFn := Pdf.RegisterSampledFunction(
    [0,1, 0,1, 0,1],   // /Domain: three input axes on [0,1]
    [0,1, 0,1, 0,1],   // /Range:  three output channels on [0,1]
    [N, N, N],         // /Size:   the cube resolution per axis
    8,                 // /BitsPerSample
    Samples,
    1);                // /Order 1 = trilinear
end;

Kebenaran kolorimetri dari kubus terletak pada bagaimana Anda mengisinya, bukan pada fungsi PDF. Jalur yang benar adalah menghitung setiap titik kisi melalui konversi yang dikelola ICC, mesin yang sama yang menggerakkan soft-proof, sehingga angka-angka di kisi tersebut memiliki arti terhadap profil sumber dan tujuan yang ditentukan. Daftarkan profil yang membatasi konversi dengan RegisterICCProfile, yang mencatat ruang warna ICCBased (1, 3, atau 4 komponen) dan mengembalikan nama sumber daya yang dapat Anda lampirkan ke konten yang diumpankan oleh LUT. Fungsi Tipe 0 membawa tabel interpolasi; profil ICC membawa arti dari titik akhir tersebut.

Kasus 1D: transformasi tint warna spot

Ruang warna pemisahan (separation color spaces) bersandar pada mesin yang sama untuk pekerjaan yang sama sekali berbeda. Ruang pemisahan (Separation space), didefinisikan dalam ISO 32000-1 §8.6.6.4, mewakili pewarna tunggal, tinta spot seperti Pantone atau pernis, dengan memasangkan nama dengan transformasi tint: fungsi yang memetakan nilai tint satu dimensi, 0 untuk tanpa tinta hingga 1 untuk tinta penuh, ke ruang warna alternatif yang sebenarnya dapat dirender oleh perangkat, biasanya CMYK. Transformasi tint tersebut sering kali berupa fungsi Tipe 0, dan sekarang kisi tersebut hanya memiliki satu sumbu masukan.

Ini adalah kontras yang jelas dengan LUT 3D. Tinta spot memiliki satu derajat kebebasan, sehingga transformasi tint-nya memerlukan satu masukan dan kisinya adalah garis sampel, masing-masing menyimpan nilai CMYK (atau alternatif lain) pada tingkat tint tersebut. Kubus RGB membutuhkan tiga masukan karena domainnya bersifat tiga dimensi dan saluran-salurannya berinteraksi. Jenis fungsi yang sama, aturan interpolasi yang sama, dimensi yang berbeda; spesifikasi menggunakan kembali satu evaluator dan membiarkan /Size memutuskan apakah Anda sedang berjalan di garis, bidang, atau kubus. HotPDF membungkus seluruh pemisahan dalam RegisterSeparationLUT, yang membangun transformasi tint Tipe 0 satu masukan dari array byte datar secara internal dan mengembalikan nama sumber daya ruang warna.

var
  SpotCS: AnsiString;
begin
  // Four CMYK output bytes per tint grid point, tint domain [0..1].
  // Here 0% ink -> all zero, 100% ink -> a rich spot build,
  // with two interior steps; the tint transform interpolates between.
  SpotCS := Pdf.RegisterSeparationLUT(
    'PANTONE 286 C',         // colorant name
    'DeviceCMYK',            // alternate color space
    [  0,   0,   0,   0,     // tint 0.00 -> 0,0,0,0
      90,  60,   0,   0,     // tint 0.33
     100,  80,   0,  10,     // tint 0.66
     100,  72,   0,  18]);   // tint 1.00 -> full ink build
  // Use SpotCS with SetFillColorSpace / SetFillColor on a page.
end;

Jumlah sampel harus berupa angka bulat dari titik kisi: kelipatan positif dari jumlah komponen ruang alternatif, dan setidaknya dua titik agar ada segmen yang diinterpolasi. Teruskan tiga byte per titik terhadap alternatif CMYK dan panggilan tersebut akan menolaknya, validasi defensif yang sama yang diterapkan oleh pembaan 3D, yang merupakan apa yang Anda inginkan dari fungsi yang jika tidak divalidasi akan gagal secara diam-diam pada waktu cetak.

Di mana mesin yang sama muncul kembali

Begitu Anda melihat Tipe 0 sebagai tabel interpolasi generik, dua fitur kontrol perangkat lainnya tidak lagi terlihat seperti kasus khusus. Fungsi transfer (transfer function) menyesuaikan nilai komponen dalam perjalanannya ke perangkat keluaran, dan itu hanyalah fungsi per saluran; HotPDF mendaftarkannya sebagai ExtGState melalui RegisterTransferFunctionState, yang menerima satu fungsi gabungan atau array fungsi per saluran. Karena fungsi-fungsi tersebut adalah objek fungsi biasa, Anda dapat menyerahkan THPDFStreamObject yang dikembalikan oleh RegisterSampledFunction dan menggerakkan kurva transfer dari tabel sampel alih-alih sebuah rumus.

var
  ToneFn: THPDFStreamObject;
  GsName: AnsiString;
begin
  // A single-input, single-output sampled tone curve on [0,1].
  ToneFn := Pdf.RegisterSampledFunction(
    [0,1], [0,1], [256], 8, ToneCurveBytes, 1);

  // Apply it to all channels as a combined /TR2 transfer function.
  GsName := Pdf.RegisterTransferFunctionState(ToneFn, []);
  // Select GsName on the page before drawing the affected content.
end;

Black generation dan undercolor removal berada dalam keluarga yang sama. Ketika perangkat mengonversi RGB ke CMYK, perangkat tersebut memutuskan seberapa banyak komponen abu-abu yang akan dibawa sebagai tinta hitam, dan spesifikasi menyatakan keputusan tersebut sebagai fungsi, entri /BG2 dan /UCR2 dari kamus status-grafis (graphics-state dictionary), masing-masing berupa kurva masukan tunggal dari abu-abu yang dihitung ke jumlah hitam. Itu adalah fungsi Tipe 0 juga ketika Anda menginginkan kurva terukur alih-alih kurva analitik, yang dibangun dengan cara yang sama melalui RegisterSampledFunction dan ditempatkan dalam status grafis. Pelajaran yang patut diingat adalah bahwa fungsi PDF bukanlah tempat terjadinya manajemen warna; fungsi tersebut adalah tabel pencarian yang membawa keputusan yang Anda buat dengan mesin warna nyata, dan Tipe 0 adalah satu-satunya jenis fungsi yang cukup fleksibel untuk membawa keputusan apa pun.

Untuk gambaran yang lebih luas tentang bagaimana font, gambar, dan sumber daya warna dikeluarkan ke dalam dokumen akhir, lihat panduan kami tentang keluaran laporan dengan font dan gambar. Ketika keluaran harus bertahan dari pemeriksaan kepatuhan (preflight check) pengarsipan atau pencetakan, aturan ruang warna (color-space) dan maksud keluaran (output-intent) yang dibahas dalam panduan validasi PDF/A, PDF/X, dan PDF/UA mengatur fungsi mana yang diizinkan dan bagaimana warna perangkat harus ditandai. Semua ini dikirim dalam HotPDF Component untuk Delphi dan C++Builder, bersama dengan API shading, ICC, dan pemisahan yang dibangun di atas inti Tipe 0 yang sama.