Předtiskárna posílá zakázku zpět: tatáž náplň spot se oddělila na dvě desky. HotPDF tomu brání už při autorování, když píše NChannel jako pětiprvkovou formu DeviceN podle ISO 32000-2 a drží jediný kanonický alternativní prostor a tint transformaci na název spotu pro celý dokument; druhou, kolidující definici odmítá místo emitování
NChannel není název rodiny barevných prostorů
První věc, kterou se odnaučit, je samotný název. NChannel není rodina barevných prostorů tak, jak rodinami jsou Separation a DeviceN. ISO 32000-2 §8.6.6.5 ho popisuje jako podtyp DeviceN, takže korektní NChannel prostor se zapisuje jako pětiprvkové pole [/DeviceN names alternateSpace tintTransform attributes] a slovník atributů nese /Subtype /NChannel. Pole [/NChannel ...] ve specifikaci neexistuje. Stavili jste-li si někdy jedno ručně a sledovali, jak na něj RIP krčí rameny, tohle je důvod
HotPDF si to jednou vykládal špatně a pak to opravil, což stojí za vyslovení nahlas, protože to formuje chování komponenty dnes. Starší verze HotPDF emitovaly formu s názvem rodiny. THotPDF.RegisterNChannelColorSpace dnes emituje jen standardní formu DeviceN plus atributy a protože podtyp NChannel přišel s PDF 1.6, vstupní bod producenta braní na RequirePDFVersion(pdf16, ...) a na starších cílech prostě odpadá. Renderovací strana je záměrně shovívavější než zapisovač: HPDFResolveColorSpace stále přijímá starý token /NChannel jako rodinu DeviceN, takže soubory ze starého zapisovače se dál renderují, ale vše, co HotPDF zapisuje zpět, používá standardní kódování. Shovívavý vstup, přísný výstup je tady správná asymetrie, protože váš čtenář musí zvládnout soubory, které nevytvořil, kdežto váš zapisovač takovou výmluvu nemá
Proč končí jeden název spotu na dvou deskách?
Protože název colorantu spotu je identita desky v rozsahu celého dokumentu, ne lokální argument. Dvě volání, která obě jmenují Orange, ale předávají jiný alternativní prostor, nebo tentýž alternativní prostor s jinou tint transformací, popisují dvě různé náplně, kterým se shodou okolností pletou štítek. RIP stavěcí separace nemá jak to smířit, takže udělá jedinou poctivou věc a dá vám dvě desky. HotPDF si proto drží kanonickou signaturu na colorant název pro dokument. RegisterSpotColorantDefinition tu signaturu skládá z alternativního barevného prostoru a tvaru tint funkce a skrz ni prochází každé RegisterSeparation, RegisterSeparationFunc, RegisterSeparationLUT i definice spotu pro NChannel. Když se druhá definice rozchází, volání vyhazuje místo tichého zaregistrování druhé varianty a hlášení je záměrně konkrétní ohledně režimu selhání, protože alternativa je objevit to na zkouškové desce o tři týdny později
// Orange už byl zaregistrován proti DeviceCMYK s tint transformací
// 0 / 0.55 / 1 / 0 při plné 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;
Rozdělení master názvů na process a spot
Úplný NChannel musí započítat každý svůj master colorant název přesně jednou, buď jako process komponentu, nebo jako colorant spotu. Pokročilé přetížení RegisterNChannelColorSpace přijímá master ColorantNames, ProcessColorantNames, alternativní prostor, celkovou tint transformaci, pole záznamů THPDFNChannelSpotColorant a volitelné tiskové pořadí. Každý záznam spotu nese vlastní název, vlastní jednovstupovou tint transformaci Separation, volitelnou soliditu a volitelnou funkci dot-gain. Celková tint transformace musí mapovat N vstupů na počet komponent alternativního prostoru; každá tint spotu musí mapovat jeden vstup na tentýž počet
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);
Z tohoto volání emituje HotPDF slovník atributů, jaký žádá specifikace: /Subtype /NChannel, slovník /Process, jehož /ColorSpace je process prostor a jehož /Components seznam process názvů v pořadí komponent toho prostoru, slovník /Colorants držící skutečné pole [/Separation name alternate tintfn] pro každý spot a slovník /MixingHints nesoucí /Solidities, /PrintingOrder a /DotGain, když jste je dodali. Vrácený název zdroje jde do SetFillColorSpace nebo SetStrokeColorSpace úplně stejně jako u jednodušších prostorů z článku o renderování spot barev Separation a DeviceN
Co kontrola konzistence skutečně odmítá?
Odmítá strukturální nesourodost uvnitř prostoru a dělá to, než se zapíše jediný objekt. Colorant názvy musejí být unikátní a nesmí být prázdné, All ani None. Process a spot definice dohromady musejí pokrýt master názvy přesně, bez colorantu v obou rolích a bez nedefinovaného zbytku. Je-li alternativním prostorem DeviceCMYK, musejí být process komponenty Cyan, Magenta, Yellow, Black v tomto pořadí a počet process názvů musí odpovídat počtu komponent alternativního prostoru. Každá tint transformace i dot-gain funkce musí být nepřímý funkční objekt se správnou aritou vstupů a výstupů. Solidita musí být konečná hodnota uvnitř 0..1. Tiskové pořadí musí být prázdné nebo úplná permutace master názvů, nikdy částečný seznam. Co nedělá, je soudit barvu: nic tady nekontroluje, že vaše tint transformace Orange skutečně připomíná náplň v kanystru, že její CMYK sestava je zdravý zástupný proxy, nebo že dodaná solidita odpovídá naměřenému chování na substrátu. To jsou otázky tisku a měření a komponenta nemá mandát je odpovídat. Jednodušší přetížení jen pro process je designem ještě přísnější: vyrábí NChannel jen s process a záměrně odmítá přijímat názvy spotů, protože zápis spotu do pole názvů bez odpovídající položky /Colorants by vyrobil strukturálně nekorektní soubor a vymýšlení výchozí definice by bylo horší než selhání
Output intents PDF/X-6n musí pokrýt každý zaregistrovaný spot
Soubor PDF/X-6n s N coloranty deklaruje své coloranty dvakrát a obě deklarace se musí shodovat. AddPDFX6ExternalOutputIntent zapisuje referenci externího ICC profilu s jeho ColorantTable a předtím ValidateRegisteredSpotOutputColorants projde každý spot, který si dokument zaregistroval, a vyhodí, když v tabulce chybí. Kontrola běží oběma směry: jakmile output intent publikoval svůj seznam colorantů, pozdější registrace spotu na název mimo ten seznam je odmítnuta také. AddPDFX6ExternalOutputIntentSpotData přidává metadata po inku navrch a vymáhá vlastní pravidla, zejména že colorant nese buď hodnotu solidity, nebo spektrální data CxF/X-4, nikdy obojí. To je týž povrch shody, o němž pojednává článek o validaci PDF/A, PDF/X a PDF/UA
Spectral := TMemoryStream.Create;
try
LoadCxFForInk('Orange', Spectral); // payload 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], // solidita pro jeden colorant
Order,
['Orange'], [Spectral]); // spektrální data pro jiný
finally
Spectral.Free;
end;
Dva provozní detaily se lehce minou. Registr, který tohle všechno podepírá, je per dokument a maže se na dokumentových hranicích, takže načtení nového souboru do téže instance THotPDF nezdědí identity spotů předchozího dokumentu; ta izolace je smyslem věci, protože uniklá signatura by odmítla naprosto korektní práci v další zakázce. Strana profilu má navíc vlastní tvrdé limity: externí output intent vyžaduje cíl PDF 2.0, absolutní URL profilu HTTP nebo HTTPS, čtyřbajtovou signaturu ICC barevného prostoru a pro PDF/X-6n mezi 2 a 15 coloranty s odpovídající signaturou 2CLR až FCLR
Kde kontrola končí
Zpracování CxF/X-4 je kus, u něhož být upřímný. HotPDF aplikuje ohraničené strukturální bezpečnostní kontroly na spektrální proud a potvrdí, že identita inku uvnitř odpovídá colorantu, který jste pojmenovali. Uzavírá velikost payloadu, odmítá vložené nulové bajty, zavrhuje jakýkoli proud obsahující deklaraci DOCTYPE nebo ENTITY, vyžaduje rozeznatelný kořen CxF a vyžaduje přesně jeden element SpotInkCharacterisation nesoucí přesně jedno SpotInkName rovnající se názvu vašeho colorantu. To je brána proti deformovanému a nepřátelskému vstupu, ne schéma validátor. Není to kompletní implementace ISO 17972-4, neověřuje vaše spektrální měření a neodaudituje zpětně libovolné předem existující objektové grafy třetích stran ani vnitřní tabulky colorantů uvnitř vloženého ICC profilu. Závisí-li vaše workflow na úplné shodě CxF, validujte soubor specializovaným nástrojem, než ho předáte komponentě
Jedno sousedící omezení kousne lidi, kteří by ho nikdy nečekali. Měkká maska luminosity nemůže použít Separation, DeviceN ani NChannel jako svou /CS průhlednostní skupiny; míchací prostor skupiny musí být device nebo CIE-based prostor, takže barva spotu uvnitř skupiny se rozliší přes tint transformaci do alternativního prostoru, než se spočítá luminosity. RegisterLuminositySoftMaskState staví skupinu DeviceGray přesně proto, aby se to nemohlo pokazit omylem. Praktický důsledek je, že design plný spotů maskovaný tímto způsobem se hodnotí přes svůj CMYK proxy, ne přes svou náplň, což zvážíte, když ho srovnáváte se separovanou zkouškou, jak popisují poznámky o overprint proofingu a render zařízeních
Nic z toho neodbývá potřebu zkouškové desky, ale přemisťuje celou třídu předtiskových odmítnutí z tiskárny zpátky do buildu. API NChannel, Separation a output intentu PDF/X-6n popsaná zde putují ve standardní HotPDF Delphi Component pro Delphi a C++Builder, kde reference dokumentuje úplná rozložení záznamů a přesné podmínky, za nichž každé volání selhává zavřeně