Technical Article

3D tablice pretraživanja boja (LUT) u PDF-u s funkcijama uzorkovanja tipa 0

PDF funkcije su jedan od tiših kutova specifikacije. Većina programera susreće se s njima samo jednom, kao s nečim što je potrebno aksijalnom sjenčanju tipa 2 (Type 2 axial shading) kako bi prelazilo između dviju boja, i više ih nikada ne pogledaju. To je šteta, jer je mehanizam funkcija mali evaluator opće namjene koji format ponovno koristi za sjenčanja, prijenosne funkcije, rasterske točke, tonove separacije i krivulje prijenosa mekih maski. Od četiri tipa funkcija, tip 0 je najmoćniji i najmanje shvaćen. To je funkcija uzorkovanja (sampled function): višedimenzionalna mreža izlaznih vrijednosti između kojih čitatelj interpolira. Budući da mreža može sadržavati bilo koje brojeve koje u nju unesete, funkcija tipa 0 može izraziti proizvoljno nelinearno mapiranje, što je točan oblik tablice za pretraživanje boja (lookup table).

Ovaj članak prolazi kroz rječnik tipa 0 kako ga definira ISO 32000-1 u §7.10.2, a zatim prikazuje dva slučaja koja su najvažnija u cjevovodu dokumenata: LUT za korekciju boja s tri ulaza (RGB-u-RGB) i transformaciju tona spot boje s jednim ulazom. Isti graditelj funkcija uzorkovanja služi za oba slučaja, a razlika među njima je isključivo u tome koliko ulaza mreža ima.

Funkcija uzorkovanja je mreža koju čitatelj interpolira

Funkcija tipa 0 mapira m-ulazni vektor u n-izlazni vektor pohranjivanjem uzoraka na pravilnoj mreži i interpolacijom 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 osi. /Range drži dva broja po izlaznoj komponenti. /Size je niz od m cijelih brojeva koji daju broj uzoraka duž svake ulazne osi, pa mreža koja ima dvanaest uzoraka po stranici u tri dimenzije ima /Size [12 12 12] i pohranjuje 1.728 mrežnih točaka. /BitsPerSample postavlja preciznost svake pohranjene vrijednosti; HotPDF prihvaća 1, 2, 4, 8, 12, 16, 24 i 32 bita, što odgovara vrijednostima koje dopušta tablica 38.

Tok uzoraka čita se fiksnim redoslijedom. Prva ulazna dimenzija mijenja se najbrže, zatim druga i tako dalje, a na svakoj mrežnoj točki pohranjeno je n izlaznih komponenti redom. Za RGB-u-RGB tablicu to su tri bajta po mrežnoj točki pri osam bita, raspoređeni kao crveni izlaz, zeleni izlaz, plavi izlaz, prebrisani najprije preko crvenog ulaza. Još dva ključa mapiraju kontinuirani svijet na cjelobrojnu mrežu. /Encode mapira svaki ulaz iz njegovog intervala /Domain u raspon indeksa uzorka od 0 do Size[i] - 1, a /Decode mapira sirove pohranjene cijele brojeve natrag na intervale /Range. Kada ih ostavite na zadanim vrijednostima, ulaz koji obuhvaća [0 1] slijeće na cijelu mrežu, a pohranjeni bajt od 255 dekodira se na vrh svog izlaznog raspona, što je upravo ono što [0,1]-normalizirani LUT boja zahtijeva.

Red 1 nasuprot Reda 3

Između mrežnih točaka čitatelj mora interpolirati, a /Order odabire kako. /Order 1 je multilinearna interpolacija: linearna duž jedne osi, bilinearna preko dvije, trilinearna preko tri. Brza je, to je točno ono što radi hardver u većini preglednika, a za glatku transformaciju boja obično se ne razlikuje od bilo čega složenijeg. /Order 3 zahtijeva interpolaciju kubičnim splineom, koja prilagođava glađu krivulju kroz uzorke uz cijenu više rada i šireg područja podrške oko svake evaluirane točke.

Kompromis je gustoća mreže nasuprot glatkoći krivulje. Kubični red se isplati kada je mreža rijetka, a mapiranje ima vidljivu zakrivljenost, jer ravna linija između dva udaljena uzorka može izravnati krivulju tonova na način koji oko primjećuje na gradijentima. Kada je mreža gusta, segmenti su dovoljno kratki da linearna interpolacija blisko prati krivulju, a kubična donosi malo koristi. Praktično pravilo je posegnuti za /Order 3 samo s malim mrežama ili strmim transformacijama, a inače ostaviti linearnu zadanu vrijednost. Napomena: /Order se primjenjuje samo na funkcije tipa 0, a HotPDF odbija bilo koju vrijednost osim 1 ili 3.

3D LUT: tri ulaza, tri izlaza

RGB-u-RGB korekcija boja je školski primjer za mrežu s tri ulaza, klasični 3D LUT koji se koristi u gradiranju boja i usklađivanju uređaja. Svaka os kocke je jedan ulazni kanal, svaka mrežna točka pohranjuje ispravljenu RGB trojku za tu ulaznu koordinatu, a čitatelj trilinearno interpolira kutne uzorke oko bilo koje dolazne boje. Tri ulaza su ovdje neizbježna jer ispravljena crvena može ovisiti o ulaznoj zelenoj i plavoj, a ne samo o ulaznoj crvenoj; krivulja po kanalu ne može izraziti preslušavanje kanala, ali kocka može.

HotPDF gradi tok tipa 0 putem RegisterSampledFunction, koji izravno uzima /Domain, /Range, /Size, /BitsPerSample i bajtove uzorka te vraća objekt funkcije. Za standardnu normaliziranu kocku prosljeđujete granice [0,1] na sve tri ulazne osi i sva tri izlaza, veličinu N x N x N i izravnatu tablicu uzoraka. Graditelj provjerava odgovara li broj bajtova mreži: za bajtovno poravnatu dubinu očekuje OutputCount x (BitsPerSample div 8) x umnožak veličina, i podiže iznimku ako je niz pogrešne duljine, tako da pogrešno izračunati korak (stride) glasno zakaže pri registraciji, umjesto da se kasnije prikaže kao smeće.

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 točnost kocke leži u tome kako je ispunjavate, a ne u PDF funkciji. Pravi put je izračunati svaku mrežnu točku putem ICC-upravljane konverzije, istog motora koji pokreće probni otisak na zaslonu (soft-proof), tako da brojevi u mreži znače nešto u odnosu na definirani izvorni i odredišni profil. Registrirajte profile koji ograničavaju konverziju pomoću RegisterICCProfile, što bilježi prostor boja ICCBased (1, 3 ili 4 komponente) i vraća naziv resursa koji možete priložiti sadržaju koji LUT hrani. Funkcija tipa 0 nosi tablicu interpolacije; ICC profil nosi značenje krajnjih točaka.

1D slučaj: transformacija tona spot boje

Separacijski prostori boja oslanjaju se na isti mehanizam za potpuno drugačiji posao. Separacijski prostor (Separation space), definiran u ISO 32000-1 §8.6.6.4, predstavlja jedno bojilo, spot tintu kao što je Pantone ili lak, uparivanjem naziva s transformacijom tona: funkcijom koja mapira jednodimenzionalnu vrijednost tona, od 0 za bez tinte do 1 za punu tintu, na alternativni prostor boja koji uređaj zapravo može iscrtati, obično CMYK. Ta transformacija tona je često funkcija tipa 0, i sada mreža ima točno jednu ulaznu os.

To je jasan kontrast s 3D LUT-om. Spot tinta je jedan stupanj slobode, pa njezina transformacija tona treba jedan ulaz i mreža je linija uzoraka, od kojih svaki drži CMYK (ili drugu alternativnu) vrijednost na toj razini tona. RGB kocka treba tri ulaza jer je njezina domena trodimenzionalna i kanali međusobno djeluju. Isti tip funkcije, ista pravila interpolacije, različita dimenzionalnost; specifikacija ponovno koristi jedan evaluator i dopušta da /Size odluči hodate li po liniji, ravnini ili kocki. HotPDF omotava cijelu separaciju u RegisterSeparationLUT, koji interno gradi jednounosnu transformaciju tona 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 cijeli broj mrežnih točaka: pozitivni višekratnik broja komponenti alternativnog prostora, i najmanje dvije točke kako bi postojao segment za interpolaciju. Proslijedite tri bajta po točki za CMYK alternativu i poziv će to odbiti, što je ista obrambena provjera koju primjenjuje 3D graditelj, a to je ono što želite od funkcije koja bi inače tiho zakazala u vrijeme ispisa.

Gdje se isti mehanizam ponovno pojavljuje

Jednom kada vidite tip 0 kao generičku tablicu interpolacije, još dvije značajke upravljanja uređajem prestaju izgledati kao posebni slučajevi. Prijenosna funkcija prilagođava vrijednosti komponenti na njihovom putu do izlaznog uređaja, i to je samo funkcija po kanalu; HotPDF je registrira kao ExtGState putem RegisterTransferFunctionState, koji prihvaća ili jednu kombiniranu funkciju ili niz funkcija po kanalu. Budući da su te funkcije obični objekti funkcija, možete im proslijediti sam THPDFStreamObject koji RegisterSampledFunction vraća i upravljati krivuljom prijenosa iz uzorkovane tablice umjesto 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;

Generiranje crne boje (black generation) i uklanjanje podboja (undercolor removal) nalaze se u istoj obitelji. Kada uređaj pretvara RGB u CMYK, on odlučuje koliko će sive komponente nositi kao crnu tintu, a specifikacija izražava tu odluku kao funkciju, unose /BG2 i /UCR2 rječnika grafičkog stanja, od kojih je svaki krivulja s jednim ulazom od izračunate sive do količine crne. To su također funkcije tipa 0 kada želite izmjerenu krivulju umjesto analitičke, izgrađene na isti način putem RegisterSampledFunction i smještene u grafičko stanje. Pouka koju vrijedi zapamtiti jest da se PDF funkcija nikada ne bavi upravljanjem bojama; to je tablica pretraživanja koja nosi odluku koju ste donijeli s pravim slikovnim motorom za boje, a tip 0 je jedini tip funkcije koji je dovoljno fleksibilan da nosi bilo koju odluku.

Za širu sliku o tome kako se fontovi, slike i resursi boja emitiraju u gotov dokument, pogledajte naš vodič kroz izlaz izvješća s fontovima i slikama. Kada izlaz mora preživjeti provjeru usklađenosti za arhiviranje ili ispis (preflight), pravila o prostorima boja i namjeri izlaza (output-intent) pokrivena u vodiču za validaciju PDF/A, PDF/X i PDF/UA određuju koje su od ovih funkcija dopuštene i kako boja uređaja mora biti označena. Sve se to isporučuje u HotPDF komponenti za Delphi i C++Builder, uz API-je za sjenčanje, ICC i separaciju koji se grade na istoj jezgri tipa 0.