Een prepress-bedrijf stuurt de klus terug: dezelfde steunkleur die op twee platen is gescheiden. HotPDF voorkomt dat op auteursmoment door NChannel te schrijven als de ISO 32000-2 vijfelementige DeviceN-vorm en door per spotnaam voor het hele document één canonieke alternatieve ruimte en tinttransformatie aan te houden, waarbij de tweede, conflicterende definitie wordt geweigerd in plaats van geëmitteerd
NChannel is geen familienaam voor kleurruimten
Het eerste wat u moet afleren is de naam zelf. NChannel is geen kleurruimtefamilie zoals Separation en DeviceN families zijn. ISO 32000-2 §8.6.6.5 beschrijft het als een subtype van DeviceN, dus een conforme NChannel-ruimte wordt geschreven als de vijfelementige array [/DeviceN names alternateSpace tintTransform attributes], en het attributes-dictionary draagt /Subtype /NChannel. Er bestaat geen [/NChannel ...]-array in de specificatie. Als u er ooit zelf een met de hand hebt gebouwd en een RIP hebt zien met de schouders ophalen, dat is de reden
HotPDF heeft dit één keer fout gedaan en het daarna gerepareerd, en dat is het eerlijk zeggen waard omdat het bepaalt hoe de component zich vandaag gedraagt. Oudere HotPDF-releases emitteerden de familienaamvorm. THotPDF.RegisterNChannelColorSpace emitteert nu alleen de standaard DeviceN-plus-attributes-vorm, en omdat het NChannel-subtype in PDF 1.6 kwam, gate het producer-entrypoint op RequirePDFVersion(pdf16, ...) en weigert het gewoon op oudere targets. De renderkant is opzettelijk vergevingsgezinder dan de writer: HPDFResolveColorSpace accepteert het legacy-token /NChannel nog steeds als een DeviceN-familie zodat bestanden uit de oude writer blijven renderen, maar alles wat HotPDF terugschrijft gebruikt de standaardencoding. Soepel op input, streng op output is hier de juiste asymmetrie, want uw reader moet omgaan met bestanden die het niet heeft gemaakt, terwijl uw writer die excuus niet heeft
Waarom belandt één spotnaam op twee platen?
Omdat een spotcolorantnaam een documentbrede plaatidentiteit is, geen lokaal argument. Twee aanroepen die allebei Orange noemen maar een andere alternatieve ruimte overhandigen, of dezelfde alternatieve ruimte met een andere tinttransformatie, beschrijven twee verschillende inkten die toevallig een label delen. Een RIP die separations bouwt heeft geen manier om dat te reconciliëren, dus doet het het enige eerlijke en geeft u twee platen. HotPDF houdt daarom per document een canonieke signature per colorantnaam bij. RegisterSpotColorantDefinition stelt die signature samen uit de alternatieve kleurruimte en de vorm van de tintfunctie, en elke RegisterSeparation, RegisterSeparationFunc, RegisterSeparationLUT en NChannel-spotdefinitie gaat erdoorheen. Wanneer een tweede definitie ervan afwijkt, gooit de aanroep een exceptie in plaats van stilletjes een tweede variant te registreren, en de melding is opzettelijk specifiek over de faalmodus, want het alternatief is het drie weken later op een plaatproef ontdekken
// Orange was al geregistreerd tegen DeviceCMYK met de
// tinttransformatie 0 / 0.55 / 1 / 0 bij volledige tint.
Conflicting := Pdf.RegisterExponentialFunction(
Domain1, NoInk, OtherOrangeCMYK, 1, []);
try
Pdf.RegisterSeparationFunc('Orange', 'DeviceCMYK', Conflicting);
except
on E: Exception do
// 'Spot colourant "Orange" has inconsistent alternate colour
// space or tint definition in this document'
LogPrepressWarning(E.Message);
end;
De master-namen opsplitsen in process en spot
Een complete NChannel moet voor elk van zijn master-colorantnamen exact één keer verantwoording afleggen, als procescomponent of als spotcolorant. De geavanceerde overload van RegisterNChannelColorSpace neemt de master-ColorantNames, de ProcessColorantNames, de alternatieve ruimte, de algehele tinttransformatie, een array met THPDFNChannelSpotColorant-records, en een optionele drukvolgorde. Elk spotrecord draagt zijn eigen naam, zijn eigen Separation-tinttransformatie met één input, een optionele solidity, en een optionele dot gain-functie. De algehele tinttransformatie moet N inputs mappen op het componentaantal van de alternatieve ruimte; elke spottint moet één input op datzelfde aantal mappen
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);
Uit die aanroep emitteert HotPDF het attributes-dictionary dat de spec vraagt: /Subtype /NChannel, een /Process-dictionary waarvan /ColorSpace de procesruimte is en waarvan /Components de procesnamen in de componentvolgorde van die ruimte opsomt, een /Colorants-dictionary met voor elke spot een echte [/Separation name alternate tintfn]-array, en een /MixingHints-dictionary met /Solidities, /PrintingOrder en /DotGain wanneer u die leverde. De teruggegeven resourcenaam gaat naar SetFillColorSpace of SetStrokeColorSpace, precies zoals bij de simpelere ruimten die het artikel over Separation- en DeviceN-spotkleurrendering behandelt
Wat wijst de consistentiecontrole werkelijk af?
Hij wijst structurele incoherentie binnen de ruimte af, en doet dat voordat er ook maar één object is geschreven. Colorantnamen moeten uniek zijn en mogen niet leeg zijn, All of None. Proces- en spotdefinities moeten samen de master-namen exact dekken, zonder dat een colorant in beide rollen voorkomt en zonder dat er een ongedefinieerd blijft. Wanneer de alternatieve ruimte DeviceCMYK is, moeten de procescomponenten Cyan, Magenta, Yellow, Black in die volgorde zijn, en het procesnaamaantal moet matchen met het componentaantal van de alternatieve ruimte. Elke tinttransformatie en dot gain-functie moet een indirect functieobject zijn met de juiste input- en outputariteit. Solidity moet een eindige waarde binnen 0..1 zijn. De drukvolgorde moet leeg zijn of een volledige permutatie van de master-namen, nooit een partiële lijst. Wat hij niet doet is kleur beoordelen: niks hier controleert of uw Orange-tinttransformatie werkelijk lijkt op de inkt in de blik, of zijn CMYK-opbouw een zinnige proxy is, of dat de solidity die u leverde matcht met gemeten gedrag op het substraat. Dat zijn pers- en meetvragen, en de component heeft geen standing om ze te beantwoorden. De simpelere process-only overload is by design nog strenger: hij produceert een process-only NChannel en weigert bewust spotnamen te accepteren, want een spot in de namenarray schrijven zonder matchende /Colorants-entry zou een structureel niet-conform bestand opleveren, en een standaarddefinitie verzinnen is erger dan falen
PDF/X-6n output intents moeten elke geregistreerde spot dekken
Een N-colorant PDF/X-6n-bestand declareert zijn colorants twee keer, en de twee declaraties moeten overeenkomen. AddPDFX6ExternalOutputIntent schrijft de externe ICC-profielreferentie met zijn ColorantTable, en voordat het dat doet, loopt ValidateRegisteredSpotOutputColorants elke spot na die het document heeft geregistreerd en gooit het een exceptie als er één in de tabel ontbreekt. De controle loopt in beide richtingen: zodra een output intent zijn colorantlijst heeft gepubliceerd, wordt een latere spotregistratie voor een naam buiten die lijst ook geweigerd. AddPDFX6ExternalOutputIntentSpotData voegt daarbovenop de per-inkt-metadata toe, en handhaaft zijn eigen regels, onder andere dat een colorant óf een solidity-waarde óf CxF/X-4-spectrale data draagt, nooit beide. Dit is hetzelfde conformantievlak als besproken in het stuk over PDF/A-, PDF/X- en PDF/UA-validatie
Spectral := TMemoryStream.Create;
try
LoadCxFForInk('Orange', Spectral); // ISO 17972-4-payload
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], // solidity voor één colorant
Order,
['Orange'], [Spectral]); // spectrale data voor een andere
finally
Spectral.Free;
end;
Twee operationele details zijn makkelijk te missen. Het register dat dit alles onderbouwt is per document en wordt gewist bij documentgrenzen, dus het laden van een nieuw bestand in dezelfde THotPDF-instantie erft de spotidentiteiten van het vorige document niet; die isolatie is het punt, want een gelekte signature zou volkomen geldig werk in de volgende klus weigeren. En de profielkant heeft eigen harde limieten: een externe output intent vereist een PDF 2.0-target, een absolute HTTP- of HTTPS-profiel-URL, een vierbyte ICC-kleurruimtesignature, en voor PDF/X-6n tussen 2 en 15 colorants met een matchende 2CLR tot FCLR-signature
Waar de controles stoppen
De CxF/X-4-afhandeling is het deel waar u eerlijk over moet zijn. HotPDF past begrensde structurele veiligheidscontroles toe op de spectrale stream en bevestigt dat de inktidentiteit erin matcht met de colorant die u noemde. Het capst de payloadgrootte, wijst ingesloten null-bytes af, weigert elke stream met een DOCTYPE- of ENTITY-declaratie, vereist een herkenbare CxF-root, en vereist exact één SpotInkCharacterisation-element dat exact één SpotInkName draagt die gelijk is aan uw colorantnaam. Dat is een poort tegen misvormde en vijandige input, geen schema-validator. Het is geen complete ISO 17972-4-implementatie, het verifieert uw spectrale metingen niet, en het her-audit geen willekeurige reeds bestaande third-party objectgraphs of de interne coloranttabellen binnen een ingesloten ICC-profiel. Als uw workflow van volledige CxF-conformance afhangt, valideer het bestand met een speciaal gereedschap voordat u het aan de component geeft
Eén aangrenzende beperking bijt mensen die haar nooit verwachtten te ontmoeten. Een luminosity soft mask kan Separation, DeviceN of NChannel niet gebruiken als /CS van zijn transparantiegroep; de groep-blending-ruimte moet een device- of CIE-based-ruimte zijn, dus spotverf binnen de groep wordt via zijn tinttransformatie naar de alternatieve ruimte opgelost voordat de luminosity wordt berekend. RegisterLuminositySoftMaskState bouwt een DeviceGray-groep juist zodat dit niet per ongeluk mis kan gaan. De praktische consequentie is dat een spotrijk ontwerp dat op deze manier gemaskd is wordt beoordeeld via zijn CMYK-proxy, niet via zijn inkt, wat telt wanneer u hem vergelijkt met een gescheiden proef zoals beschreven in de notities over overprint-proofing en render devices
Geen van dit alles haalt de noodzaak van een plaatproef weg, maar het verplaatst een hele klasse prepress-afwijzingen van de drukzaal terug naar de build. De hier beschreven NChannel-, Separation- en PDF/X-6n output intent-API's zitten in de standaard HotPDF Delphi Component voor Delphi en C++Builder, waar de referentie de volledige recordlayouts documenteert en de exacte voorwaarden waaronder elke aanroep faalt en dichtklapt