Technical Article

3D spalvų LUT PDF dokumentuose su Type 0 diskrečiosiomis funkcijomis

PDF funkcijos yra viena tylesnių specifikacijos sričių. Dauguma programuotojų su jomis susiduria tik kartą, kai Type 2 ašiniam šešėliavimui reikia pereiti tarp dviejų spalvų, ir daugiau į jas nežiūri. Tai yra klaida, nes funkcijų mechanizmas yra nedidelis bendrosios paskirties vertintojas, kurį formatas pakartotinai naudoja šešėliavimui, perdavimo funkcijoms, pustonių taškų funkcijoms, skyrimo atspalviams ir švelnių kaukių perdavimo kreivėms. Iš keturių funkcijų tipų Type 0 yra galingiausias ir mažiausiai suprantamas. Tai yra diskrečioji funkcija: daugiadmenis išvesties reikšmių tinklelis, tarp kurių skaitytuvas atlieka interpoliaciją. Kadangi tinklelyje gali būti bet kokie jūsų įvesti skaičiai, Type 0 funkcija gali išreikšti savavališką netiesinį atvaizdavimą, o to yra tiksli spalvų paieškos lentelės forma

Šiame straipsnyje apžvelgiamas Type 0 žodynas, kaip jį apibrėžia ISO 32000-1 §7.10.2 skyriuje, o tada parodomi du atvejai, kurie yra svarbiausi dokumentų konvejeryje: trijų įvesčių RGB-to-RGB spalvų korekcijos LUT ir vienos įvesties taškinės spalvos atspalvio transformacija. Tas pats diskrečiosios funkcijos kūrėjas tinka abiem atvejais, o skirtumas tarp jų yra tik tinklelio įvesčių skaičius

Diskrečioji funkcija yra tinklelis, kuriame skaitytuvas atlieka interpoliaciją

Type 0 funkcija susieja m įvesčių vektorių su n išvesčių vektoriumi, išsaugodama pavyzdžius reguliariame tinklelyje ir interpoliuodama tarp jų. ISO 32000-1 §7.10.2 skyriuje išvardyti raktai, apibūdinantys tą tinklelį. /Domain saugo du skaičius kiekvienai įvesčiai – apatinę ir viršutinę kiekvienos įvesties ašies ribą. /Range saugo du skaičius kiekvienam išvesties komponentui. /Size yra m sveikųjų skaičių masyvas, nurodantis pavyzdžių skaičių išilgai kiekvienos įvesties ašies, todėl tinklelis, turintis dvylika pavyzdžių kiekvienoje iš trijų dimensijų, turi /Size [12 12 12] ir saugo 1728 tinklelio taškus. /BitsPerSample nustato kiekvienos išsaugotos reikšmės tikslumą; HotPDF priima 1, 2, 4, 8, 12, 16, 24 ir 32 bitus, atitinkančius 38 lentelėje leidžiamas reikšmes

Pavyzdžių srautas skaitomas nustatyta tvarka. Pirmoji įvesties dimensija kinta greičiausiai, tada antroji ir t. t., o kiekviename tinklelio taške nurodyta tvarka išsaugomi n išvesties komponentai. Trijų baitų vienam tinklelio taškui esant aštuoniems bitams RGB-to-RGB lentelėje išdėstymas yra raudonos išvestis, žalios išvestis, mėlynos išvestis, pirmiausia perbraukiant raudoną įvestį. Dar du raktai susieja nepertraukiamą pasaulį su sveikųjų skaičių tinkleliu. /Encode susieja kiekvieną įvestį iš jos /Domain intervalo su pavyzdžio indekso diapazonu nuo 0 iki Size[i] - 1, o /Decode susieja neapdorotus išsaugotus sveikuosius skaičius atgal su /Range intervalais. Kai paliekate numatytąsias reikšmes, įvestis, apimanti [0 1], švariai patenka į pilną tinklelį, o išsaugotas 255 baitas iškoduojamas į viršutinę išvesties diapazono dalį, ko ir reikia [0,1] normalizuotam spalvų LUT

Eilė 1 prieš eilę 3

Tarp tinklelio taškų skaitytuvas turi atlikti interpoliaciją, o /Order parenka, kaip. /Order 1 yra daugialinijinė interpoliacija: tiesinė išilgai vienos ašies, dvitiesė per dvi, tritiesė per tris. Ji yra greita, tai yra būtent tai, ką daro daugelio peržiūros programų aparatinė įranga, ir sklandžiam spalvų transformavimui ji paprastai nesiskiria nuo sudėtingesnių būdų. /Order 3 reikalauja kubinės splaino interpoliacijos, kuri sukuria lygesnę kreivę per pavyzdžius, tačiau reikalauja daugiau darbo ir platesnės palaikymo srities aplink kiekvieną vertinamą tašką

Kompromisas yra tinklelio tankis prieš kreivės lygumą. Kubinė eilė yra naudinga, kai tinklelis yra grubus, o atvaizdavimas turi pastebimą kreivumą, nes tiesi linija tarp dviejų tolimų pavyzdžių gali suplokštinti tono kreivę taip, kad akis pastebės gradientus. Kai tinklelis yra tankus, segmentai yra pakankamai trumpi, kad tiesinė interpoliacija glaudžiai sektų kreivę, o kubinė duoda mažai naudos. Praktinė taisyklė yra naudoti /Order 3 tik su mažais tinkleliais arba stačiomis transformacijomis, o kitu atveju palikti tiesinį numatytąjį nustatymą. Atminkite, kad /Order taikomas tik Type 0 funkcijoms, o HotPDF atmeta bet kokią kitą reikšmę, išskyrus 1 arba 3

3D LUT: trys įvestys, trys išvestys

RGB-to-RGB spalvų korekcija yra vadovėlinis trijų įvesčių tinklelio atvejis – klasikinė 3D LUT, naudojama spalvų klasifikavimui ir įrenginių suderinimui. Kiekviena kubo ašis yra vienas įvesties kanalas, kiekvienas tinklelio taškas saugo pakoreguotą RGB trejetą tai įvesties koordinatei, o skaitytuvas tritiesiu būdu interpoliuoja kampinius pavyzdžius aplink bet kurią gaunamą spalvą. Trys įvestys čia yra neišvengiamos, nes pakoreguota raudona spalva gali priklausyti nuo įvesties žalios ir mėlynos, o ne tik nuo įvesties raudonos; vieno kanalo kreivė negali išreikšti kanalų tarpusavio įtakos, bet kubas gali

HotPDF sukuria Type 0 srautą per RegisterSampledFunction, kuri priima /Domain, /Range, /Size, /BitsPerSample ir pavyzdžių baitus tiesiogiai bei grąžina funkcijos objektą. Standardiniam normalizuotam kubui perduodate [0,1] ribas visose trijose įvesties ašyse ir visose trijose išvestyse, N x N x N dydį ir suplokštintą pavyzdžių lentelę. Kūrėjas patikrina, ar baitų skaičius atitinka tinklelį: esant baitais lygiuotam gyliui, jis tikisi OutputCount x (BitsPerSample div 8) x dydžių sandaugos, ir pateikia klaidą, jei masyvas yra netinkamo ilgio, todėl neteisingai apskaičiuotas žingsnis registracijos metu sukelia klaidą, o ne vėliau pateikia sugadintą vaizdą

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;

Kubo kolorimetrinis teisingumas priklauso nuo to, kaip jį užpildote, o ne nuo PDF funkcijos. Teisingas kelias yra apskaičiuoti kiekvieną tinklelio tašką per ICC valdomą konversiją – tą patį variklį, kuris valdo bandomąjį spaudinį, kad tinklelio skaičiai reikštų kažką konkretaus apibrėžtam šaltinio ir tikslo profiliui. Užregistruokite profilius, kurie riboja konversiją, naudodami RegisterICCProfile, kuri įrašo ICCBased spalvų erdvę (1, 3 arba 4 komponentus) ir grąžina ištekliaus pavadinimą, kurį galite pridėti prie turinio, kurį maitina LUT. Type 0 funkcija neša interpoliacijos lentelę; ICC profilis neša galinių taškų reikšmę

1D atvejis: taškinės spalvos atspalvio transformacija

Atskiros spalvų erdvės (angl. separation color spaces) remiasi tuo pačiu mechanizmu visiškai kitam darbui. Separation erdvė, apibrėžta ISO 32000-1 §8.6.6.4 skyriuje, reprezentuoja vieną dažiklį, taškinį rašalą, pavyzdžiui, Pantone arba laką, susiedama pavadinimą su atspalvio transformacija: funkcija, kuri susieja vienmatę atspalvio reikšmę (nuo 0 – be rašalo iki 1 – pilnas rašalas) su alternatyvia spalvų erdve, kurią įrenginys iš tikrųjų gali atvaizduoti, dažniausiai CMYK. Ši atspalvio transformacija dažnai yra Type 0 funkcija, ir dabar tinklelis turi lygiai vieną įvesties ašį

Tai yra aiškus kontrastas su 3D LUT. Taškinis rašalas yra vienas laisvės laipsnis, todėl jo atspalvio transformacijai reikia vienos įvesties, o tinklelis yra pavyzdžių linija, kurios kiekviena saugo CMYK (arba kitą alternatyvią) reikšmę tame atspalvio lygyje. RGB kubui reikia trijų įvesčių, nes jo sritis yra trimatė ir kanalai sąveikauja. Tas pats funkcijos tipas, tos pačios interpoliacijos taisyklės, skirtingas matmenų skaičius; specifikacija pakartotinai naudoja vieną vertintoją ir leidžia /Size nuspręsti, ar vaikštote linija, plokštuma ar kubu. HotPDF apgaubia visą atskyrimą RegisterSeparationLUT, kuri viduje sukuria vienos įvesties Type 0 atspalvio transformaciją iš plokščio baitų masyvo ir grąžina spalvų erdvės ištekliaus pavadinimą

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;

Pavyzdžių skaičius turi būti sveikas tinklelio taškų skaičius: teigiamas alternatyvios erdvės komponentų skaičiaus kartotinis ir bent du taškai, kad būtų segmentas interpoliavimui. Perduokite tris baitus vienam taškui prieš CMYK alternatyvą ir iškvietimas jį atmes – tą patį gynybinį patvirtinimą taiko 3D kūrėjas, o to ir norisi iš funkcijos, kuri kitaip tyliai sugestų spausdinimo metu

Kur tas pats mechanizmas pasirodo vėl

Kai pamatysite Type 0 kaip bendrąją interpoliacijos lentelę, dar dvi įrenginio valdymo funkcijos nustos atrodyti kaip specialūs atvejai. Perdavimo funkcija koreguoja komponentų reikšmes pakeliui į išvesties įrenginį, ir tai yra tik funkcija kiekvienam kanalui; HotPDF ją užregistruoja kaip ExtGState per RegisterTransferFunctionState, kuri priima arba vieną bendrą funkciją, arba per kanalo funkcijų masyvą. Kadangi šios funkcijos yra įprasti funkcijų objektai, galite jai perduoti tą patį THPDFStreamObject, kurį grąžina RegisterSampledFunction, ir valdyti perdavimo kreivę iš diskrečiosios lentelės, o ne pagal formulę

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;

Juodos spalvos generavimas ir spalvos po ja pašalinimas (angl. undercolor removal) priklauso tai pačiai šeimai. Kai įrenginys konvertuoja RGB į CMYK, jis nusintendžia, kiek pilko komponento pernešti kaip juodą rašalą, o specifikacija šį sprendimą išreiškia kaip funkciją – grafikos būsenos žodyno /BG2 ir /UCR2 įrašus, kurių kiekvienas yra vienos įvesties kreivė nuo apskaičiuotos pilkos iki juodos spalvos kiekio. Tai taip pat yra Type 0 funkcijos, kai norite išmatuotos kreivės, o ne analitinės, sukurtos tuo pačiu būdu per RegisterSampledFunction ir patalpintos grafikos būsenoje. Pamoka, kurią verta atsiminti, yra ta, kad PDF funkcija niekata nėra ta vieta, kur vyksta spalvų valdymas; tai yra paieškos lentelė, kuri perneša jūsų sprendimą, priimtą su tikru spalvų varikliu, o Type 0 yra vienintelis funkcijų tipas, pakankamai lankstus, kad perneštų bet kokį sprendimą

Norėdami gauti platesnį vaizdą apie tai, kaip šriftai, vaizdai ir spalvų ištekliai išleidžiami į baigtą dokumentą, žr. mūsų ataskaitos išvesties su šriftais ir vaizdais apžvalgą. Kai išvestis turi išgyventi archyvavimo arba spausdinimo patikrą prieš skrydį (angl. preflight), spalvų erdvės ir išvesties tikslo (angl. output intent) taisyklės, aprašytos PDF/A, PDF/X ir PDF/UA patvirtinimo vadove, reglamentuoja, kurios iš šių funkcijų yra leidžiamos ir kaip turi būti pažymėta įrenginio spalva. Visa tai tiekiama HotPDF komponente, skirtame Delphi ir C++Builder, kartu su šešėliavimo, ICC ir atskyrimo API, kurios remiasi tuo pačiu Type 0 branduoliu