印刷前工程の業者からジョブが差し戻されてきました。同一の特色インキが二つの版に分解されたのです。HotPDFはこれをオーサリング時点で防ぎます。NChannelをISO 32000-2の5要素DeviceN形式として書き、特色名ごとに文書全体で一つの正規の代替カラースペースとティント変換を保持し、二つ目の矛盾する定義は出力せずに拒否します
NChannelはカラースペースファミリーの名前ではない
最初に捨てるべきは名前そのものへの思い込みです。NChannelはSeparationやDeviceNのようなカラースペースファミリーではありません。ISO 32000-2 §8.6.6.5はこれをDeviceNのサブタイプと記述します。つまり適合するNChannelスペースは5要素配列[/DeviceN names alternateSpace tintTransform attributes]として書かれ、attributes辞書が/Subtype /NChannelを運びます。仕様に[/NChannel ...]という配列は存在しません。手で組み立ててRIPに軽くあしらわれた経験があれば、原因はこれです
HotPDFはかつてここを間違え、後に修正しました。率直に述べる価値があるのは、それが今日のコンポーネントの挙動を形作っているからです。旧リリースはファミリー名形式を出力していました。現在のTHotPDF.RegisterNChannelColorSpaceは標準のDeviceN+attributes形式のみを出力し、NChannelサブタイプはPDF 1.6で登場したため、プロデューサー側のエントリポイントはRequirePDFVersion(pdf16, ...)でゲートし、より古いターゲットでは単純に断ります。描画側はライター側より意図的に寛容です。HPDFResolveColorSpaceは旧来の/NChannelトークンをDeviceNファミリーとして今も受け付けるので、旧ライターのファイルも描画し続けますが、HotPDFが書き出すものはすべて標準エンコーディングを使います。入力に寛容、出力に厳格という非対称性はここで正しい選択です。リーダーは自分が生成していないファイルに対処する義務がありますが、ライターにはその言い訳がありません
一つの特色名が二つの版に載ってしまう理由
特色のカララント名は文書全体の版アイデンティティであり、局所的な引数ではないからです。どちらもOrangeと名付けながら異なる代替スペースを渡す二つの呼び出し、あるいは同じ代替スペースに異なるティント変換を渡す二つの呼び出しは、たまたま同じラベルを共有する二つの別個のインキを記述しています。版分解を作るRIPにこれを照合する手段はないため、唯一正直な行動として版を二つ出します。そこでHotPDFはカララント名ごとに文書単位の正規シグネチャを維持します。RegisterSpotColorantDefinitionが代替カラースペースとティント関数の形状からそのシグネチャを組み立て、すべてのRegisterSeparation、RegisterSeparationFunc、RegisterSeparationLUT、NChannel特色定義がこれを通ります。二つ目の定義が食い違うと、呼び出しは第二の変種を黙って登録する代わりに例外を送出し、メッセージは失敗モードについて意図的に具体的です。代替案は3週間後に版校正で発見することだからです
// OrangeはDeviceCMYKに対してティント変換 0 / 0.55 / 1 / 0 を
// 満ティントで登録済み。
Conflicting := Pdf.RegisterExponentialFunction(
Domain1, NoInk, OtherOrangeCMYK, 1, []);
try
Pdf.RegisterSeparationFunc('Orange', 'DeviceCMYK', Conflicting);
except
on E: Exception do
// '特色カララント "Orange" がこの文書で一貫しない代替
// カラースペースまたはティント定義を持っています'
LogPrepressWarning(E.Message);
end;
マスター名をプロセスと特色へ分解する
完全なNChannelは、マスターのカララント名を一つ残らず、プロセス成分か特色カララントのどちらかとしてちょうど一度ずつ勘定に入れなければなりません。高度なRegisterNChannelColorSpaceオーバーロードは、マスターのColorantNames、ProcessColorantNames、代替スペース、全体のティント変換、THPDFNChannelSpotColorantレコードの配列、そしてオプションの印刷順序を受け取ります。各特色レコードは固有の名前、固有の単入力Separationティント変換、オプションのsolidity、オプションのドットゲイン関数を運びます。全体のティント変換はN入力を代替スペースの成分数へ写像しなければならず、各特色のティントは1入力を同じ成分数へ写像しなければなりません
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);
この呼び出しからHotPDFは仕様が求めるattributes辞書を出力します。/Subtype /NChannel、プロセススペースを/ColorSpaceに持ちそのスペースの成分順でプロセス名を列挙する/Componentsを備えた/Process辞書、各特色について実在の[/Separation name alternate tintfn]配列を保持する/Colorants辞書、そして指定した場合は/Solidities、/PrintingOrder、/DotGainを運ぶ/MixingHints辞書です。返されたリソース名は、SeparationとDeviceNの特色カラー描画の記事で扱ったより単純なスペースとまったく同じようにSetFillColorSpaceやSetStrokeColorSpaceへ渡します
一貫性検査は実際に何を拒否するのか
スペース内部の構造的不整合を、一つもオブジェクトを書き出す前に拒否します。カララント名は一意でなければならず、空、All、Noneは禁止です。プロセス定義と特色定義の合計がマスター名を過不足なくカバーし、両方の役割に現れるカララントも、未定義のまま残るカララントも許されません。代替スペースがDeviceCMYKのとき、プロセス成分はCyan、Magenta、Yellow、Blackの順でなければならず、プロセス名数は代替成分数と一致しなければなりません。すべてのティント変換とドットゲイン関数は、正しい入出力アリティを持つ間接関数オブジェクトでなければなりません。solidityは0..1内の有限値でなければなりません。印刷順序は空か、マスター名の完全順列でなければならず、部分リストは不可です。拒否しないのは色そのものです。あなたのOrangeティント変換が缶の中のインキに実のところ似ているか、そのCMYKビルドがまっとうな近似か、指定したsolidityが基材上の実測挙動と一致するかは、ここでは検査しません。それらはプレスと測定の問題であり、コンポーネントが答える立場にありません。プロセスのみのより単純なオーバーロードは設計上さらに厳格です。プロセスのみのNChannelを生成し、特色名を受け取ることを意図的に拒否します。対応する/Colorantsエントリなしに特色をnames配列へ書くと構造的に非適合のファイルになるためであり、既定値の定義を捏造するのは失敗より悪いからです
PDF/X-6nの出力インテントは登録済みの全特色をカバーしなければならない
NカララントのPDF/X-6nファイルはカララントを二回宣言し、二つの宣言は一致しなければなりません。AddPDFX6ExternalOutputIntentはColorantTable付きの外部ICCプロファイル参照を書き出しますが、その前にValidateRegisteredSpotOutputColorantsが文書に登録されたすべての特色を辿り、表に欠けているものがあれば例外を送出します。この検査は双方向で走ります。出力インテントがカララントリストを公開した後、そのリスト外の名前についての後発の特色登録も拒否されます。AddPDFX6ExternalOutputIntentSpotDataはその上にインキごとのメタデータを追加し、独自の規則を強制します。特筆すべきは、カララントがsolidity値かCxF/X-4分光データのどちらか一方のみを運ぶことです。これはPDF/A、PDF/X、PDF/UAの検証の記事で論じたのと同じ適合面です
Spectral := TMemoryStream.Create;
try
LoadCxFForInk('Orange', Spectral); // 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
Order,
['Orange'], [Spectral]); // 別のカララントの分光データ
finally
Spectral.Free;
end;
見落としやすい運用上の細部が二つあります。これらすべてを裏付けるレジストリは文書単位で、文書境界でクリアされるため、同じTHotPDFインスタンスへ新しいファイルを読み込んでも、前の文書の特色アイデンティティは引き継がれません。この分離こそが要点です。漏えいしたシグネチャが次のジョブのまっとうな仕事を拒否することになるからです。そしてプロファイル側にも固有のハードリミットがあります。外部出力インテントはPDF 2.0ターゲット、絶対的なHTTPまたはHTTPSプロファイルURL、4バイトのICCカラースペースシグネチャを要求し、PDF/X-6nでは2〜15のカララントと対応する2CLRからFCLRまでのシグネチャを要求します
検査が止まる場所
正直に語るべきはCxF/X-4の取り扱いです。HotPDFは分光ストリームに有界の構造的安全検査を適用し、内部のインキアイデンティティが名指したカララントと一致することを確認します。ペイロードサイズに上限を設け、埋め込みnullバイトを拒否し、DOCTYPEやENTITY宣言を含むストリームを拒否し、認識可能なCxFルートを要求し、カララント名と一致するSpotInkNameをちょうど一つ運ぶSpotInkCharacterisation要素をちょうど一つ要求します。これは不正かつ敵対的な入力へのゲートであって、スキーマバリデータではありません。完全なISO 17972-4実装ではなく、分光測定を検証もせず、任意の既存サードパーティーオブジェクトグラフや埋め込みICCプロファイル内部のカララント表を逆監査もしません。ワークフローが完全なCxF適合に依存するなら、コンポーネントへ渡す前に専用ツールで検証してください
出会う予定のなかった人を襲う隣接制約があります。輝度ソフトマスクは透明グループの/CSとしてSeparation、DeviceN、NChannelを使えません。グループのブレンドスペースはデバイス依存かCIEベースでなければならず、グループ内の特色ペイントは輝度計算の前にティント変換を通じて代替スペースへ解決されます。RegisterLuminositySoftMaskStateがDeviceGrayグループを構築するのは、まさにこれが偶然に間違わないためです。実務上の帰結として、この方法でマスクされた特色多用のデザインは、インキではなくCMYK近似を通じて評価されます。オーバープリント校正とレンダーデバイスのノートで述べたように、版分解校正と比較するときに問題になる点です
これらのどれも版校正の必要性を消すわけではありませんが、プレプレス拒否のクラス全体をプレス室からビルド工程へ移します。ここで述べたNChannel、Separation、PDF/X-6n出力インテントのAPIは、DelphiとC++Builder向けの標準HotPDF Delphi Componentに同梱され、リファレンスでレコードの完全なレイアウトと各呼び出しが失敗する正確な条件を文書化しています