Un atelier de photogravure renvoie le travail : la même encre spot séparée sur deux plaques. HotPDF empêche cela au moment de la rédaction en écrivant NChannel sous la forme DeviceN à cinq éléments de l’ISO 32000-2 et en gardant un espace alternatif canonique et une transformation de teinte uniques par nom de spot pour tout le document, en refusant la seconde définition conflictuelle au lieu de l’émettre
NChannel n’est pas un nom de famille d’espaces colorimétriques
La première chose à désapprendre, c’est le nom lui-même. NChannel n’est pas une famille d’espaces colorimétriques comme le sont Separation et DeviceN. L’ISO 32000-2 §8.6.6.5 le décrit comme un sous-type de DeviceN, si bien qu’un espace NChannel conforme s’écrit comme le tableau à cinq éléments [/DeviceN names alternateSpace tintTransform attributes], et le dictionnaire d’attributs porte /Subtype /NChannel. Il n’existe aucun tableau [/NChannel ...] dans la spécification. Si vous en avez déjà construit un à la main et regardé un RIP hausser les épaules, voilà pourquoi
HotPDF s’est trompé là-dessus une fois puis l’a corrigé, ce qui mérite d’être dit franchement car cela façonne le comportement actuel du composant. Les versions antérieures de HotPDF émettaient la forme à nom de famille. THotPDF.RegisterNChannelColorSpace n’émet désormais que la forme standard DeviceN avec attributs, et comme le sous-type NChannel est arrivé en PDF 1.6, le point d’entrée de production se verrouille sur RequirePDFVersion(pdf16, ...) et décline simplement sur des cibles plus anciennes. Le côté rendu est délibérément plus tolérant que l’écrivain : HPDFResolveColorSpace accepte encore le jeton historique /NChannel comme une famille DeviceN afin que les fichiers issus de l’ancien écrivain continuent de se rendre, mais tout ce que HotPDF réécrit utilise l’encodage standard. Tolérant en entrée, strict en sortie est la bonne asymétrie ici, car votre lecteur doit composer avec des fichiers qu’il n’a pas créés tandis que votre écrivain n’a aucune excuse de ce genre
Pourquoi un nom de spot finit-il sur deux plaques ?
Parce qu’un nom de colorant spot est une identité de plaque à l’échelle du document, pas un argument local. Deux appels qui nomment tous deux Orange mais remettent un espace alternatif différent, ou le même espace alternatif avec une transformation de teinte différente, décrivent deux encres différentes qui se partagent une étiquette par hasard. Un RIP qui construit des séparations n’a aucun moyen de les réconcilier, alors il fait la seule chose honnête et vous donne deux plaques. HotPDF maintient donc une signature canonique par nom de colorant et par document. RegisterSpotColorantDefinition compose cette signature à partir de l’espace colorimétrique alternatif et de la forme de la fonction de teinte, et chaque RegisterSeparation, RegisterSeparationFunc, RegisterSeparationLUT et définition de spot NChannel passe par elle. Quand une seconde définition est en désaccord, l’appel lève plutôt que d’enregistrer silencieusement une seconde variante, et le message est délibérément précis sur le mode d’échec, car l’alternative, c’est de le découvrir sur une épreuve de plaque trois semaines plus tard
// Orange était déjà enregistré contre DeviceCMYK avec la
// transformation de teinte 0 / 0.55 / 1 / 0 à teinte pleine.
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;
Répartir les noms maîtres entre procédé et spot
Un NChannel complet doit rendre compte de chacun de ses noms de colorants maîtres exactement une fois, comme composant de procédé ou comme colorant spot. La surcharge avancée de RegisterNChannelColorSpace prend les ColorantNames maîtres, les ProcessColorantNames, l’espace alternatif, la transformation de teinte globale, un tableau d’enregistrements THPDFNChannelSpotColorant, et un ordre d’impression facultatif. Chaque enregistrement de spot porte son propre nom, sa propre transformation de teinte Separation à entrée unique, une solidité facultative, et une fonction de gain de point facultative. La transformation de teinte globale doit faire correspondre N entrées au nombre de composants de l’espace alternatif ; chaque teinte de spot doit faire correspondre une entrée à ce même nombre
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);
De cet appel, HotPDF émet le dictionnaire d’attributs que la spécification demande : /Subtype /NChannel, un dictionnaire /Process dont /ColorSpace est l’espace de procédé et dont /Components liste les noms de procédé dans l’ordre des composants de cet espace, un dictionnaire /Colorants détenant un véritable tableau [/Separation name alternate tintfn] pour chaque spot, et un dictionnaire /MixingHints portant /Solidities, /PrintingOrder, et /DotGain quand vous les avez fournis. Le nom de ressource renvoyé va à SetFillColorSpace ou SetStrokeColorSpace exactement comme les espaces plus simples couverts dans l’article sur le rendu des couleurs spot Separation et DeviceN
Que refuse réellement le contrôle de cohérence ?
Il refuse l’incohérence structurelle à l’intérieur de l’espace, et il le fait avant qu’un seul objet ne soit écrit. Les noms de colorants doivent être uniques et ne doivent être ni vides, ni All, ni None. Les définitions de procédé et de spot doivent ensemble couvrir exactement les noms maîtres, sans colorant apparaissant dans les deux rôles et sans aucun laissé indéfini. Quand l’espace alternatif est DeviceCMYK, les composants de procédé doivent être Cyan, Magenta, Yellow, Black dans cet ordre, et le nombre de noms de procédé doit correspondre au nombre de composants de l’alternatif. Chaque transformation de teinte et chaque fonction de gain de point doivent être un objet fonction indirect avec les arités d’entrée et de sortie appropriées. La solidité doit être une valeur finie dans 0..1. L’ordre d’impression doit être vide ou une permutation complète des noms maîtres, jamais une liste partielle. Ce qu’il ne fait pas, c’est juger la couleur : rien ici ne vérifie que votre transformation de teinte Orange ressemble réellement à l’encre du pot, que sa composition CMYK est un mandataire sain, ou que la solidité fournie correspond au comportement mesuré sur le substrat. Ce sont des questions de presse et de mesure, et le composant n’a pas qualité pour y répondre. La surcharge plus simple, procédé seul, est encore plus stricte par conception : elle produit un NChannel de procédé seul et refuse délibérément d’accepter des noms de spot, car écrire un spot dans le tableau des noms sans entrée /Colorants correspondante produirait un fichier structurellement non conforme, et fabriquer une définition par défaut serait pire qu’échouer
Les output intents PDF/X-6n doivent couvrir chaque spot enregistré
Un fichier PDF/X-6n à N colorants déclare ses colorants deux fois, et les deux déclarations doivent concorder. AddPDFX6ExternalOutputIntent écrit la référence de profil ICC externe avec sa ColorantTable, et avant de le faire, ValidateRegisteredSpotOutputColorants parcourt chaque spot enregistré par le document et lève si l’un est absent de la table. Le contrôle tourne dans les deux sens : une fois qu’un output intent a publié sa liste de colorants, un enregistrement de spot ultérieur pour un nom en dehors de cette liste est refusé lui aussi. AddPDFX6ExternalOutputIntentSpotData ajoute par-dessus les métadonnées par encre, et il applique ses propres règles, notamment qu’un colorant porte soit une valeur de solidité, soit des données spectrales CxF/X-4, jamais les deux. C’est la même surface de conformité dont traite l’article sur la validation PDF/A, PDF/X et PDF/UA
Spectral := TMemoryStream.Create;
try
LoadCxFForInk('Orange', Spectral); // charge utile ISO 17972-4
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], // solidité pour un colorant
Order,
['Orange'], [Spectral]); // données spectrales pour un autre
finally
Spectral.Free;
end;
Deux détails opérationnels sont faciles à manquer. Le registre qui soutient tout cela est propre au document et est vidé aux frontières du document, si bien que charger un nouveau fichier dans la même instance THotPDF n’hérite pas des identités de spot du document précédent ; cet isolement est le but, car une signature qui fuite rejetterait un travail parfaitement valide dans le prochain job. Et le côté profil a ses propres limites dures : un output intent externe exige une cible PDF 2.0, une URL de profil HTTP ou HTTPS absolue, une signature d’espace colorimétrique ICC de quatre octets, et pour PDF/X-6n entre 2 et 15 colorants avec une signature 2CLR à FCLR correspondante
Là où le contrôle s’arrête
La gestion CxF/X-4 est la partie dont il faut parler honnêtement. HotPDF applique des contrôles de sécurité structurels bornés au flux spectral et confirme que l’identité d’encre à l’intérieur correspond au colorant que vous avez nommé. Il plafonne la taille de la charge utile, refuse les octets nuls embarqués, refuse tout flux contenant une déclaration DOCTYPE ou ENTITY, exige une racine CxF reconnaissable, et exige exactement un élément SpotInkCharacterisation portant exactement un SpotInkName égal à votre nom de colorant. C’est un verrou contre une entrée malformée et hostile, pas un validateur de schéma. Ce n’est pas une implémentation complète de l’ISO 17972-4, il ne vérifie pas vos mesures spectrales, et il n’audit pas à rebours des graphes d’objets tiers préexistants arbitraires ni les tables de colorants internes d’un profil ICC embarqué. Si votre flux de travail dépend d’une conformité CxF complète, validez le fichier avec un outil dédié avant de le remettre au composant
Une contrainte adjacente mord ceux qui ne s’y attendaient jamais. Un masque de luminosité ne peut pas utiliser Separation, DeviceN ou NChannel comme /CS de son groupe de transparence ; l’espace de fusion du groupe doit être un espace périphérique ou fondé sur CIE, si bien que la peinture spot à l’intérieur du groupe est résolue à travers sa transformation de teinte vers l’espace alternatif avant que la luminosité ne soit calculée. RegisterLuminositySoftMaskState construit un groupe DeviceGray précisément pour que cela ne puisse pas tourner mal par accident. La conséquence pratique est qu’un design riche en spots masqué de cette façon est évalué à travers son mandataire CMYK, pas son encre, ce qui compte quand vous le comparez à une épreuve séparée comme décrit dans les notes sur l’épreuvage de surimpression et les périphériques de rendu
Rien de tout cela ne supprime le besoin d’une épreuve de plaque, mais cela ramène toute une classe de rejets de photogravure de la salle de presse vers la construction. Les API NChannel, Separation et output intent PDF/X-6n décrites ici sont livrées dans le composant PDF HotPDF pour Delphi standard pour Delphi et C++Builder, où la référence documente les dispositions complètes des enregistrements et les conditions exactes sous lesquelles chaque appel échoue sans rien émettre