PDF-funksjoner er et av de roligere hjørnene av spesifikasjonen. De fleste utviklere møter dem én gang, som tingen en Type 2 aksial skyggelegging trenger for å tone ut mellom to farger, og ser aldri igjen. Det er synd, fordi funksjonsmaskineriet er en liten generell evaluator som formatet gjenbruker for skyggelegging, overføringsfunksjoner, rasterpunktfunksjoner (halftone spot functions), separasjonstoner og overføringskurver for myke masker. Av de fire funksjonstypene er Type 0 den kraftigste og minst forståtte. Det is en samplet funksjon: et flerdimensjonalt rutenett av utgangsverdier som leseren interpolerer mellom. Fordi rutenettet kan inneholde hvilke som helst tall du legger inn i det, kan en Type 0-funksjon uttrykke en vilkårlig ikke-lineær avbildning, som er den nøyaktige formen til en fargetabell (color lookup table).
Denne artikkelen går gjennom Type 0-ordboken slik ISO 32000-1 definerer den i §7.10.2, og viser deretter de to tilfellene som betyr mest i en dokumentbehandlingslinje: en tre-inngangs RGB-til-RGB fargekorrigerings-LUT, og en én-inngangs spotfarge-toningstransformasjon. Den samme samplede funksjonsbyggeren tjener begge, og forskjellen mellom dem er utelukkende et spørsmål om hvor mange innganger rutenettet har.
En samplet funksjon er et rutenett leseren interpolerer
En samplet funksjon avbilder en m-inngangsvektor til en n-utgangsvektor bygger på å lagre sampler på et regulært rutenett og interpolere mellom dem. ISO 32000-1 §7.10.2 lister opp nøklene som beskriver dette rutenettet. /Domain inneholder to tall per inngang, den nedre og øvre grensen for hver inngangsakse. /Range inneholder to tall per utgangskomponent. /Size er et array med m heltall som angir antall sampler langs hver inngangsakse, så et rutenett som er tolv sampler på en side i tre dimensjoner har /Size [12 12 12] og lagrer 1 728 rutenettpunkter. /BitsPerSample setter presisjonen for hver lagrede verdi; HotPDF godtar 1, 2, 4, 8, 12, 16, 24 og 32 biter, noe som samsvarer med verdiene tabell 38 tillater.
Samplingsstrømmen leses i en fast rekkefølge. Den første inngangsdimensjonen varierer raskest, deretter den andre osv., og ved hvert rutenettpunkt lagres de n utgangskomponentene i rekkefølge. For en RGB-til-RGB-tabell er det tre byte per rutenettpunkt ved åtte biter, lagt ut som rød-utgang, grønn-utgang, blå-utgang, sopt over den røde inngangen først. To nøkler til avbilder den kontinuerlige verdenen på heltallsrutenettet. /Encode avbilder hver inngang fra sitt /Domain-intervall til samplingsindeksområdet 0 til Size[i] - 1, og /Decode avbilder de rå lagrede heltallene tilbake til /Range-intervallene. Når du lar dem være på standardverdiene, lander en inngang som spenner over [0 1] lander rent på det fulle rutenettet, og en lagret byte på 255 dekodes til toppen av utgangsområdet, noe som er det en [0,1]-normalisert farge-LUT vil ha.
Order 1 mot Order 3
Mellom rutenettpunktene må leseren interpolere, og /Order velger hvordan. /Order 1 er multilineær interpolasjon: lineær langs én akse, bilineær over to, trilineær over tre. Det er raskt, det er akkurat det maskinvaren i de fleste visningsprogrammer gjør, og for en jevn fargetransformasjon er det vanligvis umulig å skille fra noe mer avansert. /Order 3 ber om kubisk spline-interpolasjon, som tilpasser en jevnere kurve gjennom samplene på bekostning av mer arbeid og et bredere støtteområde rundt hvert evaluerte punkt.
Kompromisset er rutenetttetthet mot kurvemykhet. Kubisk rekkefølge (Order 3) gjør seg fortjent til plassen når rutenettet er grovt og avbildningen har synlig krumning, fordi en rett linje mellom to fjerne sampler kan flate ut en tonekurve på en måte øyet oppdager på gradienter. Når rutenettet er tett, er segmentene korte nok til at lineær interpolasjon følger kurven tett, og kubisk kjøp gir lite. En praktisk regel er å bruke /Order 3 bare med små rutenett eller bratte transformasjoner, og ellers la den stå på det lineære standardvalget. Merk at /Order bare gjelder for Type 0-funksjoner, og HotPDF avviser alle andre verdier enn 1 eller 3.
3D LUT: tre innganger, tre utganger
En RGB-til-RGB fargekorrigering er læreboktilfellet for et tre-inngangs rutenett, den klassiske 3D-LUT-en som brukes i fargegradering og enhetsmatching. Hver akse i kuben er én inngangskanal, hvert rutenettpunkt lagrer den korrigerte RGB-trippelen for den inngangskoordinaten, og leseren interpolerer trilineært hjørnesamplene rundt enhver innkommende farge. Tre innganger er uunngåelig her fordi den korrigerte rødfargen kan avhenge av inngangsgrønn og inngangsblå, ikke bare av inngangsrød; en kurve per kanal kan ikke uttrykke krysstale mellom kanaler, men en kube kan.
HotPDF bygger Type 0-strømmen gjennom RegisterSampledFunction, som tar /Domain, /Range, /Size, /BitsPerSample og samplingsbyte direkte og returnerer funksjonsobjektet. For en standard normalisert kube sender du [0,1]-grenser på alle tre inngangsakser og alle tre utganger, en N x N x N-størrelse, og den flate samlingstabellen. Byggeren validerer at antall byte samsvarer med rutenettet: for en byte-justert dybde forventer den OutputCount x (BitsPerSample div 8) x produktet av størrelsene, og feiler hvis arrayet har feil lengde, slik at en feilberegnet trinnlengde (stride) feiler tydelig ved registrering i stedet for å vises som søppel senere.
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;
Den fargemessige korrektheten til kuben ligger i hvordan du fyller den, ikke i PDF-funksjonen. Den riktige veien er å beregne hvert rutenettpunkt gjennom en ICC-styrt konvertering, den samme motoren som driver en skjermprøve (soft-proof), slik at tallene i rutenettet betyr noe mot en definert kilde- og målprofil. Registrer profilene som begrenser konverteringen med RegisterICCProfile, som registrerer et ICCBased fargerom (1, 3 eller 4 komponenter) og returnerer et ressursnavn du kan knytte til innholdet som LUT-en mater. Type 0-funksjonen bærer interpolasjonstabellen; ICC-profilen bærer betydningen av endepunktene.
1D-tilfellet: en spotfarge-toningstransformasjon
Separasjonsfargerom lener seg på det samme maskineri for en helt annen jobb. Et Separation-fargerom, definert i ISO 32000-1 §8.6.6.4, representerer et enkelt fargestoff, et spotblekk som Pantone eller lakk, ved å koble et navn med en toningstransformasjon (tint transform): en funksjon som avbilder den endimensjonale toningsverdien, 0 for ingen blekk til 1 for fullt blekk, på et alternativt fargerom enheten faktisk kan gjengi, vanligvis CMYK. Den toningstransformasjonen er ofte en Type 0-funksjon, og nå har rutenettet nøyaktig én inngangsakse.
Dette er den tydelige kontrasten til 3D-LUT-en. Et spotblekk har én frihetsgrad, så dets toningstransformasjon trenger én inngang, og rutenettet er en linje med sampler der hver inneholder CMYK-verdien (eller annen alternativ verdi) på det toningsnivået. RGB-kuben trenger tre innganger fordi dens domene er tredimensjonalt og kanalene samhandler. Samme funksjonstype, same interpolasjonsregler, forskjellig dimensjonalitet; spesifikasjonen gjenbruker én evaluator og lar /Size bestemme om du går på en linje, et plan eller en kube. HotPDF pakker hele separasjonen inn i RegisterSeparationLUT, som bygger den én-inngangs Type 0-toningstransformasjonen fra et flatt byte-array internt og returnerer fargerom-ressursnavnet.
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;
Samplingsantallet må være et helt antall rutenettpunkter: et positivt multiplum av komponentantallet i det alternative rommet, og minst to punkter slik at det er et segment å interpolere. Sender du tre byte per punkt mot et CMYK-alternativ, avviser kallet det, den samme defensive valideringen som 3D-byggeren bruker, noe som er det du ønsker fra en funksjon som ellers vil feile lydløst under utskrift.
Hvor det samme maskineriet dukker opp igjen
Når du ser på Type 0 som en generisk interpolasjonstabell, ytterligere to enhetskontrollfunksjoner slutter å se ut som spesialtilfeller. En overføringsfunksjon (transfer function) justerer komponentverdier på vei til utdataenheten, og det er bare en funksjon per kanal; HotPDF registrerer den som en ExtGState gjennom RegisterTransferFunctionState, som godtar enten én kombinert funksjon eller et array med funksjoner per kanal. Fordi disse funksjonene er vanlige funksjonsobjekter, kan du gi den selve THPDFStreamObject-en som RegisterSampledFunction returnerer, og drive en overføringskurve fra en samplet tabell i stedet for en formel.
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;
Fargegenerering (black generation) og underfargefjerning (undercolor removal) hører til samme familie. Når en enhet konverterer RGB til CMYK, bestemmer den hvor mye av gråkomponenten som skal bæres som svart blekk, og spesifikasjonen uttrykker denne avgjørelsen som en funksjon, /BG2- og /UCR2-oppføringene i en grafikkstatusordbok, der hver er en enkelt-inngangskurve fra den beregnede gråfargen til en svartmengde. Disse er også Type 0-funksjoner når du vil ha en målt kurve i stedet for en analytisk en, bygget på samme måte gjennom RegisterSampledFunction og plassert i grafikkstatusen. Leksjonen verdt å huske er at PDF-funksjonen aldri er der fargestyringen skjer; det er oppslagstabellen som bærer en avgjørelse du tok med en ekte fargemotor, og Type 0 er den eneste funksjonstypen som er fleksibel nok til å bære enhver avgjørelse i det hele tatt.
For det bredere bildet av hvordan fonter, bilder og fargeressurser sendes ut i et ferdig dokument, se vår gjennomgang av rapportutdata med fonter og bilder. Når utdataene må overleve en arkiverings- eller utskriftskontroll (preflight check), reglene for fargerom og utdataintensjon dekket i PDF/A-, PDF/X- og PDF/UA-valideringsguiden styrer hvilke av disse funksjonene som er tillatt, og hvordan enhetsfarge må merkes. Alt dette leveres i HotPDF Component for Delphi og C++Builder, sammen med skyggeleggings-, ICC- og separasjons-API-ene som bygger på den samme Type 0-kjernen.