Funkcie PDF patria k menej známym častiam špecifikácie. Väčšina vývojárov sa s nimi stretne len raz, ako s prvkom, ktorý axiálne tieňovanie typu 2 (Type 2 axial shading) potrebuje na plynulý prechod medzi dvoma farbami, a už sa k nim nevráti. To je škoda, pretože mechanizmus funkcií je malý univerzálny vyhodnocovač, ktorý formát opakovane používa na tieňovanie, prenosové funkcie, rastrové bodové funkcie, odtiene separácie a prenosové krivky mäkkých masiek. Zo štyroch typov funkcií je typ 0 najvýkonnejší a najmenej pochopený. Ide o vzorkovanú funkciu: viacrozmernú mriežku výstupných hodnôt, medzi ktorými čítačka interpoluje. Keďže mriežka môže obsahovať akékoľvek čísla, ktoré do nej vložite, funkcia typu 0 dokáže vyjadriť ľubovoľné nelineárne mapovanie, čo je presný tvar vyhľadávacej tabuľky farieb (color lookup table).
Tento článok prechádza slovník typu 0 tak, ako ho definuje norma ISO 32000-1 v §7.10.2, a potom ukazuje dva prípady, na ktorých najviac záleží v spracovaní dokumentov: trojvstupovú farebnú korekčnú LUT tabuľku RGB-to-RGB a jednovstupovú transformáciu odtieňa priamej farby. Obe obsluhuje rovnaký nástroj na zostavenie vzorkovanej funkcie a rozdiel medzi nimi je čisto otázkou toho, koľko vstupov mriežka má.
Vzorkovaná funkcia je mriežka, ktorú čítačka interpoluje
Funkcia typu 0 mapuje m-vstupový vektor na n-výstupový vektor ukladaním vzoriek na pravidelnej mriežke a interpoláciou medzi nimi. ISO 32000-1 §7.10.2 uvádza kľúče, ktoré popisujú túto mriežku. /Domain obsahuje dve čísla na vstup, spodnú a hornú hranicu každej vstupnej osi. /Range obsahuje dve čísla na výstupnú zložku. /Size je pole m celých čísel udávajúcich počet vzoriek pozdĺž každej vstupnej osi, takže mriežka, ktorá má dvanásť vzoriek na stranu v troch rozmeroch, má /Size [12 12 12] a ukladá 1 728 bodov mriežky. /BitsPerSample nastavuje presnosť každej uloženej hodnoty; HotPDF podporuje 1, 2, 4, 8, 12, 16, 24 a 32 bitov, čo zodpovedá hodnotám, ktoré povoľuje tabuľka 38.
Tok vzoriek sa číta v pevnom poradí. Najrýchlejšie sa mení prvý vstupný rozmer, potom druhý atď., pričom v každom bode mriežky sú po sebe uložené n výstupné zložky. Pre tabuľku RGB-to-RGB sú to tri bajty na bod mriežky pri ôsmich bitoch, usporiadané ako výstup červenej, výstup zelenej, výstup modrej, pričom sa najprv prechádza červený vstup. Dva ďalšie kľúče mapujú spojitý svet na celočíselnú mriežku. /Encode mapuje každý vstup z jeho intervalu /Domain do rozsahu indexov vzoriek 0 až Size[i] - 1 a /Decode mapuje surové uložené celé čísla späť na intervaly /Range. Ak ich ponecháte na predvolených hodnotách, vstup v rozsahu [0 1] presne pokryje celú mriežku a uložený bajt s hodnotou 255 sa dekóduje na vrchol jeho výstupného rozsahu, čo je presne to, čo vyžaduje [0,1]-normalizovaná farebná LUT.
Rád 1 verzus Rád 3
Medzi bodmi mriežky musí čítačka interpolovať a /Order určuje ako. /Order 1 je multilineárna interpolácia: lineárna pozdĺž jednej osi, bilineárna naprieč dvoma, trilineárna naprieč troma. Je rýchla, je to presne to, čo robí hardvér vo väčšine prehliadačov, a pri hladkej transformácii farieb je zvyčajne nerozoznateľná od zložitejších metód. /Order 3 vyžaduje kubickú spline interpoláciu, ktorá prekladá hladšiu krivku cez vzorky za cenu väčšieho množstva práce a širšej oblasti podpory okolo každého vyhodnocovaného bodu.
Kompromisom je hustota mriežky verzus hladkosť krivky. Kubický poriadok sa oplatí vtedy, keď je mriežka riedka a mapovanie má viditeľné zakrivenie, pretože priama čiara medzi dvoma vzdialenými vzorkami môže sploštiť tónovú krivku spôsobom, ktorý ojo zachytí na prechodoch. Akonáhle je mriežka hustá, segmenty sú dostatočne krátke na to, aby lineárna interpolácia tesne sledovala krivku, a kubická prináša len málo. Praktickým pravidlom je siahnuť po /Order 3 len pri malých mriežkach alebo strmých transformáciách a inak ponechať predvolenú lineárnu hodnotu. Upozorňujeme, že /Order sa vzťahuje len na funkcie typu 0 a HotPDF odmieta akúkoľvek inú hodnotu ako 1 alebo 3.
3D LUT: tri vstupy, tri výstupy
Korekcia farieb RGB-to-RGB je učebnicovým príkladom pre trojvstupovú mriežku, klasickú 3D LUT používanú pri korekcii farieb a prispôsobení zariadení. Každá os kocky je jedným vstupným kanálom, každý bod mriežky ukladá opravenú trojicu RGB pre túto vstupnú súradnicu a čítačka trilineárne interpoluje rohové vzorky okolo akejkoľvek prichádzajúcej farby. Tri vstupy sú tu nevyhnutné, pretože korigovaná červená môže závisieť od vstupnej zelenej a modrej, nielen od vstupnej červenej; krivka pre jednotlivé kanály nedokáže vyjadriť presluchy medzi kanálmi, ale kocka áno.
HotPDF vytvára tok typu 0 prostredníctvom RegisterSampledFunction, ktorá priamo prijíma /Domain, /Range, /Size, /BitsPerSample a bajty vzoriek a vracia objekt funkcie. Pre štandardnú normalizovanú kocku odovzdávate hranice [0,1] na všetkých troch vstupných osiach aj troch výstupoch, rozmer N x N x N a sploštenú tabuľku vzoriek. Nástroj na zostavenie overuje, či počet bajtov zodpovedá mriežke: pre hĺbku zarovnanú na bajty očakáva OutputCount x (BitsPerSample div 8) x súčin rozmerov a vyvolá chybu, ak má pole nesprávnu dĺžku, takže nesprávne vypočítaný krok zlyhá hlučne už pri registrácii, namiesto toho, aby sa neskôr zobrazil ako nečitateľný odpad.
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;
Kolorimetrická správnosť kocky spočíva v tom, ako ju naplníte, nie vo funkcii PDF. Správnou cestou je vypočítať každý bod mriežky prostredníctvom konverzie riadenej profilom ICC, rovnakým enginom, ktorý riadi soft-proof, aby čísla v mriežke znamenali niečo voči definovanému zdrojovému a cieľovému profilu. Zaregistrujte profily, ktoré ohraničujú konverziu, pomocou RegisterICCProfile, čo zaznamená farebný priestor ICCBased (1, 3 alebo 4 zložky) a vráti názov zdroja, ktorý môžete pripojiť k obsahu, ktorý LUT sýti. Funkcia typu 0 nesie interpolačnú tabuľku; ICC profil nesie význam koncových bodov.
Prípad 1D: transformácia odtieňa priamej farby
Separačné farebné priestory sa opierajú o rovnaký mechanizmus pre úplne inú úlohu. Separačný priestor, definovaný v ISO 32000-1 §8.6.6.4, reprezentuje jedno farbivo, priamu farbu (spot ink) ako Pantone alebo lak, spojením názvu s transformáciou odtieňa (tint transform): funkciou, ktorá mapuje jednorozmernú hodnotu odtieňa, 0 pre žiadny atrament až po 1 pre plný atrament, na alternatívny farebný priestor, ktorý zariadenie dokáže skutočne vykresliť, zvyčajne CMYK. Táto transformácia odtieňa je často funkciou typu 0 a teraz má mriežka presne jednu vstupnú os.
Toto je jasný kontrast s 3D LUT. Priama farba je jedným stupňom voľnosti, takže jej transformácia odtieňa potrebuje jeden vstup a mriežka je radom vzoriek, z ktorých každá obsahuje hodnotu CMYK (alebo inú alternatívu) na danej úrovni odtieňa. Kocka RGB potrebuje tri vstupy, pretože jej doména je trojrozmerná a kanály navzájom reagujú. Rovnaký typ funkcie, rovnaké interpolačné pravidlá, iná dimenzionalita; špecifikácia opakovane používa jeden vyhodnocovač a necháva /Size rozhodnúť, či prechádzate po čiare, rovine alebo kocke. HotPDF obaľuje celú separáciu do RegisterSeparationLUT, čo vnútorne vytvára jednovstupovú transformáciu odtieňa typu 0 z plochého poľa bajtov a vracia názov zdroja farebného priestoru.
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;
Počet vzoriek musí byť celým počtom bodov mriežky: kladným násobkom počtu zložiek alternatívneho priestoru a aspoň dvoma bodmi, aby existoval segment na interpoláciu. Odovzdajte tri bajty na bod voči alternatíve CMYK a volanie to odmietne, čo je rovnaké defenzívne overenie, aké používa zostavovač 3D, čo je presne to, čo chcete od funkcie, ktorá by inak pri tlači potichu zlyhala.
Kde sa rovnaký mechanizmus objavuje znova
Akonáhle uvidíte typ 0 ako generickú interpolačnú tabuľku, ďalšie dve funkcie riadenia zariadenia prestanú vyzerať ako špeciálne prípady. Prenosová funkcia upravuje hodnoty zložiek na ich ceste k výstupnému zariadeniu, a ide len o funkciu pre každý kanál; HotPDF ju registruje ako ExtGState prostredníctvom RegisterTransferFunctionState, čo preberá buď jednu kombinovanú funkciu, alebo pole funkcií pre jednotlivé kanály. Keďže tieto funkcie sú bežnými objektmi funkcií, môžete im odovzdať presne ten THPDFStreamObject, ktorý vracia RegisterSampledFunction, a riadiť prenosovú krivku zo vzorkovanej tabuľky, a nie zo vzorca.
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;
Tvorba čiernej (black generation) a odstránenie podkladovej farby (undercolor removal) patria do rovnakej rodiny. Keď zariadenie prevádza RGB na CMYK, rozhoduje o tom, koľko sivej zložky prenesie ako čierny atrament, a špecifikácia vyjadruje toto rozhodnutie ako funkciu, položky /BG2 a /UCR2 slovníka grafického stavu (graphics-state), pričom každá je jednovstupovou krivkou od vypočítanej sivej k množstvu čiernej. Sú to tiež funkcie typu 0, ak chcete meranú krivku namiesto analytickej, vytvorené rovnakým spôsobom pomocou RegisterSampledFunction a umiestnené v grafickom stave. Ponaučenie, ktoré stojí za to si zapamätať, je, že funkcia PDF nie je nikdy miestom, kde dochádza k správe farieb; je to vyhľadávacia tabuľka, ktorá nesie rozhodnutie, ktoré ste urobili so skutočným farebným enginom, a typ 0 je jediný typ funkcie dostatočne flexibilný na to, aby niesol akékoľvek rozhodnutie.
Pre širší obraz o tom, ako sa písma, obrázky a farebné zdroje emitujú do hotového dokumentu, si pozrite nášho sprievodcu výstupom reportov s písmami a obrázkami. Keď musí výstup prežiť kontrolu predletovej prípravy (preflight) pre archív alebo tlač, pravidlá pre farebný priestor a výstupný zámer popísané v príručke na overenie PDF/A, PDF/X a PDF/UA riadia, ktoré z týchto funkcií sú povolené a ako sa musí označiť farba zariadenia. To všetko sa dodáva v komponente HotPDF Component pre Delphi a C++Builder spolu so shading, ICC a separačnými API, ktoré stavajú na rovnakom jadre typu 0.