Teknisk artikkel

NChannel spot-blekk-konsistens i Delphi med HotPDF

Et reprohus sender jobben tilbake: samme spot-blekk separert på to plater. HotPDF forhindrer det ved forfattelsestid ved å skrive NChannel som ISO 32000-2 fem-elements DeviceN-form og ved å holde ett kanonisk alternativt fargerom og én tint-transform per spot-navn for hele dokumentet, og avviser den andre, motstridende definisjonen i stedet for å avgir den

NChannel er ikke et fargerom-familienavn

Det første du må avlære, er selve navnet. NChannel er ikke en fargerom-familie slik Separation og DeviceN er familier. ISO 32000-2 §8.6.6.5 beskriver det som en subtype av DeviceN, så et konformt NChannel-fargerom skrives som fem-elements matrisen [/DeviceN names alternateSpace tintTransform attributes], og attributtordboken bærer /Subtype /NChannel. Det finnes ingen [/NChannel ...]-matrise i spesifikasjonen. Har du noensinne håndbygget én og sett en RIP blunke på den, er det derfor

HotPDF skriver et NChannel-fargerom som fem-elements DeviceN-matrisen hvis attributtordbok bærer Subtype NChannel sammen med Process-, Colorants- og MixingHints-oppføringene, for ingen NChannel-familienavn-matrise finnes i spesifikasjonen i det hele tatt
Et konformt NChannel-fargerom er en DeviceN-matrise med en attributtordbok, noe som er hvorfor skriveren avgir bare denne formen mens leseren fremdeles aksepterer det eldre symbolet

HotPDF fikk dette galt én gang og fikk det så rettet, noe som er verdt å si rett ut fordi det former hvordan komponenten oppfører seg i dag. Eldre HotPDF-utgaver avgir familienavn-formen. THotPDF.RegisterNChannelColorSpace avgir nå bare standard DeviceN-pluss-attributter-formen, og fordi NChannel-subtypen ankom i PDF 1.6, porter produsentinngangspunktet på RequirePDFVersion(pdf16, ...) og sier bare nei på eldre mål. Gjengivelsessiden er med vilje mer tilgivende enn skriveren: HPDFResolveColorSpace aksepterer fremdeles det eldre /NChannel-symbolet som en DeviceN-familie så filer fra den gamle skriveren fortsetter å gjengis, men alt HotPDF skriver tilbake bruker standard koding. Tilgivende på inngang, streng på utgang er den riktige asymmetrien her, for leseren din må takle filer den ikke opprettet mens skriveren din har ingen slik unnskyldning

Hvorfor havner ett spot-navn på to plater?

Fordi et spot-colorant-navn er en dokumentvide plate-identitet, ikke et lokalt argument. To kall som begge navngir Orange men overleverer et annet alternativt fargerom, eller samme alternative fargerom med en annen tint-transform, beskriver to forskjellige blekker som tilfeldigvis deler en etikett. En RIP som bygger separasjoner har ingen måte å forsoning det på, så den gjør den eneste ærlige tingen og gir deg to plater. HotPDF vedlikeholder derfor en per dokument kanonisk signatur per colorant-navn. RegisterSpotColorantDefinition komponerer den signaturen fra det alternative fargerommet og formen på tint-funksjonen, og hver RegisterSeparation, RegisterSeparationFunc, RegisterSeparationLUT og NChannel spot-definisjon passerer gjennom den. Når en andre definisjon er uenig, utløser kallet unntak i stedet for å stille registrere en annen variant, og meldingen er med vilje spesifikk om feilmodusen, for alternativet er å oppdage det på en plateprøv tre uker senere

Hvert HotPDF spot-registreringskall ledes gjennom RegisterSpotColorantDefinition, som registrerer ett kanonisk alternativt fargerom og tint-signatur per colorant-navn for dokumentet og utløser unntak når en andre, uenig definisjon av samme navn ankommer
Ett navn, én signatur: den andre, motstridende definisjonen av en spot nektes ved forfattelsestid snarere enn å bli oppdaget på en plateprøv
// Orange var allerede registrert mot DeviceCMYK med
// tint-transformen 0 / 0.55 / 1 / 0 ved full 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;

Dele hovednavnene i prosess og spot

Et komplett NChannel må stå til regnskap for hvert ett av sine hoved-colorant-navn nøyaktig én gang, som enten en prosesskomponent eller en spot-colorant. Den avanserte RegisterNChannelColorSpace-overlasten tar hoved-ColorantNames, ProcessColorantNames, det alternative fargerommet, den samlede tint-transformen, en matrise av THPDFNChannelSpotColorant-poster, og en valgfri skriveorden. Hver spot-post bærer sitt eget navn, sin egen enkeltinngangs Separation tint-transform, en valgfri soliditet, og en valgfri dot-gain-funksjon. Den samlede tint-transformen må kartlegge N innganger til antall komponenter i alternative fargerom; hver spot-tint må kartlegge én inngang til samme antall

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);

Fra det kallet avgir HotPDF attributtordboken spesifikasjonen ber om: /Subtype /NChannel, en /Process-ordbok hvis /ColorSpace er prosessfargerommet og hvis /Components lister prosessnavnene i den fargerommets komponentorden, en /Colorants-ordbok som holder en ekte [/Separation name alternate tintfn]-matrise for hver spot, og en /MixingHints-ordbok som bærer /Solidities, /PrintingOrder og /DotGain når du leverte dem. Det returnerte ressursnavnet går til SetFillColorSpace eller SetStrokeColorSpace nøyaktig som de enklere fargerommene dekket i artikkelen om Separation- og DeviceN-spot-fargegjengivelse

HotPDF deler hoved-colorant-navnene i et NChannel-fargerom i en Process-ordbok for de fire CMYK-komponentene og en Colorants-ordbok som holder én Separation-matrise per spot, med hver aritet sjekket før skriving
Hvert hovednavn kreves nøyaktig én gang, og den samlede tint-transformen, spot-tintene og skriveordenen valideres alle før noe objekt avgis

Hva avviser konsistenssjekken egentlig?

Den avviser strukturell inkohensjon innen fargerommet, og gjør det før et enkelt objekt er skrevet. Colorant-navn må være unike og må ikke være tomme, All eller None. Prosess- og spot-definisjoner sammen må dekke hovednavnene nøyaktig, uten colorant i begge roller og ingen igjen udefinert. Når det alternative fargerommet er DeviceCMYK, må prosesskomponentene være Cyan, Magenta, Yellow, Black i den orden, og prosessnavnantallet må stemme med alternativ komponentantall. Hver tint-transform og dot-gain-funksjon må være et indirekte funksjonsobjekt med riktig inngangs- og utgangsaritet. Soliditet må være en endelig verdi inne i 0..1. Skriveorden må være tom eller en full permutasjon av hovednavnene, aldri en delvis liste. Det den ikke gjør, er å dømme farge: ingenting her sjekker at din Orange tint-transform faktisk ligner blekken i boksen, at dens CMYK-bygg er en fornuftig proxy, eller at soliditeten du leverte stemmer med målt oppførsel på substratet. Det er presse- og målingsspørsmål, og komponenten har ingen posisjon til å svare dem. Den enklere prosess-only overlasten er strengere fortsatt ved design: den produserer et prosess-only NChannel og nekter villet å akseptere spot-navn, for å skrive en spot inn i navnematriksen uten en matchende /Colorants-oppføring ville produsert en strukturelt ikke-konform fil, og å fabrikere en standarddefinisjon ville være verre enn å feile

PDF/X-6n utgangsintensjoner må dekke hver registrert spot

En N-colorant PDF/X-6n-fil deklarerer sine coloranter to ganger, og de to deklarasjonene må stemme. AddPDFX6ExternalOutputIntent skriver den eksterne ICC-profilreferansen med sin ColorantTable, og før den gjør det, går ValidateRegisteredSpotOutputColorants gjennom hver spot dokumentet har registrert og utløser unntak hvis én mangler i tabellen. Sjekken kjører i begge retninger: når en utgangsintensjon har publisert sin colorantliste, nektes også en senere spot-registrering for et navn utenfor listen. AddPDFX6ExternalOutputIntentSpotData legger per-blekk metadataen oppå det, og håndhever sine egne regler, særlig at en colorant bærer enten en soliditetsverdi eller CxF/X-4 spektraldata, aldri begge. Dette er samme konformitetsflate diskutert 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 colorant
    Order,
    ['Orange'], [Spectral]);           // spektraldata for en annen
finally
  Spectral.Free;
end;

To operasjonelle detaljer er lette å misse. Registeret som bærer alt dette er per dokument og tømmes ved dokumentgrenser, så å laste en ny fil inn i samme THotPDF-instans arver ikke forrige dokument spot-identiteter; den isolasjonen er poenget, siden en lekket signatur ville avvist fullt gyldig arbeid i neste jobb. Og profilsiden har harde grenser av sitt eget: en ekstern utgangsintensjon krever et PDF 2.0-mål, en absolutt HTTP- eller HTTPS-profil-URL, en fire-byte ICC fargerom-signatur, og for PDF/X-6n mellom 2 og 15 coloranter med en matchende 2CLR gjennom FCLR-signatur

Der sjekkingen stopper

CxF/X-4-håndteringen er delen å være ærlig om. HotPDF anvender begrensede strukturelle sikkerhetssjekker på spektralstrømmen og bekrefter at blekk-identiteten inne i den stemmer med coloranten du navnga. Den takler nyttelaststørrelsen, avviser innebygde null-byte, nekter enhver strøm som inneholder en DOCTYPE- eller ENTITY-deklarasjon, krever en gjenkjennelig CxF-rot, og krever nøyaktig ett SpotInkCharacterisation-element som bærer nøyaktig ett SpotInkName som er likt ditt colorant-navn. Det er en port mot feilformet og fiendtlig inndata, ikke en skjemavalidator. Den er ikke en komplett ISO 17972-4-implementasjon, den verifiserer ikke dine spektrale målinger, og den reviderer ikke baklengs vilkårlige forhåndseksisterende tredjeparts objektgrafer eller de interne coloranttabellene inne i en innebygd ICC-profil. Avhenger arbeidsflyten din av full CxF-konformitet, valider filen med et dedikert verktøy før du gir den til komponenten

En tilstøtende begrensning biter folk som aldri ventet å møte den. En luminositets-soft-maske kan ikke bruke Separation, DeviceN eller NChannel som sin transparensgruppe-/CS; gruppens blandingsfargerom må være et enhets- eller CIE-basert fargerom, så spot-maling inne i gruppen løses gjennom sin tint-transform inn i alternative fargerom før luminositet beregnes. RegisterLuminositySoftMaskState bygger en DeviceGray-gruppe presis så dette ikke kan gå galt ved et uhell. Den praktiske konsekvensen er at et spot-tungt design maskert slik evalueres gjennom sin CMYK-proxy, ikke sin blekk, noe som betyr noe når du sammenligner den mot en separert prøv som beskrevet i notatene om overprint-prøving og gjengivelsesenheter

Ingen av dette fjerner behovet for en plateprøv, men det flytter en hel klasse av repro-avvisninger fra presserommet tilbake til bygget. NChannel-, Separation- og PDF/X-6n utgangsintensjon-API-ene beskrevet her leveres i standard HotPDF Delphi Component for Delphi og C++Builder, der referansen dokumenterer de fullstendige postoppsettene og de nøyaktige betingelsene under hvilke hvert kall feiler lukket