Odborný článok

Konzistencia spot farieb NChannel v Delphi s HotPDF

Prípravňa tlačiarne posiela prácu späť: tá istá spot farba separovaná na dve dosky. HotPDF tomu bráni už pri autorovaní tak, že píše NChannel ako päťprvkovú formu DeviceN podľa ISO 32000-2 a drží jeden kanonický alternatívny priestor a tint transform na meno spotu pre celý dokument, pričom druhú, konfliktnú definíciu zamietne namiesto jej vysypania

NChannel nie je názov rodiny farebných priestorov

Prvá vec, ktorú treba najprv zabudnúť, je samotné meno. NChannel nie je rodina farebných priestorov tak, ako sú rodinami Separation a DeviceN. ISO 32000-2 §8.6.6.5 ho opisuje ako subtype DeviceN, takže zlučiteľný priestor NChannel sa píše ako päťprvkové pole [/DeviceN names alternateSpace tintTransform attributes] a slovník attributes nesie /Subtype /NChannel. V špecifikácii neexistuje žiadne pole [/NChannel ...]. Ak ste si niečo také kedysi postavili ručne a sledovali, ako nad tím RIP pokrčí plecami, presne preto to je

HotPDF zapisuje priestor NChannel ako päťprvkové pole DeviceN, ktorého slovník attributes nesie Subtype NChannel spolu s položkami Process, Colorants a MixingHints, lebo žiadne pole s názvom rodiny NChannel v špecifikácii vôbec neexistuje
Zlučiteľný priestor NChannel je pole DeviceN so slovníkom attributes, preto pisateľ vysypáva len túto formu, kým čítač stále prijíma legacy token

HotPDF sa v tom raz pomýlil a potom to opravil, čo stojí za povedanie nahlas, lebo formuje, ako sa komponent dnes správa. Staršie vydania HotPDF vysypali formu názvu rodiny. THotPDF.RegisterNChannelColorSpace teraz vysypáva len štandardnú formu DeviceN-plus-attributes a keďže subtype NChannel prišiel v PDF 1.6, vstupný bod producenta bráni cez RequirePDFVersion(pdf16, ...) a na starších cieľoch jednoducho odmieta. Renderovacia strana je zámerne zhovievavejšia než pisateľ: HPDFResolveColorSpace stále prijíma legacy token /NChannel ako rodinu DeviceN, takže súbory zo starého pisateľa sa vykresľujú ďalej, ale čokoľvek, čo HotPDF zapíše späť, používa štandardné kódovanie. Zhovievavé na vstupe, prísne na výstupe je tu správna asymetria, lebo váš čítač sa musí vyrovnať so súbormi, ktoré nevytvoril, zatiaľ čo váš pisateľ takú výhovorku nemá

Prečo skončí jedno meno spotu na dvoch doskách?

Pretože meno spot farbiva je identita dosky na úrovni celého dokumentu, nie miestny argument. Dve volania, ktoré obe menujú Orange, ale podajú iný alternatívny priestor, alebo ten istý alternatívny priestor s iným tint transform, opisujú dve rôzne farby, ktoré sa náhodou delia o štítok. RIP staviajúci separácie nemá ako to zmieriť, takže urobí jedinú úprimnú vec a dá vám dve dosky. HotPDF preto udržuje podpis pre každé meno farbiva na úrovni dokumentu. RegisterSpotColorantDefinition skladá ten podpis z alternatívneho farebného priestoru a tvaru funkcie tónu a každý RegisterSeparation, RegisterSeparationFunc, RegisterSeparationLUT a NChannel definícia spotu cez neho prechádza. Keď druhá definícia nesúhlasí, volanie vyvolá výnimku namiesto potichu registrácie druhej varianty a hlásenie je zámerne špecifické k režimu zlyhania, lebo alternatíva je objaviť to na doskovom prevode o tri týždne neskôr

Každé registračné volanie spotu HotPDF sa lievikuje cez RegisterSpotColorantDefinition, ktoré zaznamenáva jeden kanonický alternatívny priestor a podpis tónu na meno farbiva pre dokument a vyvolá výnimku, keď príde druhá, nesúhlasiaca definícia toho istého mena
Jedno meno, jeden podpis: druhá, konfliktná definícia spotu sa zamietne pri autorovaní namiesto toho, aby sa objavila na doskovom prevode
// Orange už bol zaregistrovaný proti DeviceCMYK s tint
// transformom 0 / 0.55 / 1 / 0 pri plnom tóne.
Conflicting := Pdf.RegisterExponentialFunction(
  Domain1, NoInk, OtherOrangeCMYK, 1, []);
try
  Pdf.RegisterSeparationFunc('Orange', 'DeviceCMYK', Conflicting);
except
  on E: Exception do
    // 'Spot farbivo „Orange" má v tomto dokumente nekonzistentný
    //  alternatívny farebný priestor alebo definíciu tónu'
    LogPrepressWarning(E.Message);
end;

Rozdelenie master mien na process a spot

Úplný NChannel musí zohľadniť každé jedno zo svojich master mien farbív presne raz, buď ako process komponent, alebo ako spot farbivo. Rozšírený overload RegisterNChannelColorSpace berie master ColorantNames, ProcessColorantNames, alternatívny priestor, celkový tint transform, pole záznamov THPDFNChannelSpotColorant a voliteľné poradie tlače. Každý záznam spotu nesie vlastné meno, vlastný tint transform Separation s jedným vstupom, voliteľnú soliditu a voliteľnú funkciu dot-gain. Celkový tint transform musí mapovať N vstupov na počet komponentov alternatívneho priestoru; každý tón spotu musí mapovať jeden vstup na ten istý 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 toho volania vysypie HotPDF slovník attributes, ktorý špecifikácia žiada: /Subtype /NChannel, slovník /Process, ktorého /ColorSpace je process priestor a ktorého /Components vymenúva process mená v poradí komponentov toho priestoru, slovník /Colorants držiaci reálne pole [/Separation name alternate tintfn] pre každý spot a slovník /MixingHints nesúci /Solidities, /PrintingOrder a /DotGain, keď ste ich dodali. Vrátené meno zdroja ide do SetFillColorSpace alebo SetStrokeColorSpace presne ako jednoduchšie priestory pokryté v článku o vykresľovaní spot farieb Separation a DeviceN

HotPDF rozdeľuje master mená farbív priestoru NChannel do slovníka Process pre štyri komponenty CMYK a slovníka Colorants držiaceho jedno pole Separation na spot, s kontrolou arity skôr, než sa čokoľvek zapíše
Každé master meno je nárokované presne raz a celkový tint transform, tóny jednotlivých spotov aj poradie tlače sa validujú skôr, než sa vysypie akýkoľvek objekt

Čo kontrola konzistencie vlastne zamieta?

Zamietne štrukturálnu nekoherenciu vnútri priestoru a robí to skôr, než sa napíše jediný objekt. Mená farbív musia byť unikátne a nesmú byť prázdne, All ani None. Process a spot definície spolu musia pokryť master mená presne, bez farbiva objavujúceho sa v oboch úlohách a bez ponechaného nedefinovaného. Keď je alternatívnym priestorom DeviceCMYK, process komponenty musia byť Cyan, Magenta, Yellow, Black v tomto poradí a počet process mien musí sedieť s počtom komponentov alternatívy. Každý tint transform a dot-gain funkcia musí byť nepriamy funkčný objekt so správnou aritou vstupu a výstupu. Solidita musí byť konečná hodnota vnútri 0..1. Poradie tlače musí byť prázdne alebo úplná permutácia master mien, nikdy čiastočný zoznam. Čo nerobí, je súdenie farby: nič tu nekontroluje, že váš tint transform Orange vôbec pripomína farbu v vedre, že jeho CMYK zostavenie je rozumný proxy alebo že dodaná solida sedí s nameraným správaním na substrate. To sú otázky tlače a merania a komponent nemá mandát ich riešiť. Jednoduchší process-only overload je navrhovo ešte prísnejší: produkuje process-only NChannel a zámerne odmieta prijať mená spotov, lebo zápis spotu do poľa mien bez zodpovedajúcej položky /Colorants by vyrobil štrukturálne nezlučiteľný súbor a fabrikovanie predvolenej definície by bolo horšie než zlyhanie

Output intenty PDF/X-6n musia pokryť každý zaregistrovaný spot

Súbor PDF/X-6n s N farbivami vyhlasuje svoje farbivá dvakrát a obe vyhlásenia musia sedieť. AddPDFX6ExternalOutputIntent zapisuje referenciu externého ICC profilu so svojou ColorantTable a skôr než to urobí, ValidateRegisteredSpotOutputColorants prejde každý spot, ktorý dokument zaregistroval, a vyvolá výnimku, keď niektorý z tabuľky chýba. Kontrola beží oboma smermi: keď output intent raz publikoval zoznam farbív, neskoršia registrácia spotu pre meno mimo tohto zoznamu sa tiež zamietne. AddPDFX6ExternalOutputIntentSpotData pridáva na to metadata pre jednotlivé farby a vynucuje vlastné pravidlá, význačne to, že farbivo nesie buď hodnotu solidity, alebo spektrálne dáta CxF/X-4, nikdy oboje. To je ten istý povrch súladu rozobraný v článku o validácii PDF/A, PDF/X a PDF/UA

Spectral := TMemoryStream.Create;
try
  LoadCxFForInk('Orange', Spectral);   // dátový obsah 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],                  // solidity pre jedno farbivo
    Order,
    ['Orange'], [Spectral]);           // spektrálne dáta pre iné
finally
  Spectral.Free;
end;

Dva prevádzkové detaily sa ľahko prehliadnú. Registr, ktorý toto všetko nesie, je na dokument a čistí sa na hraniciach dokumentov, takže načítanie nového súboru do tej istej inštancie THotPDF nededia identity spotov predchádzajúceho dokumentu; tá izolácia je pointa, lebo uniknutý podpis by zamietol úplne platnú prácu v ďalšej úlohe. A profilová strana má vlastné tvrdé limity: externý output intent vyžaduje cieľ PDF 2.0, absolútne URL profilu HTTP alebo HTTPS, štvorbajtový podpis farebného priestoru ICC a pre PDF/X-6n medzi 2 a 15 farbivami so zodpovedajúcim podpisom 2CLR až FCLR

Kde kontrola končí

Obsluha CxF/X-4 je časť, ku ktorej treba byť úprimný. HotPDF aplikuje ohraničené štrukturálne bezpečnostné kontroly na spektrálny stream a potvrdí, že identita farby vo vnútri sedí s farbivom, ktoré ste pomenovali. Stropuje veľkosť obsahu, zamieta vložené nulové bajty, odmieta každý stream obsahujúci deklaráciu DOCTYPE alebo ENTITY, vyžaduje rozoznateľný koreň CxF a vyžaduje presne jeden element SpotInkCharacterisation nesúci presne jedno SpotInkName rovné vášmu menu farbiva. To je brána proti znetvorenému a nepriateľskému vstupu, nie validátor schémy. Nie je to úplná implementácia ISO 17972-4, neoveruje vaše spektrálne merania a nerobí spätný audit ľubovoľných vopred existujúcich grafov objektov tretích strán ani interných tabuliek farbív vo vnútri vloženého ICC profilu. Ak váš workflow závisí od úplného súladu CxF, validujte súbor dedikovaným nástrojom skôr, než ho podáte komponentu

Jedno susedné obmedzenie hrýze ľudí, ktorí nikdy nečakali, že sa s ním stretnú. Mäkká maska luminancie nemôže použiť Separation, DeviceN ani NChannel ako svoju skupinu priehľadnosti /CS; zlučovací priestor skupiny musí byť priestor zariadenia alebo založený na CIE, takže spotová farba vo vnútri skupiny sa vyrieši cez jej tint transform do alternatívneho priestoru skôr, než sa vypočíta luminancia. RegisterLuminositySoftMaskState stavia skupinu DeviceGray presne preto, aby to nemohlo zlyhať náhodou. Praktický dôsledok je, že dizajn ťažký na spoty maskovaný týmto spôsobom sa vyhodnocuje cez svoj CMYK proxy, nie cez svoju farbu, čo záleží, keď ho porovnávate s doskovým prevodom popísaným v poznámkach o overprint prevodoch a renderovacích zariadeniach

Žiadne z tohto neodstraňuje potrebu doskového prevodu, ale presúva celú triedu zamietnutí prípravne z tlačiarne späť do buildu. API NChannel, Separation a output intentov PDF/X-6n popísané tu dodáva štandardný HotPDF Delphi Component pre Delphi a C++Builder, kde referencia dokumentuje kompletné rozloženia záznamov a presné podmienky, pri ktorých každé volanie zlyhá bezpečne