دوال PDF هي واحدة من الزوايا الهادئة في المواصفات. يقابلها معظم المطورين مرة واحدة، كشيء يحتاجه التظليل المحوري من النوع 2 للتلاشي بين لونين، ولا ينظرون إليها مرة أخرى. هذا أمر مؤسف، لأن آلية الدوال هي مقيم صغير عام الأغراض يعيد التنسيق استخدامه للتظليل، ودوال النقل، ودوال بقع درجات اللون النصفي، ودرجات فصل الألوان، ومنحنيات نقل القناع الناعم. ومن بين أنواع الدوال الأربعة، فإن النوع 0 هو الأكثر قوة والأقل فهماً. إنها دالة مأخوذة عينات: شبكة متعددة الأبعاد من قيم المخرجات التي يستكملها القارئ. ونظراً لأن الشبكة يمكن أن تحتوي على أي أرقام تضعها فيها، فإن دالة النوع 0 يمكنها التعبير عن تعيين غير خطي عشوائي، وهو الشكل الدقيق لجدول البحث عن الألوان (LUT).
يستعرض هذا المقال قاموس النوع 0 كما يحدده معيار ISO 32000-1 في القسم 7.10.2، ثم يوضح الحالتين الأكثر أهمية في خط معالجة المستندات: جدول LUT لتصحيح الألوان RGB إلى RGB بثلاثة مدخلات، وتحويل درجة لون بقعي بمدخل واحد. يخدم نفس منشئ الدوال المأخوذة عينات كلتا الحالتين، والفرق بينهما هو بالكامل مسألة عدد المدخلات التي تحتوي عليها الشبكة.
الدالة المأخوذة عينات هي شبكة يستكملها القارئ
تقوم دالة النوع 0 بتعيين متجه ذي m من المدخلات إلى متجه ذي n من المخرجات عن طريق تخزين عينات على شبكة منتظمة والاستكمال بينها. يسرد القسم 7.10.2 من معيار ISO 32000-1 المفاتيح التي تصف تلك الشبكة. يحتفظ /Domain برقمين لكل مدخل، الحدين الأدنى والأقصى لكل محور إدخال. ويحتفظ /Range برقمين لكل مكون إخراج. /Size عبارة عن مصفوفة من m من الأعداد الصحيحة التي تعطي عدد العينات على طول كل محور إدخال، لذا فإن الشبكة التي تحتوي على اثنتي عشرة عينة على جانب في ثلاثة أبعاد تكون ذات حجم /Size [12 12 12] وتخزن 1,728 نقطة شبكة. يحدد /BitsPerSample دقة كل قيمة مخزنة، ويقبل HotPDF قيم 1، 2، 4، 8، 12، 16، 24، و32 بت، وهي تطابق القيم التي يسمح بها الجدول 38.
يتم قراءة تدفق العينات بترتيب ثابت. يختلف بعد الإدخال الأول بأسرع ما يمكن، ثم الثاني، وهكذا، وعند كل نقطة شبكة يتم تخزين مكونات الإخراج n بالترتيب. بالنسبة لجدول RGB إلى RGB، يمثل هذا ثلاثة بايت لكل نقطة شبكة عند ثمانية بتات، مرتبة كالتالي: مخرج أحمر، مخرج أخضر، مخرج أزرق، وتكتسح المدخل الأحمر أولاً. يقوم مفتاحان آخران بتعيين العالم المستمر على شبكة الأعداد الصحيحة. يقوم /Encode بتعيين كل مدخل من فاصل /Domain الخاص به إلى نطاق فهرس العينات من 0 إلى Size[i] - 1، ويقوم /Decode بتعيين الأعداد الصحيحة الخام المخزنة مرة أخرى إلى فواصل /Range. عندما تتركها عند قيمها الافتراضية، فإن المدخل الذي يغطي [0 1] يستقر تماماً على الشبكة الكاملة والبايت المخزن بقيمة 255 يتم فك ترميزه إلى قمة نطاق الإخراج الخاص به، وهو ما يريده جدول LUT للألوان الموحد على نطاق [0,1].
الترتيب 1 مقابل الترتيب 3
بين نقاط الشبكة، يتعين على القارئ إجراء الاستكمال، ويختار /Order كيفية ذلك. /Order 1 هو الاستكمال متعدد الخطوط: خطي على طول محور واحد، وثنائي الخطوط عبر محورين، وثلاثي الخطوط عبر ثلاثة محاور. إنه سريع، وهو بالضبط ما تفعله الأجهزة في معظم برامج العرض، وبالنسبة لتحويل ألوان سلس، لا يمكن تمييزه عادةً عن أي شيء أكثر تعقيداً. يطلب /Order 3 استكمال المنحنيات التكعيبية (cubic-spline)، والذي يلاءم منحنى أكثر سلاسة عبر العينات على حساب المزيد من العمل ومنطقة دعم أوسع حول كل نقطة يتم تقييمها.
المقايضة هي كثافة الشبكة مقابل سلاسة المنحنى. يثبت الترتيب التكعيبي قيمته عندما تكون الشبكة خشنة والتعيين يحتوي على انحناء مرئي، لأن الخط المستقيم بين عينتين متباعدتين يمكن أن يسطح منحنى النغمة بطريقة تلتقطها العين على التدرجات. بمجرد أن تصبح الشبكة كثيفة، تكون الأجزاء قصيرة بما يكفي ليتتبع الاستكمال الخطي المنحنى عن كثب ولا يضيف التكعيبي الكثير. القاعدة العملية هي اللجوء إلى /Order 3 فقط مع الشبكات الصغيرة أو التحويلات الحادة، وإلا يترك عند الخيار الافتراضي الخطي. لاحظ أن /Order ينطبق على دوال النوع 0 فقط، ويرفض HotPDF أي قيمة أخرى غير 1 أو 3.
LUT ثلاثية الأبعاد: ثلاثة مدخلات، وثلاثة مخرجات
تصحيح الألوان RGB إلى RGB هو الحالة النموذجية لشبكة ذات ثلاثة مدخلات، وهو جدول LUT ثلاثي الأبعاد الكلاسيكي المستخدم في تصنيف الألوان ومطابقة الأجهزة. كل محور من محاور المكعب هو قناة إدخال واحدة، وتخزن كل نقطة شبكة ثلاثية RGB المصححة لإحداثيات الإدخال تلك، ويقوم القارئ باستكمال عينات الزاوية ثلاثياً حول أي لون وارد. ثلاثة مدخلات لا مفر منها هنا لأن اللون الأحمر المصحح يمكن أن يعتمد على اللونين الأخضر والأزرق المدخلين، وليس فقط على الأحمر المدخل، ولا يمكن لمنحنى خاص بكل قناة التعبير عن التداخل بين القنوات، ولكن المكعب يمكنه ذلك.
HotPDF يبني تدفق النوع 0 من خلال RegisterSampledFunction، والذي يأخذ /Domain، و/Range، و/Size، و/BitsPerSample، وبايتات العينات مباشرة ويعيد كائن الدالة. بالنسبة لمكعب قياسي موحد، فإنك تمرر حدود [0,1] على محاور الإدخال الثلاثة والمخرجات الثلاثة، وحجم N x N x N، وجدول العينات المسطح. يتحقق المنشئ من أن عدد البايتات يطابق الشبكة: بالنسبة للعمق المحاذي للبايت، فإنه يتوقع OutputCount x (BitsPerSample div 8) x حاصل ضرب الأحجام، ويرفع خطأ إذا كانت المصفوفة بطول خاطئ، لذا فإن الخطوة المحسوبة بشكل خاطئ تفشل بصوت عالٍ عند التسجيل بدلاً من أن تظهر كبيانات تالفة لاحقاً.
const
N = 17; // 17 x 17 x 17 cube, the common ICC LUT resolution
var
LutFn: THPDFStreamObject;
Samples: TBytes;
begin
// Fill Samples with N*N*N grid points, 3 bytes each (R,G,B output),
// red input varying fastest. Build the corrected triple for each
// grid coordinate with your ICC-managed conversion, then store it.
SetLength(Samples, N * N * N * 3);
BuildCorrectedCube(Samples, N); // your color-managed fill
LutFn := Pdf.RegisterSampledFunction(
[0,1, 0,1, 0,1], // /Domain: three input axes on [0,1]
[0,1, 0,1, 0,1], // /Range: three output channels on [0,1]
[N, N, N], // /Size: the cube resolution per axis
8, // /BitsPerSample
Samples,
1); // /Order 1 = trilinear
end;
تكمن الصحة اللونية للمكعب في كيفية ملئه، وليس في دالة PDF. المسار الصحيح هو حساب كل نقطة شبكة من خلال تحويل مدار بواسطة ICC، وهو نفس المحرك الذي يدير التدقيق البرمجي، بحيث تعني الأرقام الموجودة في الشبكة شيئاً مقابل ملف تعريف مصدر ووجهة محددين. قم بتسجيل ملفات التعريف التي تحدد التحويل باستخدام RegisterICCProfile، والذي يسجل مساحة ألوان مبنية على ICC (مكون واحد، أو 3، أو 4) ويعيد اسم مورد يمكنك إرفاقه بالمحتوى الذي يغذيه جدول LUT. تحمل دالة النوع 0 جدول الاستكمال، بينما يحمل ملف تعريف ICC معنى نقاط النهاية.
الحالة أحادية البعد: تحويل درجة لون بقعي
تعتمد مساحات فصل الألوان على نفس الآلية لوظيفة مختلفة تماماً. تمثل مساحة الفصل (Separation space)، المحددة في القسم 8.6.6.4 من معيار ISO 32000-1، لوناً واحداً، وهو حبر بقعي مثل Pantone أو الورنيش، عن طريق إقران اسم بتحويل درجة اللون: دالة تعين قيمة درجة اللون أحادية البعد، من 0 لعدم وجود حبر إلى 1 للحبر الكامل، إلى مساحة ألوان بديلة يمكن للجهاز عرضها فعلياً، وتكون عادةً CMYK. وغالباً ما يكون تحويل درجة اللون هذا دالة من النوع 0، والآن تحتوي الشبكة على محور إدخال واحد بالضبط.
هذا هو التباين الواضح مع مكعب RGB. الحبر البقعي يمثل درجة حرية واحدة، لذا يحتاج تحويل درجة اللون الخاص به إلى مدخل واحد والشبكة عبارة عن خط من العينات، كل منها يحتفظ بقيمة CMYK (أو بديل آخر) عند مستوى درجة اللون ذلك. ويحتاج مكعب RGB إلى ثلاثة مدخلات لأن نطاقه ثلاثي الأبعاد وتتفاعل القنوات مع بعضها. نفس نوع الدالة، ونخص بذكر نفس قواعد الاستكمال، وأبعاد مختلفة، وتعيد المواصفات استخدام مقيم واحد وتسمح لـ /Size بتحديد ما إذا كنت تسير على خط، أو مستوى، أو مكعب. يغلف HotPDF الفصل بأكمله في RegisterSeparationLUT، والذي يبني تحويل درجة اللون من النوع 0 ذي المدخل الواحد من مصفوفة بايتات مسطحة داخلياً ويعيد اسم مورد مساحة الألوان.
var
SpotCS: AnsiString;
begin
// Four CMYK output bytes per tint grid point, tint domain [0..1].
// Here 0% ink -> all zero, 100% ink -> a rich spot build,
// with two interior steps; the tint transform interpolates between.
SpotCS := Pdf.RegisterSeparationLUT(
'PANTONE 286 C', // colorant name
'DeviceCMYK', // alternate color space
[ 0, 0, 0, 0, // tint 0.00 -> 0,0,0,0
90, 60, 0, 0, // tint 0.33
100, 80, 0, 10, // tint 0.66
100, 72, 0, 18]); // tint 1.00 -> full ink build
// Use SpotCS with SetFillColorSpace / SetFillColor on a page.
end;
يجب أن يكون عدد العينات عدداً صحيحاً من نقاط الشبكة: مضاعف إيجابي لعدد مكونات مساحة الألوان البديلة، ونقطتين على الأقل حتى يكون هناك جزء للاستكمال بينه. قم بتمرير ثلاثة بايتات لكل نقطة مقابل بديل CMYK وسيرفض الاستدعاء ذلك، وهو نفس التحقق الدفاعي الذي يطبقه منشئ الأبعاد الثلاثية، وهو ما تريده من دالة ستفشل بصمت في وقت الطباعة بخلاف ذلك.
أين تظهر نفس الآلية مرة أخرى
بمجرد أن ترى النوع 0 كجدول استكمال عام، تتوقف ميزتان إضافيتان للتحكم في الأجهزة عن الظهور كحالات خاصة. تقوم دالة النقل بضبط قيم المكونات في طريقها إلى جهاز الإخراج، وهي مجرد دالة لكل قناة، ويقوم HotPDF بتسجيلها كـ ExtGState من خلال RegisterTransferFunctionState، والذي يقبل إما دالة واحدة مدمجة أو مصفوفة من الدوال الخاصة بكل قناة. ونظراً لأن هذه الدوال هي كائنات دوال عادية، يمكنك تمرير كائن THPDFStreamObject الذي يعيده RegisterSampledFunction وتشغيل منحنى نقل من جدول مأخوذ عينات بدلاً من صيغة رياضية.
var
ToneFn: THPDFStreamObject;
GsName: AnsiString;
begin
// A single-input, single-output sampled tone curve on [0,1].
ToneFn := Pdf.RegisterSampledFunction(
[0,1], [0,1], [256], 8, ToneCurveBytes, 1);
// Apply it to all channels as a combined /TR2 transfer function.
GsName := Pdf.RegisterTransferFunctionState(ToneFn, []);
// Select GsName on the page before drawing the affected content.
end;
تندرج وظائف توليد اللون الأسود وإزالة الألوان التحتية في نفس العائلة. عندما يقوم جهاز بتحويل RGB إلى CMYK، فإنه يقرر مقدار المكون الرمادي الذي سيحمله كحبر أسود، وتعبر المواصفات عن هذا القرار كدالة، إدخالات /BG2 و/UCR2 في قاموس حالة الرسومات، كل منها عبارة عن منحنى ذي مدخل واحد من الرمادي المحسوب إلى كمية اللون الأسود. هذه هي دوال النوع 0 أيضاً عندما تريد منحنى مقاساً بدلاً من منحنى تحليلي، ويتم بناؤها بنفس الطريقة عبر RegisterSampledFunction ووضعها في حالة الرسومات. الدرس الذي يجدر الاحتفاظ به هو أن دالة PDF ليست أبداً المكان الذي تدار فيه الألوان، بل هي جدول البحث الذي يحمل قراراً اتخذته باستخدام محرك ألوان حقيقي، والنوع 0 هو نوع الدوال الوحيد المرن بما يكفي لحمل أي قرار على الإطلاق.
للحصول على صورة أوسع لكيفية إصدار الخطوط والصور وموارد الألوان في مستند نهائي، راجع دليلنا لتقرير المخرجات مع الخطوط والصور. عندما يتعين على المخرجات اجتياز فحص التحقق قبل الطباعة أو الأرشفة، فإن قواعد مساحة الألوان ونية المخرجات الموضحة في دليل التحقق من صحة PDF/A وPDF/X وPDF/UA تحدد أي من هذه الدوال مسموح به وكيف يجب وسم ألوان الأجهزة. كل هذا يتم شحنه في مكون HotPDF لـ Delphi وC++Builder، إلى جانب واجهات برمجة تطبيقات التظليل وICC والفصل التي تعتمد على نفس نواة النوع 0.