Et prepress-bureau sender jobbet tilbage: den samme spotfarve er separeret ud på to plader. HotPDF forhindrer det allerede ved skrivetidspunktet ved at skrive NChannel som ISO 32000-2 DeviceN-formen med fem elementer og ved at holde ét kanonisk alternativt farverum og én tinttransform pr. spotnavn for hele dokumentet og afvise den anden, modstridende definition i stedet for at emitere den
NChannel er ikke navnet på en farverumsfamilie
Det første, man skal aflære, er selve navnet. NChannel er ikke en farverumsfamilie på samme måde, som Separation og DeviceN er familier. ISO 32000-2 §8.6.6.5 beskriver det som en subtype af DeviceN, så et standardoverholdende NChannel-farverum skrives som arrayet med fem elementer [/DeviceN names alternateSpace tintTransform attributes], og attributordbogen bærer /Subtype /NChannel. Der findes intet [/NChannel ...]-array i specifikationen. Har du nogensinde bygget et i hånden og set en RIP ignorere det, er det derfor
HotPDF fik dette forkert én gang og rettede det derefter, hvilket er værd at sige rent ud, fordi det former, hvordan komponenten opfører sig i dag. Ældre HotPDF-udgaver emitterede familienavnsformen. THotPDF.RegisterNChannelColorSpace emitterer nu kun standardformen DeviceN-plus-attributter, og da NChannel-subtypen kom i PDF 1.6, stopper producentens indgangspunkt ved RequirePDFVersion(pdf16, ...) og takker nej på ældre mål. Rendersiden er bevidst mere eftergivende end skriveren: HPDFResolveColorSpace accepterer stadig det gamle /NChannel-token som en DeviceN-familie, så filer fra den gamle skriver fortsætter med at rendere, men alt, hvad HotPDF skriver ud igen, bruger den standardiserede kodning. Eftergivende på input, streng på output er den rigtige asymmetri her, fordi din læser skal klare filer, den ikke selv har skabt, mens din skriver ikke har den undskyldning
Hvorfor ender ét spotnavn på to plader?
Fordi et spotfarvenavn er en pladeidentitet for hele dokumentet, ikke et lokalt argument. To kald, der begge navngiver Orange, men overrækker et andet alternativt farverum, eller det samme alternative farverum med en anden tinttransform, beskriver to forskellige trykfarver, der tilfældigvis deler en etiket. En RIP, der bygger separationer, har ingen måde at forlige det på, så den gør det eneste ærlige og giver dig to plader. HotPDF vedligeholder derfor en kanonisk signatur pr. farvenavn pr. dokument. RegisterSpotColorantDefinition sammensætter den signatur ud fra det alternative farverum og formen på tintfunktionen, og hvert RegisterSeparation, RegisterSeparationFunc, RegisterSeparationLUT og hver NChannel-spotdefinition passerer gennem den. Når en anden definition er uenig, udløser kaldet en fejl i stedet for stille at registrere en anden variant, og meddelelsen er bevidst specifik om fejlmåden, fordi alternativet er at opdage det på en pladekorrektur tre uger senere
// Orange var allerede registreret mod DeviceCMYK med
// tinttransformen 0 / 0.55 / 1 / 0 ved fuld tint.
Conflicting := Pdf.RegisterExponentialFunction(
Domain1, NoInk, OtherOrangeCMYK, 1, []);
try
Pdf.RegisterSeparationFunc('Orange', 'DeviceCMYK', Conflicting);
except
on E: Exception do
// 'Spot colourant "Orange" har inkonsistent alternativt farverum
// eller tintdefinition i dette dokument'
LogPrepressWarning(E.Message);
end;
Opdeling af masternavnene i process og spot
Et komplet NChannel skal redegøre for hvert af sine masterfarvenavne præcis én gang, enten som proceskomponent eller som spotfarve. Den avancerede overbelastning af RegisterNChannelColorSpace tager masternavnene ColorantNames, ProcessColorantNames, det alternative farverum, tinttransformen i sin helhed, et array af THPDFNChannelSpotColorant-records og en valgfri trykkerækkefølge. Hver spotrecord bærer sit eget navn, sin egen Separation-tinttransform med ét input, en valgfri soliditet og en valgfri punktforstørrelsesfunktion. Tinttransformen i sin helhet skal afbilde N inputs til antallet af komponenter i det alternative farverum, og hver spot-tint skal afbilde ét input til det samme antal
const
Colorants: array[0..4] of AnsiString =
('Cyan', 'Magenta', 'Yellow', 'Black', 'Orange');
ProcessNames: array[0..3] of AnsiString =
('Cyan', 'Magenta', 'Yellow', 'Black');
Order: array[0..4] of AnsiString =
('Yellow', 'Magenta', 'Cyan', 'Orange', 'Black');
Domain5: array[0..9] of Single = (0, 1, 0, 1, 0, 1, 0, 1, 0, 1);
Range4: array[0..7] of Single = (0, 1, 0, 1, 0, 1, 0, 1);
Domain1: array[0..1] of Single = (0, 1);
NoInk: array[0..3] of Single = (0, 0, 0, 0);
OrangeCMYK: array[0..3] of Single = (0, 0.55, 1, 0);
GainC0: array[0..0] of Single = (0);
GainC1: array[0..0] of Single = (1);
var
Pdf: THotPDF;
Spots: array[0..0] of THPDFNChannelSpotColorant;
CSName: AnsiString;
begin
Pdf.Version := pdf20;
Pdf.BeginDoc;
Spots[0].Name := 'Orange';
Spots[0].TintTransform := Pdf.RegisterExponentialFunction(
Domain1, NoInk, OrangeCMYK, 1, []);
Spots[0].HasSolidity := True;
Spots[0].Solidity := 0.82;
Spots[0].DotGainFunction := Pdf.RegisterExponentialFunction(
Domain1, GainC0, GainC1, 1, []);
CSName := Pdf.RegisterNChannelColorSpace(Colorants, ProcessNames,
'DeviceCMYK',
Pdf.RegisterPostScriptFunction(Domain5, Range4,
'{ pop pop pop pop pop 0 0 0 0 }'),
Spots, Order);
Af det kald emitterer HotPDF den attributordbog, specifikationen kræver: /Subtype /NChannel, en /Process-ordbog, hvis /ColorSpace er procesfarverummet, og hvis /Components lister procesnavnene i den komponentrækkefølge, de har i det rum, en /Colorants-ordbog med et rigtigt [/Separation name alternate tintfn]-array for hver spot, og en /MixingHints-ordbog med /Solidities, /PrintingOrder og /DotGain, når du har leveret dem. Det returnerede ressourcenavn går til SetFillColorSpace eller SetStrokeColorSpace præcis som de enklere farverum, der behandles i artiklen om Separation- og DeviceN-spotfarverendering
Hvad afviser konsistenskontrollen reelt?
Den afviser strukturel inkohærens inden for farverummet, og det gør den, før et eneste objekt skrives. Farvenavne skal være unikke og må ikke være tomme, All eller None. Proces- og spotdefinitionerne skal til sammen dække masternavnene præcist, uden at nogen farve optræder i begge roller og uden at nogen efterlades udefineret. Når det alternative farverum er DeviceCMYK, skal proceskomponenterne være Cyan, Magenta, Yellow, Black i den rækkefølge, og antallet af procesnavne skal svare til antallet af komponenter i det alternative farverum. Hver tinttransform og punktforstørrelsesfunktion skal være et indirekte funktionsobjekt med den rigtige input- og output-arity. Soliditet skal være en endelig værdi inden for 0..1. Trykkerækkefølgen skal være tom eller en fuld permutation af masternavnene, aldrig en delvis liste. Det, den ikke gør, er at bedømme farven: intet her kontrollerer, at din Orange-tinttransform faktisk ligner blækket på dåsen, at dens CMYK-opbygning er en fornuftig proxy, eller at den leverede soliditet matcher målt adfærd på substratet. Det er presse- og målespørgsmål, og komponenten har ikke mandat til at svare på dem. Den enklere overbelastning med kun proces er strengere af design: den producerer et NChannel med kun proces og nægter bevidst at acceptere spotnavne, fordi at skrive en spot ind i navnearrayet uden en tilsvarende /Colorants-indgang ville give en strukturelt ikke-overholdende fil, og at fabrikere en standarddefinition ville være værre end at fejle
PDF/X-6n output intents skal dække hver registreret spot
En N-farve-PDF/X-6n-fil deklarerer sine farver to gange, og de to deklarationer skal stemme overens. AddPDFX6ExternalOutputIntent skriver den eksterne ICC-profilreference med sin ColorantTable, og inden den gør det, gennemgår ValidateRegisteredSpotOutputColorants hver spot, dokumentet har registreret, og udløser en fejl, hvis én mangler i tabellen. Kontrollen kører i begge retninger: når en output intent først har offentliggjort sin farveliste, afvises en senere spotregistrering af et navn uden for listen ligeledes. AddPDFX6ExternalOutputIntentSpotData lægger metadata pr. blæk ovenpå det og håndhæver sine egne regler, især at en farve bærer enten en soliditetsværdi eller CxF/X-4-spektraldata, aldrig begge. Det er den samme overholdelsesflade, som behandles i stykket om PDF/A-, PDF/X- og PDF/UA-validering
Spectral := TMemoryStream.Create;
try
LoadCxFForInk('Orange', Spectral); // ISO 17972-4-nyttelast
Pdf.AddPDFX6ExternalOutputIntentSpotData(
'ECG-5', 'Five-colour output condition',
'https://profiles.example.com/ecg-5.icc', '5CLR',
Colorants,
'00112233445566778899AABBCCDDEEFF', #4#3#0#0,
['Cyan'], [0.70], // soliditet for én farve
Order,
['Orange'], [Spectral]); // spektraldata for en anden
finally
Spectral.Free;
end;
To operationelle detaljer er lette at overse. Registret, der ligger bag alt dette, er pr. dokument og ryddes ved dokumentgrænser, så indlæsning af en ny fil i samme THotPDF-instans ikke arver det forrige dokuments spotidentiteter; isolationen er hele pointen, da en lækket signatur ville afvise helt gyldigt arbejde i det næste job. Og profilsiden har egne hårde grænser: en ekstern output intent kræver et PDF 2.0-mål, en absolut HTTP- eller HTTPS-profil-URL, en firebyte ICC-farverumssignatur og for PDF/X-6n mellem 2 og 15 farver med en matchende 2CLR- til FCLR-signatur
Hvor kontrollen stopper
CxF/X-4-håndteringen er den del, man skal være ærlig omkring. HotPDF udfører afgrænsede strukturelle sikkerhedskontroller af den spektrale strøm og bekræfter, at blækidentiteten indeni matcher den farve, du navngav. Den begrænser nyttelastens størrelse, afviser indlejrede null-byte, nægter enhver strøm med en DOCTYPE- eller ENTITY-deklaration, kræver en genkendelig CxF-rod og kræver præcis ét SpotInkCharacterisation-element, der bærer præcis ét SpotInkName, som svarer til dit farvenavn. Det er en port mod misdannet og fjendtligt input, ikke en skemavalidator. Det er ikke en komplet ISO 17972-4-implementering, den verificerer ikke dine spektrale målinger, og den laver ikke bagudrettet revision af vilkårlige, på forhånd eksisterende tredjeparts objektgrafer eller de interne farvetabeller i en indlejret ICC-profil. Hvis din arbejdsgang afhænger af fuld CxF-overholdelse, skal du validere filen med et dedikeret værktøj, inden du overrækker den til komponenten
En nærliggende begrænsning bider folk, der aldrig ventede at møde den. En luminositets-softmask må ikke bruge Separation, DeviceN eller NChannel som sin transparensgruppes /CS; gruppens blandingsfarverum skal være et device- eller CIE-baseret farverum, så spotmaling inde i gruppen løses gennem sin tinttransform til det alternative farverum, før luminositeten beregnes. RegisterLuminositySoftMaskState bygger netop af den grund en DeviceGray-gruppe, så det ikke kan gå galt ved et uheld. Den praktiske konsekvens er, at et spottungt design, der maskeres sådan, vurderes gennem sin CMYK-proxy og ikke sit blæk, hvilket betyder noget, når du sammenligner det med en separeret korrektur som beskrevet i noterne om overprint-korrektur og renderenheder
Ingen af dette fjerner behovet for en pladekorrektur, men det flytter en hel klasse af prepress-afvisninger fra presserummet tilbage til bygget. De NChannel-, Separation- og PDF/X-6n-output intent-metoder, der er beskrevet her, følger med den standard HotPDF Delphi Component til Delphi og C++Builder, hvor referencen dokumenterer de fulde record-layouts og de præcise betingelser, under hvilke hvert kald fejler lukket