Techninis straipsnis

NChannel spotinių dažų nuoseklumas Delphi su HotPDF

Maketo ruošos studija grąžina užsakymą: tas pats spotinis dažas atskirtas į dvi formas. HotPDF to užkerta jau rašymo metu — NChannel įrašo kaip ISO 32000-2 penkialelementę DeviceN formą ir visam dokumentui laiko po vieną kanoninę alternatyvią erdvę bei atspalvio transformaciją kiekvienam spotinio dažo pavadinimui, atmesdamas antrą prieštaraus apibrėžtį užuot ją išdavęs

NChannel nėra spalvų erdvių šeimos pavadinimas

Pirmas dalykas, kurį reikia išmokti iš naujo, yra pats pavadinimas. NChannel nėra spalvų erdvių šeima, kokia yra Separation ir DeviceN. ISO 32000-2 §8.6.6.5 apibūdina jį kaip potipį, tad atitinkanti NChannel erdvė rašoma kaip penkialelementis masyvas [/DeviceN names alternateSpace tintTransform attributes], o atributų žodynas neša /Subtype /NChannel. Specifikacijoje nėra jokio [/NChannel ...] masyvo. Jei kada nors tokį sukonstravote rankomis ir matėte, kaip RIP tik pečiais gūrčiasi, štai kodėl

HotPDF NChannel erdvę rašo kaip penkialelementį DeviceN masyvą, kurio atributų žodynas neša Subtype NChannel kartu su Process, Colorants ir MixingHints įrašais, nes specifikacijoje iš viso nėra NChannel šeimos pavadinimo masyvo
Atitinkanti NChannel erdvė yra DeviceN masyvas su atributų žodynu, todėl rašytojas išduoda tik tokią formą, o skaitytojas vis dar priima senąjį tokeną

HotPDF čia kadaise klydo ir paskui tai sutvarkė, ir verta tai pasakyti tiesiai, nes tai formuoja tai, kaip komponentas elgiasi šiandien. Senesnės HotPDF laidos išdavė šeimos pavadinimo formą. THotPDF.RegisterNChannelColorSpace dabar išduoda tik standartinę DeviceN su atributais formą, o kadangi NChannel potipis atsirado PDF 1.6, gamintojo įėjimo taškas vartais laiko RequirePDFVersion(pdf16, ...) ir ant senesnių taikinių tiesiog atsisako. Atvaizdavimo pusė sąmoningai atlaisesnė už rašytoją: HPDFResolveColorSpace vis dar priima senąjį /NChannel tokeną kaip DeviceN šeimą, tad failai iš seno rašytojo tebeatvaizduojami, bet viskas, ką HotPDF rašo atgal, naudoja standartinį kodavimą. Atliekama įvedime, griežta išvedime — čia tai teisinga asimetrija, nes jūsų skaitytojas turi susidoroti su failais, kurių pats nesukūrė, o jūsų rašytojas tokios atleidimo priežasties neturi

Kodėl vienas spot pavadinimas atsiduria ant dviejų formų?

Nes spotinio dažiklio pavadinimas yra visam dokumentui bendras formos tapatumas, o ne vietinis argumentas. Du iškvietimai, abu įvardijantys Orange, bet perduodantys kitokią alternatyvią erdvę arba tą pačią alternatyvią erdvę su kita atspalvio transformacija, apibūdina du skirtingus dažus, kuriems tiesiog atsitiko ta pati etiketė. RIP, renkantis atskirtis, to sutaikyti negali, tad daro vienintelį sąžiningą dalyką ir duoda jums dvi formas. HotPDF todėl palaiko dokumento masto kanoninį parašą kiekvienam dažiklio pavadinimui. RegisterSpotColorantDefinition tą parašą sudeda iš alternatyvios spalvų erdvės ir atspalvio funkcijos formos, ir per jį eina kiekvienas RegisterSeparation, RegisterSeparationFunc, RegisterSeparationLUT bei NChannel spot apibrėžimas. Kai antra apibrėžtis nesutampa, iškvietimas pakelia išimtį, užuot tyliai užregistruavęs antrą variantą, o pranešimas sąmoningai konkrečiai įvardija žlugimo režimą, nes alternatyva — atrasti tai ant formos patikrinimo po trijų savaičių

Kiekvienas HotPDF spot registracijos iškvietimas praeina pro RegisterSpotColorantDefinition, kuris dokumentui užfiksuoja po vieną kanoninę alternatyvią erdvę ir atspalvio parašą kiekvienam dažiklio pavadinimui ir pakelia išimtį, kai atkeliauja antra, nesutampanti to paties pavadinimo apibrėžtis
Vienas pavadinimas, vienas parašas: antra prieštaraus spot apibrėžtis atmetama rašymo metu, o ne atrandama ant formos patikrinimo
// Orange jau buvo užregistruotas su DeviceCMYK ir atspalvio
// transformacija 0 / 0.55 / 1 / 0 pilnam atspalviui.
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;

Pagrindinių pavadinimų skaidymas į process ir spot

Pilnas NChannel turi apskaityti kiekvieną savo pagrindinį dažiklio pavadinimą lygiai kartą — arba kaip process komponentą, arba kaip spot dažiklį. Išplėstinė RegisterNChannelColorSpace perkrova pima pagrindinius ColorantNames, ProcessColorantNames, alternatyvią erdvę, bendrąją atspalvio transformaciją, THPDFNChannelSpotColorant įrašų masyvą ir pasirinktinę spausdinimo tvarką. Kiekvienas spot įrašas neša savo vardą, savo vieno įėjimo Separation atspalvio transformaciją, pasirinktiną solidity reikšmę ir pasirinktiną taškų prieaugio (dot gain) funkciją. Bendroji atspalvio transformacija turi atvaizduoti N įėjimų į alternatyvios erdvės komponentų skaičių; kiekvieno spot atspalvis turi atvaizduoti vieną įėjimą į tą patį skaičių

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

Iš to iškvietimo HotPDF išduoda specifikacijos reikalaujamą atributų žodyną: /Subtype /NChannel, /Process žodyną, kurio /ColorSpace yra process erdvė, o /Components išvardija process pavadinimus tos erdvės komponentų tvarka, /Colorants žodyną su tikru [/Separation name alternate tintfn] masyvu kiekvienam spot, ir /MixingHints žodyną su /Solidities, /PrintingOrder bei /DotGain, kai juos pateikėte. Grąžintas ištekliaus vardas keliauja į SetFillColorSpace ar SetStrokeColorSpace lygiai taip pat kaip paprastesnės erdvės, aptartos straipsnyje Separation ir DeviceN spot spalvų atvaizdavimas

HotPDF NChannel erdvės pagrindinius dažiklių pavadinimus padalija į Process žodyną keturiems CMYK komponentams ir Colorants žodyną su po vieną Separation masyvą kiekvienam spot, patikrindamas kiekvieną argumentų skaičių prieš rašymą
Kiekvienas pagrindinis pavadinimas užimamas lygiai kartą, o bendroji atspalvio transformacija, atskirų spot atspalviai ir spausdinimo tvarka patikrinami, kol dar neišduotas nė vienas objektas

Ką iš tikrųjų atmeta nuoseklumo patikra?

Ji atmeta struktūrinį nesuderinamumą erdvės viduje ir daro tai, kol dar neįrašytas nė vienas objektas. Dažiklių pavadinimai turi būti unikalūs ir negali būti tušti, All ar None. Process ir spot apibrėžtys kartu turi padengti pagrindinius pavadinimus tiksliai, kad nė vienas dažiklis atsirastų abiejose rolėse ir nė vienas liktų neapibrėžtas. Kai alternatyvi erdvė yra DeviceCMYK, process komponentai turi būti Cyan, Magenta, Yellow, Black būtent tokia tvarka, o process pavadinimų skaičius turi sutapti su alternatyvių komponentų skaičiumi. Kiekviena atspalvio transformacija ir taškų prieaugio funkcija turi būti netiesioginis funkcijos objektas su teisingu įėjimų ir išėjimų skaičiumi. Solidity turi būti baigtinė reikšmė intervale 0..1. Spausdinimo tvarka turi būti tuščia arba pilna pagrindinių pavadinimų permutacija, niekada dalinis sąrašas. Ko ji nedaro — nesprendžia apie spalvą: niekas čia netikrina, ar jūsų Orange atspalvio transformacija iš tikrųjų panaši į dažą skardinėje, ar jos CMYK sudėtis yra protingas pakaitalas, ar jūsų pateikta solidity reikšmė atitinka išmatuotą elgseną ant pagrindo. Tai spaustuvės ir matavimų klausimai, ir komponentas neturi teisės jų atsakyti. Paprastesnė tik process perkrova pagal projektą dar griežtesnė: ji pagamina tik process NChannel ir sąmoningai atsisako priimti spot pavadinimus, nes spot įrašymas į pavadinimų masyvą be atitinkamo /Colorants įrašo pagamintų struktūriškai neatitinkantį failą, o numatytos apibrėžties išgalvojimas būtų blogiau nei žlugimas

PDF/X-6n išvesties ketinimai turi dengti kiekvieną užregistruotą spot

N dažiklių PDF/X-6n failas savo dažiklius deklaruoja du kartus, ir abi deklaracijos turi sutapti. AddPDFX6ExternalOutputIntent rašo išorinės ICC profilės nuorodą su jos ColorantTable, o prieš tai darydamas ValidateRegisteredSpotOutputColorants pereina kiekvieną dokumento užregistruotą spot ir pakelia išimtį, jei kurio iš jų lentelėje nėra. Patikra vyksta abiem kryptimis: kai išvesties ketinimas jau paskelbė savo dažiklių sąrašą, vėlesnė spot registracija pavadinimui už to sąrašo ribų taip pat atmetama. AddPDFX6ExternalOutputIntentSpotData virš to prideda kiekvieno dažo metaduomenis ir taiko savas taisykles, ypač tai, kad dažiklis neša arba solidity reikšmę, arba CxF/X-4 spektrinius duomenis, niekada abu. Tai tas pats atitikties paviršius, aptartas straipsnyje PDF/A, PDF/X ir PDF/UA patikra

Spectral := TMemoryStream.Create;
try
  LoadCxFForInk('Orange', Spectral);   // ISO 17972-4 duomenų turinys
  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 vienam dažikliui
    Order,
    ['Orange'], [Spectral]);           // spektriniai duomenys kitam
finally
  Spectral.Free;
end;

Dvi veiklos detalės lengvai praleidžiamos. Registras, paremtas visa tai, yra dokumento masto ir išvalomas dokumentų ribose, tad naujo failo įkėlimas į tą patį THotPDF egzempliorių nepaveldi ankstesnio dokumento spot tapatumų; izoliacija ir yra esmė, nes išsiliejęs parašas atmestų visiškai teisingą darbą kitame užsakyme. O profilės pusė turi savų kietų ribų: išoriniam išvesties ketinimui reikia PDF 2.0 taikinio, absoliučios HTTP ar HTTPS profilės URL, keturių baitų ICC spalvų erdvės parašo, o PDF/X-6n — nuo 2 iki 15 dažiklių su atitinkamu 2CLR iki FCLR parašu

Kur patikra stoja

CxF/X-4 apdorojimas yra dalis, apie kurią verta būti sąžiningam. HotPDF spektriniam srautui taiko apribotas struktūrinio saugumo patikras ir patvirtina, kad jame esanti dažo tapatybė sutampa su jūsų įvardytu dažikliu. Jis riboja duomenų turinio dydį, atmeta įterptus nulio baitus, atsisako bet kokio srauto su DOCTYPE ar ENTITY deklaracija, reikalauja atpažįstamos CxF šaknies ir reikalauja lygiai vieno SpotInkCharacterisation elemento, nešančio lygiai vieną SpotInkName, lygų jūsų dažiklio pavadinimui. Tai vartai prieš sugadintą ir priešišką įvestį, o ne schemos validatorius. Tai nėra pilna ISO 17972-4 realizacija, ji nepatikrina jūsų spektrinių matavimų ir neatvirkščiai audita savavališkų jau egzistuojančių trečiųjų šalių objektų grafinių struktūrų ar vidinių dažiklių lentelių įterptoje ICC profilėje. Jei jūsų procesas remiasi pilnu CxF atitikimu, patikrinkite failą specialiu įrankiu, prieš perduodamas jį komponentui

Viena gretima sąlyga įkanda tiems, kas nesitikėjo jos sutikti. Šviesio slėptuvės kaukė negali naudoti Separation, DeviceN ar NChannel kaip savo permatomumo grupės /CS; grupės maišymo erdvė turi būti įrenginio ar CIE pagrindo erdvė, tad spot dažai grupės viduje per savo atspalvio transformaciją sutraukiami į alternatyvią erdvę dar prieš skaičiuojant šviesį. RegisterLuminositySoftMaskState sukonstruoja DeviceGray grupę būtent tam, kad to nebūtų galima sugadinti atsitiktinai. Praktinė pasekmė: taip uždengtas spotinių dažų sunkus dizainas vertinamas per savo CMYK pakaitalą, o ne per savo dažą, o tai svarbu, kai lyginate jį su atskirta proba, kaip aprašyta pastabose apie perdangos probas ir atvaizdavimo įrenginius

Nieko iš to nereiškia, kad formos patikrinimo nebeprireiks, bet visa viena maketų ruošos atmetimų klasė keliauja iš spaustuvės atgal į kūrimą. Čia aprašyti NChannel, Separation ir PDF/X-6n išvesties ketinimų API tiekiami standartiniame HotPDF Delphi Component Delphi ir C++Builder aplinkoms, kur dokumentacijoje yra pilni įrašų išdėstymai ir tikslios sąlygos, kuriomis kiekvienas iškvietimas žlunga uždarai