O tipografie de prepress trimite lucrarea înapoi: aceeași cerneală spot separată pe două plăci. HotPDF previne asta în momentul autorării scriind NChannel ca forma ISO 32000-2 cu cinci elemente de DeviceN și ținând un spațiu alternativ canonic și o transformare de tentă per nume de spot pentru tot documentul, respingând a doua definiție conflictuală în loc să o emită
NChannel nu este un nume de familie de spații de culoare
Primul lucru de dezînvățat este chiar numele. NChannel nu este o familie de spații de culoare așa cum Separation și DeviceN sunt familii. ISO 32000-2 §8.6.6.5 îl descrie ca un subtype al DeviceN, deci un spațiu NChannel conform este scris ca tabloul cu cinci elemente [/DeviceN names alternateSpace tintTransform attributes], iar dicționarul de atribute poartă /Subtype /NChannel. Nu există niciun tablou [/NChannel ...] în specificație. Dacă ați construit vreodată unul de mână și ați privit un RIP dând din umeri, asta este motivul
HotPDF a greșit asta o dată și apoi a reparat-o, ceea ce merită spus limpede pentru că modelează cum se comportă componenta astăzi. Versiunile mai vechi HotPDF emiteau forma cu nume de familie. THotPDF.RegisterNChannelColorSpace emite acum doar forma standard DeviceN-plus-atribute, și pentru că subtipul NChannel a sosit în PDF 1.6, punctul de intrare al producătorului poartă pe RequirePDFVersion(pdf16, ...) și pur și simplu refuză pe ținte mai vechi. Partea de randare este în mod deliberat mai îngăduitoare decât scriitorul: HPDFResolveColorSpace acceptă încă tokenul legacy /NChannel ca o familie DeviceN, astfel încât fișierele de la vechiul scriitor continuă să se randeze, dar orice scrie HotPDF înapoi folosește codificarea standard. Îngăduitor la intrare, strict la ieșire este asimetria corectă aici, pentru că cititorul dumneavoastră trebuie să se descurce cu fișiere pe care nu le-a creat, în timp ce scriitorul dumneavoastră nu are o asemenea scuză
De ce ajunge un nume de spot pe două plăci?
Pentru că un nume de colorant spot este o identitate de placă la nivel de document, nu un argument local. Două apeluri care ambele numesc Orange dar predau un spațiu alternativ diferit, sau același spațiu alternativ cu o transformare de tentă diferită, descriu două cerneli diferite care se întâmplă să împartă o etichetă. Un RIP care construiește separări nu are cum să le reconcilieze, deci face singurul lucru onest și vă dă două plăci. HotPDF întreține de aceea o semnătură canonică per document pentru fiecare nume de colorant. RegisterSpotColorantDefinition compune acea semnătură din spațiul de culoare alternativ și forma funcției de tentă, și fiecare RegisterSeparation, RegisterSeparationFunc, RegisterSeparationLUT și definiție de spot NChannel trece prin ea. Când o a doua definiție nu este de acord, apelul ridică excepție în loc să înregistreze în tăcere o a doua variantă, iar mesajul este în mod deliberat specific despre modul de eșec, pentru că alternativa este să o descoperiți pe o probă de placă trei săptămâni mai târziu
// Orange era deja înregistrat contra DeviceCMYK cu
// transformarea de tentă 0 / 0.55 / 1 / 0 la tentă maximă.
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;
Împărțirea numelor master în proces și spot
Un NChannel complet trebuie să țină seama de fiecare nume de colorant master exact o dată, fie ca o componentă de proces, fie ca un colorant spot. Overload-ul avansat RegisterNChannelColorSpace ia numele master ColorantNames, ProcessColorantNames, spațiul alternativ, transformarea de tentă globală, un tablou de înregistrări THPDFNChannelSpotColorant și o ordine de tipărire opțională. Fiecare înregistrare de spot poartă propriul nume, propria transformare de tentă Separation cu o singură intrare, o soliditate opțională și o funcție de dot-gain opțională. Transformarea de tentă globală trebuie să mapeze N intrări la numărul de componente al spațiului alternativ; fiecare tentă de spot trebuie să mapeze o intrare la același număr
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);
Din acel apel HotPDF emite dicționarul de atribute pe care specificația îl cere: /Subtype /NChannel, un dicționar /Process al cărui /ColorSpace este spațiul de proces și al cărui /Components listează numele de proces în ordinea componentelor acelui spațiu, un dicționar /Colorants care ține un tablou real [/Separation name alternate tintfn] pentru fiecare spot, și un dicționar /MixingHints care poartă /Solidities, /PrintingOrder și /DotGain când le-ați furnizat. Numele de resursă returnat merge la SetFillColorSpace sau SetStrokeColorSpace exact ca spațiile mai simple tratate în articolul despre randarea culorilor spot Separation și DeviceN
Ce respinge de fapt verificarea de consistență?
Respinge incoerența structurală din interiorul spațiului, și o face înainte să fie scris un singur obiect. Numele de colorant trebuie să fie unice și să nu fie goale, All sau None. Definițiile de proces și de spot împreună trebuie să acopere numele master exact, fără vreun colorant care apare în ambele roluri și fără vreunul rămas nedefinit. Când spațiul alternativ este DeviceCMYK, componentele de proces trebuie să fie Cyan, Magenta, Yellow, Black în ordinea aceea, iar numărul de nume de proces trebuie să se potrivească cu numărul de componente al spațiului alternativ. Fiecare transformare de tentă și funcție de dot-gain trebuie să fie un obiect funcție indirect cu aritatea corectă de intrare și ieșire. Soliditatea trebuie să fie o valoare finită în 0..1. Ordinea de tipărire trebuie să fie goală sau o permutare completă a numelor master, niciodată o listă parțială. Ceea ce nu face este să judece culoarea: nimic aici nu verifică că transformarea dumneavoastră de tentă Orange seamănă de fapt cu cerneala din cutie, că puntea sa CMYK este un proxy sănătos, sau că soliditatea furnizată corespunde comportamentului măsurat pe suport. Acestea sunt întrebări de presă și de măsurare, iar componenta nu are calitatea de a le răspunde. Overload-ul mai simplu, doar-proces, este și mai strict prin design: produce un NChannel doar-proces și refuză în mod deliberat nume de spot, pentru că scrierea unui spot în tabloul de nume fără o intrare /Colorants potrivită ar produce un fișier structural neconform, iar fabricarea unei definiții implicite ar fi mai rău decât eșecul
Output intent-urile PDF/X-6n trebuie să acopere fiecare spot înregistrat
Un fișier PDF/X-6n cu N coloranți își declară coloranții de două ori, iar cele două declarații trebuie să fie de acord. AddPDFX6ExternalOutputIntent scrie referința profilului ICC extern cu ColorantTable-ul său, iar înainte să o facă, ValidateRegisteredSpotOutputColorants parcurge fiecare spot pe care documentul l-a înregistrat și ridică excepție dacă unul lipsește din tabel. Verificarea rulează în ambele direcții: o dată ce un output intent și-a publicat lista de coloranți, o înregistrare ulterioară de spot pentru un nume din afara listei este refuzată la fel. AddPDFX6ExternalOutputIntentSpotData adaugă metadatele per cerneală peste asta, și își impune propriile reguli, în mod notabil că un colorant poartă fie o valoare de soliditate, fie date spectrale CxF/X-4, niciodată ambele. Aceasta este aceeași suprafață de conformitate discutată în piesa despre validarea PDF/A, PDF/X și PDF/UA
Spectral := TMemoryStream.Create;
try
LoadCxFForInk('Orange', Spectral); // încărcătură 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], // soliditate pentru un colorant
Order,
['Orange'], [Spectral]); // date spectrale pentru altul
finally
Spectral.Free;
end;
Două detalii operaționale sunt ușor de ratat. Registrul care susține toate astea este per document și este curățat la granițele de document, astfel încât încărcarea unui fișier nou în aceeași instanță THotPDF nu moștenește identitățile de spot ale documentului anterior; izolarea aceasta este chiar scopul, pentru că o semnătură scursă ar respinge lucrări perfect valide în următoarea lucrare. Iar partea de profil are limite dure ale ei: un output intent extern cere o țintă PDF 2.0, un URL absolut de profil HTTP sau HTTPS, o semnătură de spațiu de culoare ICC de patru octeți, iar pentru PDF/X-6n între 2 și 15 coloranți cu o semnătură potrivită de la 2CLR până la FCLR
Unde se oprește verificarea
Tratarea CxF/X-4 este partea despre care trebuie să fiți sincer. HotPDF aplică verificări structurale de siguranță mărginite fluxului spectral și confirmă că identitatea cernelii din interiorul lui se potrivește cu colorantul pe care l-ați numit. Plafonează dimensiunea încărcăturii, respinge octeți null înglobați, refuză orice flux care conține o declarație DOCTYPE sau ENTITY, cere o rădăcină CxF recognoscibilă și cere exact un element SpotInkCharacterisation care poartă exact un SpotInkName egal cu numele colorantului dumneavoastră. Aceasta este o poartă contra datelor de intrare malformate și ostile, nu un validator de schemă. Nu este o implementare completă ISO 17972-4, nu vă verifică măsurătorile spectrale și nu face audit invers asupra unor grafuri de obiecte terțe preexistente arbitrare sau asupra tabelelor interne de coloranți din interiorul unui profil ICC înglobat. Dacă fluxul dumneavoastră de lucru depinde de conformitate CxF completă, validați fișierul cu un instrument dedicat înainte să-l predați componentei
O constrângere adiacentă mușcă oamenii care nu se așteptau niciodată să o întâlnească. O mască soft de luminozitate nu poate folosi Separation, DeviceN sau NChannel ca /CS al grupului său de transparență; spațiul de amestec al grupului trebuie să fie un spațiu de dispozitiv sau bazat pe CIE, astfel încât vopseaua spot din interiorul grupului este rezolvată prin transformarea sa de tentă în spațiul alternativ înainte să fie calculată luminozitatea. RegisterLuminositySoftMaskState construiește un grup DeviceGray tocmai pentru ca asta să nu poată merge prost din accident. Consecința practică este că un design bogat în spoturi mascat astfel este evaluat prin proxy-ul său CMYK, nu prin cerneala sa, ceea ce contează când îl comparați cu o probă separată, cum este descris în notele despre probatul overprint și dispozitivele de randare
Nimic din toate astea nu elimină nevoia de o probă de placă, dar mută o întreagă clasă de respingeri de prepress din sala de presă înapoi la build. API-urile NChannel, Separation și output intent PDF/X-6n descrise aici vin în HotPDF Delphi Component standard pentru Delphi și C++Builder, unde referința documentează aranjamentele complete de înregistrări și condițiile exacte sub care fiecare apel eșuează închis