Một xưởng in tiền ấn gửi trả công việc: cùng một mực spot bị tách ra hai bản in riêng. HotPDF ngăn điều đó ngay lúc soạn thảo bằng cách ghi NChannel theo dạng DeviceN năm phần tử của ISO 32000-2 và giữ một không gian thay thế cùng tint transform chính tắc cho mỗi tên spot trên toàn tài liệu, từ chối định nghĩa thứ hai xung đột thay vì phát hành nó
NChannel không phải một tên họ không gian màu
Điều đầu tiên cần gỡ bỏ khỏi đầu là chính cái tên đó. NChannel không phải một họ không gian màu như Separation và DeviceN là các họ. ISO 32000-2 §8.6.6.5 mô tả nó là một subtype của DeviceN, nên một không gian NChannel đạt chuẩn được viết thành mảng năm phần tử [/DeviceN names alternateSpace tintTransform attributes], và dictionary attributes mang /Subtype /NChannel. Không hề có mảng [/NChannel ...] nào trong đặc tả. Nếu bạn từng tự tay dựng một cái và thấy RIP nhún vai, thì đó là lý do
HotPDF từng sai chỗ này rồi sửa lại, và điều đó đáng nói thẳng vì nó định hình cách component vận hành hôm nay. Các bản HotPDF cũ phát hành dạng tên họ. THotPDF.RegisterNChannelColorSpace giờ chỉ phát hành dạng chuẩn DeviceN kèm attributes, và vì subtype NChannel xuất hiện từ PDF 1.6, entry point phía producer kiểm soát bằng RequirePDFVersion(pdf16, ...) và đơn giản là từ chối trên mục tiêu cũ hơn. Phía render cố tình khoan dung hơn writer: HPDFResolveColorSpace vẫn chấp nhận token cũ /NChannel như một họ DeviceN để các tệp từ writer cũ tiếp tục render được, nhưng bất cứ thứ gì HotPDF ghi lại ra ngoài đều dùng mã hoá chuẩn. Khoan dung khi đọc, nghiêm ngặt khi ghi là bất đối xứng đúng đắn ở đây, vì reader của bạn phải chịu đựng các tệp nó không sinh ra còn writer của bạn thì không có cớ nào như thế
Vì sao một tên spot lại nằm trên hai bản in?
Vì một tên colorant spot là danh tính bản in trên toàn tài liệu, không phải tham số cục bộ. Hai lời gọi đều nhắc tới Orange nhưng đưa vào một không gian thay thế khác, hoặc cùng không gian thay thế với một tint transform khác, mô tả hai mực khác nhau tình cờ dùng chung một nhãn. Một RIP dựng bản tách không có cách nào hoà giải điều đó, nên nó làm việc duy nhất hợp lý và trao cho bạn hai bản in. HotPDF vì thế duy trì một chữ ký chính tắc theo từng tên colorant cho mỗi tài liệu. RegisterSpotColorantDefinition dựng chữ ký đó từ không gian màu thay thế và hình dạng của hàm tint, và mọi RegisterSeparation, RegisterSeparationFunc, RegisterSeparationLUT, cùng định nghĩa spot NChannel đều đi qua nó. Khi một định nghĩa thứ hai bất đồng, lời gọi raise thay vì lặng lẽ đăng ký thêm một biến thể, và thông điệp cố tình nói cụ thể về kiểu lỗi, vì lựa chọn còn lại là phát hiện ra nó trên bản in thử ba tuần sau
// Orange đã được đăng ký với DeviceCMYK và
// tint transform 0 / 0.55 / 1 / 0 ở tint đầy đủ.
Conflicting := Pdf.RegisterExponentialFunction(
Domain1, NoInk, OtherOrangeCMYK, 1, []);
try
Pdf.RegisterSeparationFunc('Orange', 'DeviceCMYK', Conflicting);
except
on E: Exception do
// 'Spot colourant "Orange" có không gian màu thay thế
// hoặc định nghĩa tint không nhất quán trong tài liệu này'
LogPrepressWarning(E.Message);
end;
Tách các tên master thành process và spot
Một NChannel hoàn chỉnh phải giải thích cho từng tên colorant master của nó đúng một lần, hoặc là một thành phần process hoặc là một colorant spot. Overload nâng cao RegisterNChannelColorSpace nhận ColorantNames master, ProcessColorantNames, không gian thay thế, tint transform tổng thể, một mảng record THPDFNChannelSpotColorant, và một thứ tự in tuỳ chọn. Mỗi record spot mang tên riêng của nó, tint transform Separation một đầu vào riêng, một solidity tuỳ chọn, và một hàm dot-gain tuỳ chọn. Tint transform tổng thể phải map N đầu vào ra số thành phần của không gian thay thế; mỗi tint spot phải map một đầu vào ra đúng số đó
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);
Từ lời gọi đó HotPDF phát hành dictionary attributes mà đặc tả yêu cầu: /Subtype /NChannel, một dictionary /Process mà /ColorSpace của nó là không gian process và /Components liệt kê các tên process theo đúng thứ tự thành phần của không gian đó, một dictionary /Colorants giữ một mảng [/Separation name alternate tintfn] thật cho từng spot, và một dictionary /MixingHints mang /Solidities, /PrintingOrder, và /DotGain khi bạn cung cấp. Tên tài nguyên trả về được đưa cho SetFillColorSpace hoặc SetStrokeColorSpace y hệt các không gian đơn giản hơn được trình bày trong bài về render màu spot Separation và DeviceN
Kiểm tra nhất quán thực sự từ chối những gì?
Nó từ chối sự thiếu nhất quán cấu trúc bên trong không gian, và làm điều đó trước khi bất cứ object nào được ghi. Tên colorant phải duy nhất và không được rỗng, không được là All hay None. Định nghĩa process và spot cộng lại phải phủ đúng các tên master, không colorant nào xuất hiện ở cả hai vai trò và không tên nào bỏ ngỏ. Khi không gian thay thế là DeviceCMYK, các thành phần process phải là Cyan, Magenta, Yellow, Black đúng thứ tự đó, và số tên process phải khớp số thành phần của không gian thay thế. Mọi tint transform và hàm dot-gain phải là object hàm indirect với arity đầu vào và đầu ra đúng. Solidity phải là một giá trị hữu hạn trong 0..1. Thứ tự in phải rỗng hoặc là một hoán vị đầy đủ của các tên master, tuyệt đối không phải danh sách một phần. Điều nó không làm là phán xét màu: chẳng có gì ở đây kiểm tra rằng tint transform Orange của bạn thực sự giống mực trong can, rằng công thức CMYK của nó là một proxy hợp lý, hay rằng solidity bạn cung cấp khớp hành vi đo đạc được trên bề mặt in. Đó là những câu hỏi của máy in và phép đo, và component không có tư cách trả lời chúng. Overload đơn giản hơn chỉ-process còn nghiêm ngặt hơn nữa do chủ đích thiết kế: nó sinh ra một NChannel chỉ-process và cố tình từ chối nhận tên spot, vì việc ghi một spot vào mảng names mà không có entry /Colorants tương ứng sẽ sinh ra một tệp không đạt chuẩn cấu trúc, và bịa ra một định nghĩa mặc định còn tệ hơn cả thất bại
Output intent PDF/X-6n phải phủ mọi spot đã đăng ký
Một tệp PDF/X-6n N-colorant khai báo colorant của nó hai lần, và hai lời khai báo phải khớp nhau. AddPDFX6ExternalOutputIntent ghi tham chiếu profile ICC ngoài cùng ColorantTable của nó, và trước khi làm vậy, ValidateRegisteredSpotOutputColorants đi qua mọi spot tài liệu đã đăng ký và raise nếu có một cái vắng mặt trong bảng. Phép kiểm tra chạy theo cả hai chiều: một khi output intent đã công bố danh sách colorant, một lời đăng ký spot sau đó cho một tên ngoài danh sách cũng bị từ chối. AddPDFX6ExternalOutputIntentSpotData thêm metadata theo từng mực lên trên, và nó thi hành các luật riêng, đáng chú ý là một colorant chỉ được mang giá trị solidity hoặc dữ liệu quang phổ CxF/X-4, không bao giờ cả hai. Đây là cùng một bề mặt tuân thủ được bàn trong bài về xác thực PDF/A, PDF/X và PDF/UA
Spectral := TMemoryStream.Create;
try
LoadCxFForInk('Orange', Spectral); // payload 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 cho một colorant
Order,
['Orange'], [Spectral]); // dữ liệu quang phổ cho colorant khác
finally
Spectral.Free;
end;
Hai chi tiết vận hành dễ bị bỏ sót. Registry đứng sau tất cả những điều này thuộc về từng tài liệu và bị xoá tại các ranh giới tài liệu, nên nạp một tệp mới vào cùng instance THotPDF không thừa hưởng các danh tính spot của tài liệu trước; sự cách ly đó chính là điểm mấu chốt, vì một chữ ký sót lại sẽ từ chối những công việc hoàn toàn hợp lệ trong job kế tiếp. Phía profile cũng có những trần cứng của riêng nó: output intent ngoài yêu cầu mục tiêu PDF 2.0, một URL profile HTTP hoặc HTTPS tuyệt đối, một chữ ký không gian màu ICC bốn byte, và với PDF/X-6n là từ 2 đến 15 colorant với chữ ký 2CLR đến FCLR tương ứng
Nơi phép kiểm tra dừng lại
Phần xử lý CxF/X-4 là chỗ cần nói thật. HotPDF áp các kiểm tra an toàn cấu trúc có biên độ lên stream quang phổ và xác nhận danh tính mực bên trong nó khớp colorant bạn đã nêu tên. Nó đặt trần kích thước payload, từ chối byte null nhúng bên trong, khước từ mọi stream chứa khai báo DOCTYPE hay ENTITY, yêu cầu một root CxF nhận diện được, và yêu cầu đúng một phần tử SpotInkCharacterisation mang đúng một SpotInkName bằng với tên colorant của bạn. Đó là một cổng chống đầu vào dị dạng và mang tính thù địch, chứ không phải một validator schema. Nó không phải một bản triển khai ISO 17972-4 hoàn chỉnh, không kiểm chứng các phép đo quang phổ của bạn, và không kiểm toán ngược các đồ thị object bên thứ ba có sẵn tuỳ ý hay các bảng colorant nội bộ bên trong một profile ICC nhúng. Nếu quy trình của bạn phụ thuộc tuân thủ CxF đầy đủ, hãy xác thực tệp bằng một công cụ chuyên dụng trước khi trao nó cho component
Một ràng buộc liền kề cắn những người không bao giờ ngờ gặp nó. Một soft mask luminosity không thể dùng Separation, DeviceN, hay NChannel làm /CS của nhóm trong suốt; không gian trộn của nhóm phải là một không gian kiểu device hoặc CIE, nên màu spot bên trong nhóm được phân giải qua tint transform của nó vào không gian thay thế trước khi luminosity được tính. RegisterLuminositySoftMaskState dựng một nhóm DeviceGray chính xác vì điều đó để không thể sai sót do bất cẩn. Hệ quả thực tế là một thiết kế nhiều spot bị mask theo cách này đang được đánh giá qua proxy CMYK của nó, chứ không phải qua mực của nó, điều này có ý nghĩa khi bạn so nó với bản in tách màu như đã mô tả trong ghi chú về proofing overprint và thiết bị render
Không điều nào trong số này xoá bỏ nhu cầu về bản in thử, nhưng nó chuyển cả một lớp từ chối tiền ấn từ xưởng in trở lại bước dựng. Các API NChannel, Separation và output intent PDF/X-6n được mô tả ở đây đi kèm trong HotPDF Delphi Component chuẩn cho Delphi và C++Builder, nơi tài liệu tham khảo ghi rõ bố cục record đầy đủ và các điều kiện chính xác khiến mỗi lời gọi fail closed