Technical Article

3D LUT-ovi za boje u PDF-u sa uzorkovanim funkcijama tipa 0

PDF funkcije su jedan od mirnijih delova specifikacije. Većina programera ih sretne samo jednom, kao stvar koja je potrebna aksijalnom senčenju tipa 2 da bi izbledelo između dve boje, i nikada više ne pogledaju. To je šteta, jer je mehanizam funkcija mali evaluator opšte namene koji format ponovo koristi za senčenja, prenosne funkcije, funkcije rastera, nijanse razdvajanja i krive prenosa meke maske. Od četiri tipa funkcija, tip 0 je najmoćniji i najmanje shvaćen. To je uzorkovana funkcija: višedimenzionalna mreža izlaznih vrednosti između kojih čitač interpolira. Pošto mreža može da sadrži bilo koje brojeve koje u nju unesete, funkcija tipa 0 može da izrazi proizvoljno nelinearno mapiranje, što je tačan oblik tabele za pretragu boja.

Ovaj članak prolazi kroz rečnik tipa 0 onako kako ga definiše standard ISO 32000-1 u §7.10.2, a zatim prikazuje dva slučaja koja su najvažnija u toku rada sa dokumentima: LUT za korekciju boja sa tri ulaza RGB-u-RGB i transformaciju nijanse spot-boje sa jednim ulazom. Isti graditelj uzorkovanih funkcija služi za oba slučaja, a razlika među njima je isključivo pitanje broja ulaza koje mreža ima.

Uzorkovana funkcija je mreža koju čitač interpolira

Funkcija tipa 0 mapira vektor od m ulaza u vektor od n izlaza tako što čuva uzorke na pravilnoj mreži i vrši interpolaciju između njih. ISO 32000-1 §7.10.2 navodi ključeve koji opisuju tu mrežu. /Domain sadrži dva broja po ulazu, donju i gornju granicu svake ulazne ose. /Range sadrži dva broja po izlaznoj komponenti. /Size je niz od m celih brojeva koji daju broj uzoraka duž svake ulazne ose, tako da mreža koja ima dvanaest uzoraka po strani u tri dimenzije ima /Size [12 12 12] i čuva 1.728 mrežnih tačaka. /BitsPerSample postavlja preciznost svake sačuvane vrednosti; HotPDF prihvata 1, 2, 4, 8, 12, 16, 24 i 32 bita, što odgovara vrednostima koje dozvoljava tabela 38.

Tok uzoraka se čita po fiksnom redosledu. Prva ulazna dimenzija se menja najbrže, zatim druga, i tako dalje, a u svakoj mrežnoj tački se n izlaznih komponenti čuva po redu. Za tabelu RGB-u-RGB to je tri bajta po mrežnoj tački na osam bita, raspoređeno kao crveni izlaz, zeleni izlaz, plavi izlaz, pri čemu se prvo prolazi kroz crveni ulaz. Još dva ključa mapiraju kontinualni svet na celobrojnu mrežu. /Encode mapira svaki ulaz iz njegovog /Domain intervala u opseg indeksa uzorka 0 do Size[i] - 1, a /Decode mapira sirove sačuvane cele brojeve nazad na /Range intervale. Kada ih ostavite na podrazumevanim vrednostima, ulaz koji obuhvata [0 1] sleže se čisto na punu mrežu, a sačuvani bajt od 255 se dekodira na vrh svog izlaznog opsega, što je upravo ono što LUT za boje normalizovan na [0,1] zahteva.

Redosled 1 naspram redosleda 3

Između mrežnih tačaka čitač mora da izvrši interpolaciju, a /Order bira kako. /Order 1 je multilinearna interpolacija: linearna duž jedne ose, bilinearna preko dve, trilinearne preko tri ose. Brza je, to je tačno ono što hardver u većini čitača radi, i za glatku transformaciju boja obično se ne razlikuje od bilo čega složenijeg. /Order 3 zahteva interpolaciju kubnim splajnom, koja prilagođava glatkiju krivu kroz uzorke po cenu više rada i šireg regiona podrške oko svake procenjene tačke.

Kompromis je gustina mreže naspram glatkoće krive. Kubni redosled se isplati kada je mreža gruba i mapiranje ima vidljivu zakrivljenost, jer prava linija između dva udaljena uzorka može izravnati krivu tonova na način koji oko primećuje na gradijentima. Kada je mreža gusta, segmenti su dovoljno kratki da linearna interpolacija blisko prati krivu, a kubna donosi malo poboljšanja. Praktično pravilo je da posegnete za /Order 3 samo kod malih mreža ili strmih transformacija, a inače je ostavite na linearnoj podrazumevanoj vrednosti. Imajte na umu da se /Order odnosi samo na funkcije tipa 0, a HotPDF odbacuje bilo koju vrednost osim 1 ili 3.

3D LUT: tri ulaza, tri izlaza

Korekcija boja RGB-u-RGB je školski primer za mrežu sa tri ulaza, klasični 3D LUT koji se koristi u gradiranju boja i usklađivanju uređaja. Svaka osa kocke je jedan ulazni kanal, svaka mrežna tačka čuva korigovanu RGB trojku za tu ulaznu koordinatu, a čitač vrši trilinearnu interpolaciju uzoraka uglova oko bilo koje dolazne boje. Tri ulaza su ovde neizbežna jer korigovana crvena može da zavisi od ulazne zelene i plave, a ne samo od ulazne crvene; kriva po kanalu ne može da izrazi preslušavanje kanala, ali kocka može.

HotPDF gradi tok tipa 0 kroz funkciju RegisterSampledFunction, koja direktno uzima /Domain, /Range, /Size, /BitsPerSample i bajtove uzoraka i vraća objekat funkcije. Za standardnu normalizovanu kocku prosleđujete granice [0,1] na sve tri ulazne ose i sva tri izlaza, veličinu N x N x N i poravnatu tabelu uzoraka. Graditelj proverava da li broj bajtova odgovara mreži: za bajt-poravnatu dubinu očekuje OutputCount x (BitsPerSample div 8) x proizvod veličina, i prijavljuje grešku ako je niz pogrešne dužine, tako da pogrešno izračunat korak ne uspeva bučno prilikom registracije, a ne kao smeće pri kasnijem renderovanju.

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;

Kolorimetrijska ispravnost kocke leži u tome kako je popunjavate, a ne u PDF funkciji. Pravi put je da izračunate svaku tačku mreže kroz ICC-upravljanu konverziju, isti mehanizam koji pokreće softverski probni otisak, tako da brojevi u mreži znače nešto u odnosu na definisani profil izvora i odredišta. Registrujte profile koji ograničavaju konverziju pomoću RegisterICCProfile, što beleži prostor boja zasnovan na ICC-u (1, 3 ili 4 komponente) i vraća ime resursa koje možete zakačiti za sadržaj koji LUT napaja. Funkcija tipa 0 nosi tabelu interpolacije; ICC profil nosi značenje krajnjih tačaka.

1D slučaj: transformacija nijansi spot-boje

Separacioni prostori boja se oslanjaju na isti mehanizam za potpuno drugačiji posao. Separacioni prostor, definisan u standardu ISO 32000-1 §8.6.6.4, predstavlja jednu boju, spot mastilo kao što je Pantone ili lak, uparujući ime sa transformacijom nijanse: funkcijom koja mapira jednodimenzionalnu vrednost nijanse, od 0 za bez mastila do 1 za puno mastilo, na alternativni prostor boja koji uređaj zapravo može da renderuje, obično CMYK. Ta transformacija nijanse je često funkcija tipa 0, a mreža sada ima tačno jednu ulaznu osu.

Ovo je jasan kontrast sa 3D LUT-om. Spot boja ima jedan stepen slobode, tako da njenoj transformaciji nijansi treba jedan ulaz i mreža je linija uzoraka, od kojih svaki drži CMYK vrednost na tom nivou nijanse. RGB kocki su potrebna tri ulaza jer je njen domen trodimenzionalan i kanali međusobno deluju. Isti tip funkcije, ista pravila interpolacije, drugačija dimenzionalnost; specifikacija ponovo koristi jedan evaluator i dozvoljava da /Size odluči da li hodate linijom, ravni ili kockom. HotPDF obmotava celu separaciju u RegisterSeparationLUT, koji interno gradi jednocifrenu transformaciju nijanse tipa 0 iz ravnog niza bajtova i vraća naziv resursa prostora boja.

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;

Broj uzoraka mora biti ceo broj mrežnih tačaka: pozitivni umnožak broja komponenti alternativnog prostora, i najmanje dve tačke tako da postoji segment za interpolaciju. Prosledite tri bajta po tački protiv CMYK alternative i poziv to odbija, istu defanzivnu proveru koju 3D graditelj primenjuje, što je ono što želite od funkcije koja će inače tiho propasti u vreme štampanja.

Gde se isti mehanizam ponovo pojavljuje

Kada shvatite tip 0 kao generičku tabelu interpolacije, još dve funkcije za kontrolu uređaja prestaju da izgledaju kao posebni slučajevi. Prenosna funkcija prilagođava vrednosti komponenti na njihovom putu do izlaznog uređaja, i to je samo funkcija po kanalu; HotPDF je registruje kao ExtGState kroz RegisterTransferFunctionState, koji prihvata ili jednu kombinovanu funkciju ili niz funkcija po kanalu. Pošto su te funkcije obični objekti funkcija, možete im proslediti upravo onaj THPDFStreamObject koji RegisterSampledFunction vraća i voditi prenosnu krivu iz uzorkovane tabele umesto iz formule.

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;

Generisanje crne i uklanjanje podboja spadaju u istu porodicu. Kada uređaj konvertuje RGB u CMYK, on odlučuje koliko sive komponente će nositi kao crno mastilo, a specifikacija izražava tu odluku kao funkciju, unose /BG2 i /UCR2 u rečnik grafičkog stanja, od kojih je svaka jednocifrena kriva od izračunate sive do količine crne. To su takođe funkcije tipa 0 kada želite izmerenu krivu umesto analitičke, izgrađene na isti način preko RegisterSampledFunction i postavljene u grafičko stanje. Pouka koju vredi zapamtiti jeste da se upravljanje bojama nikada ne dešava u PDF funkciji; to je tabela za pretragu koja prenosi odluku koju ste doneli sa stvarnim mehanizmom za boje, a tip 0 je jedini tip funkcije dovoljno fleksibilan da prenese bilo koju odluku.

Za širu sliku o tome kako se fontovi, slike i resursi boja emituju u gotov dokument, pogledajte naš vodič kroz izveštavanje sa fontovima i slikama. Kada izlaz mora da preživi arhivsku ili grafičku proveru, pravila o prostoru boja i nameri izlaza pokrivena u vodiču kroz validaciju za PDF/A, PDF/X i PDF/UA određuju koje od ovih funkcija su dozvoljene i kako boja uređaja mora biti označena. Sve to se isporučuje u HotPDF komponenti za Delphi i C++Builder, zajedno sa API-jima za senčenje, ICC i separaciju koji se grade na istom jezgru tipa 0.