Tehnički članak

NChannel doslednost spot boje u Delphi-ju uz HotPDF

Prepress kuća vraća posao: ista spot boja separirana na dve ploče. HotPDF to sprečava u trenutku autorstva pišući NChannel kao ISO 32000-2 DeviceN oblik sa pet elemenata i držeći jedan kanonski alternativni prostor i tint transformaciju po spot imenu za ceo dokument, odbijajući drugu, protivrečeću definiciju umesto da je ispiše

NChannel nije ime familije prostora boja

Prvo što treba zaboraviti je samo ime. NChannel nije familija prostora boja na način na koji su Separation i DeviceN familije. ISO 32000-2 §8.6.6.5 opisuje ga kao podtip DeviceN-a, pa usklađen NChannel prostor piše se kao peteročlani niz [/DeviceN names alternateSpace tintTransform attributes], a rečnik atributa nosi /Subtype /NChannel. Ne postoji [/NChannel ...] niz u specifikaciji. Ako ste ga ikad ručno izgradili i gledali kako RIP slegne ramenima na njega, zato

HotPDF piše NChannel prostor kao peteročlani DeviceN niz čiji rečnik atributa nosi Subtype NChannel zajedno sa Process, Colorants i MixingHints unosima, jer NChannel familija-imeni niz uopšte ne postoji u specifikaciji
Usklađen NChannel prostor je DeviceN niz sa rečnikom atributa, pa ispisivač ispisuje samo ovaj oblik dok čitač i dalje prima zastareli token

HotPDF je ovo jednom pogrešio pa ispravio, i vredi to reći jasno jer oblikuje kako se komponenta danas ponaša. Starija HotPDF izdanja ispisivala su familija-imeni oblik. THotPDF.RegisterNChannelColorSpace sada ispisuje samo standardni DeviceN-plus-atributi oblik, i pošto je NChannel podtip stigao u PDF 1.6, proizvodna ulazna tačka kapijuje na RequirePDFVersion(pdf16, ...) i jednostavno odbija na starijim ciljevima. Render strana namerno je popustljivija od pisca: HPDFResolveColorSpace i dalje prima zastareli /NChannel token kao DeviceN familiju da bi fajlovi sa starog pisca i dalje renderovali, ali sve što HotPDF ispisuje nazad koristi standardno kodiranje. Popustljivo na ulazu, strog na izlazu je prava asimetrija ovde, jer vaš čitač mora da se snađe sa fajlovima koje nije stvorio dok vaš pisac nema takvo opravdanje

Zašto jedno spot ime završi na dve ploče?

Jer je spot ime boje identitet ploče na nivou dokumenta, ne lokalni argument. Dva poziva koji oba imenuju Orange ali predaju drugačiji alternativni prostor, ili isti alternativni prostor sa drugačijom tint transformacijom, opisuju dve različite boje koje slučajno dele oznaku. RIP koji gradi separacije nema načina da to izmiri, pa čini jedino pošteno i daje vam dve ploče. HotPDF zato održava po dokumentu kanonski potpis po imenu boje. RegisterSpotColorantDefinition sastavlja taj potpis iz alternativnog prostora boja i oblika tint funkcije, i svaki RegisterSeparation, RegisterSeparationFunc, RegisterSeparationLUT i NChannel spot definicija prolazi kroz njega. Kada se druga definicija ne slaže, poziv baca izuzetak umesto da tiho registruje drugu varijantu, i poruka je namerno specifična o načinu pada, jer je alternativa otkriti to na pločnom dokazu tri nedelje kasnije

Svaki HotPDF spot registracioni poziv čvorno prolazi kroz RegisterSpotColorantDefinition, koji beleži jedan kanonski alternativni prostor i tint potpis po imenu boje za dokument i baca kada stigne druga, neslagajuća definicija istog imena
Jedno ime, jedan potpis: druga, protivrečeća definicija spota odbija se u trenutku autorstva umesto da se otkrije na pločnom dokazu
// Orange je već registrovan protiv DeviceCMYK sa tint
// transformacijom 0 / 0.55 / 1 / 0 pri punoj tinti.
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;

Razdvajanje glavnih imena na process i spot

Kompletan NChannel mora da obuhvati svako svoje glavno ime boje tačno jednom, kao process komponentu ili kao spot boju. Napredni RegisterNChannelColorSpace overload prima glavne ColorantNames, ProcessColorantNames, alternativni prostor, ukupnu tint transformaciju, niz THPDFNChannelSpotColorant zapisa i opcionu štamparsku redoslednost. Svaki spot zapis nosi sopstveno ime, sopstvenu jednoulanu Separation tint transformaciju, opcionu solidity i opcionu dot-gain funkciju. Ukupna tint transformacija mora mapirati N ulaza na broj komponenti alternativnog prostora; svaka spot tinta mora mapirati jedan ulaz na isti taj broj

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

Iz tog poziva HotPDF ispisuje rečnik atributa koji specifikacija traži: /Subtype /NChannel, /Process rečnik čiji je /ColorSpace process prostor a čiji /Components navodi process imena u tom redu komponenata prostora, /Colorants rečnik koji drži pravi [/Separation name alternate tintfn] niz za svaki spot, i /MixingHints rečnik koji nosi /Solidities, /PrintingOrder i /DotGain kada ste ih dali. Vraćeno ime resursa ide u SetFillColorSpace ili SetStrokeColorSpace tačno kao jednostavniji prostori pokriveni u članku o Separation i DeviceN spot renderovanju boja

HotPDF razdvaja glavna imena boja NChannel prostora u Process rečnik za četiri CMYK komponente i Colorants rečnik koji drži jedan Separation niz po spotu, uz svaku proveru arnosti pre pisanja
Svako glavno ime preuzeto je tačno jednom, a ukupna tint transformacija, tinte po spotu i štamparski redosled svi se validiraju pre nego što bilo koji objekat izađe

Šta provera doslednosti zaista odbija?

Odbija strukturnu nekogerentnost unutar prostora, i to pre nego što jedan jedini objekat bude napisan. Imena boja moraju biti jedinstvena i ne smeju biti prazna, All ili None. Process i spot definicije zajedno moraju pokriti glavna imena tačno, bez boje koja se pojavljuje u obe uloge i bez nijedne nedefinisane. Kada je alternativni prostor DeviceCMYK, process komponente moraju biti Cyan, Magenta, Yellow, Black tim redom, i broj process imena mora poklapati broj komponenti alternativnog prostora. Svaka tint transformacija i dot-gain funkcija moraju biti indirektni objekti funkcije sa pravom ulaznom i izlaznom arnošću. Solidity mora biti konačna vrednost unutar 0..1. Štamparski redosled mora biti prazan ili puna permutacija glavnih imena, nikad delimična lista. Ono što ne čini je prosuđivanje boje: ništa ovde ne proverava da vaša Orange tint transformacija zaista liči na boju u kanti, da je njena CMYK izgradnja pametan zamenik, ili da se solidity koji ste dali poklapa sa izmerenim ponašanjem na podlozi. To su pitanja štamparske mašine i merenja, i komponenta nema mandat da na njih odgovori. Jednostavniji process-only overload strogiji je po dizajnu: proizvodi process-only NChannel i namerno odbija da primi spot imena, jer bi pisanje spota u niz imena bez odgovarajućeg /Colorants unosa proizvelo strukturno neusklađen fajl, a izmišljanje podrazumevane definicije bilo bi gore od pada

PDF/X-6n output intenti moraju pokriti svaki registrovani spot

N-bojni PDF/X-6n fajl deklariše svoje boje dvaput, i dve deklaracije se moraju slagati. AddPDFX6ExternalOutputIntent piše eksternu ICC referencu profila sa svojim ColorantTable, a pre nego što to učini, ValidateRegisteredSpotOutputColorants prelazi svaki spot koji je dokument registrovao i baca ako ijedan nedostaje u tabeli. Provera ide u oba smera: jednom kada je output intent objavio svoju listu boja, kasnija spot registracija za ime van te liste takođe se odbija. AddPDFX6ExternalOutputIntentSpotData dodaje metapodatke po boji na to, i sprovodi svoja pravila, posebno da boja nosi ili solidity vrednost ili CxF/X-4 spektralne podatke, nikad oba. To je ista površina usklađenosti razmatrana u tekstu o PDF/A, PDF/X i PDF/UA validaciji

Spectral := TMemoryStream.Create;
try
  LoadCxFForInk('Orange', Spectral);   // ISO 17972-4 sadržaj
  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 za jednu boju
    Order,
    ['Orange'], [Spectral]);           // spektralni podaci za drugu
finally
  Spectral.Free;
end;

Dva operativna detalja lako se previdi. Registar koji stoji iza svega ovoga po dokumentu je i briše se na granicama dokumenta, pa učitavanje novog fajla u istu THotPDF instancu ne nasleđuje spot identitete prethodnog dokumenta; ta izolacija je poenta, jer bi procureli potpis odbio sasvim ispravan rad u sledećem poslu. I strana profila ima krute limite: eksterni output intent zahteva PDF 2.0 cilj, apsolutni HTTP ili HTTPS URL profila, četvorobajtni ICC signature prostora boja, i za PDF/X-6n između 2 i 15 boja sa odgovarajućim 2CLR do FCLR signature-om

Gde provera staje

CxF/X-4 rukovanje je deo oko kog treba biti iskren. HotPDF primenjuje ograničene strukturne bezbednosne provere na spektralni tok i potvrđuje da se identitet boje unutra poklapa sa bojom koju ste imenovali. Ograničava veličinu sadržaja, odbija ugrađene null bajtove, odbija svaki tok koji sadrži DOCTYPE ili ENTITY deklaraciju, zahteva prepoznatljiv CxF koren, i zahteva tačno jedan SpotInkCharacterisation element koji nosi tačno jedan SpotInkName jednak vašem imenu boje. To je kapija protiv deformisanog i neprijateljskog ulaza, ne schema validator. Nije kompletna ISO 17972-4 implementacija, ne proverava vaša spektralna merenja, i ne audituje unazad proizvoljne postojeće grafove objekata trećih strana ni unutrašnje tabele boja unutar ugrađenog ICC profila. Ako vaš tok rada zavisi od potpune CxF usklađenosti, proverite fajl namenskim alatom pre nego što ga predate komponenti

Jedno susedno ograničenje ujeda ljude koji nikad nisu očekivali da ga sretnu. Luminosity soft mask ne može koristiti Separation, DeviceN ili NChannel kao svoj transparency group /CS; blending prostor grupe mora biti device ili CIE-baziran prostor, pa se spot boja unutar grupe razrešava kroz svoju tint transformaciju u alternativni prostor pre nego što se luminositet izračuna. RegisterLuminositySoftMaskState gradi DeviceGray grupu upravo da ovo ne može poći naopako slučajno. Praktična posledica je da se dizajn bogat spotovima maskiran ovako procenjuje kroz svoj CMYK zamenik, a ne kroz svoju boju, što je bitno kada ga poredite sa separiranim dokazom kao što opisuju beleške o overprint dokazivanju i render uređajima

Ništa od ovoga ne uklanja potrebu za pločnim dokazom, ali celu jednu klasu prepress odbijanja premešta iz štamparske sobe nazad u build. NChannel, Separation i PDF/X-6n output intent API-ji opisani ovde stižu uz standardnu HotPDF Delphi Component za Delphi i C++Builder, gde referenca dokumentuje kompletne rasporede zapisa i tačne uslove pod kojima svaki poziv pada zatvoren