مقالة تقنية

عرض ألوان Separation وDeviceN الموضعية في دلفي

يعرض HotPDF ألوان Separation وDeviceN الموضعية على صفحات PDF المحملة عن طريق حل مساحة اللون من خلال HPDFResolveColorSpace، وتقييم دالة تحويل الظل باستخدام HPDFEvalTintTransform، وتحويل النتيجة عبر مساحة بديلة إلى RGB للشاشة. منذ الإصدار v2.375.0، تقيم هذه الأنبوبية جميع أنواع وظائف PDF الأربعة، بما في ذلك حاسبات PostScript من النوع Type 4، وبالتالي يعرض الملف الجاهز للطباعة بأحبار Pantone ألوانه الحقيقية بدلاً من عنصر نائب. تستعرض هذه المقالة كيفية عمل هذه الأنبوبية، وبنفس القدر من الأهمية, كيف فشلت أثناء بنائها

تكون الحالة المحفزة هي نفسها دائماً. يتلقى العميل ملف PDF من مطبعة: يتم تعيين العنوان الرئيسي بحبر موضعي مسمى، وتستخدم أعمال التغليف الفنية مزيج DeviceN ثنائي الحبر، ونص الجسم باللون الأسود العادي. في Acrobat يبدو ممتازاً. أما في تطبيق دلفي الخاص بك فيعرض العنوان باللون الأسود، أو الأسوأ من ذلك أنه لا يعرض على الإطلاق، ويقوم العميل بتسجيل خطأ ضد برنامجك بدلاً من الملف. الملف سليم تماماً. ولكن معالج العرض لا يتحدث ببساطة بلغة مساحات الألوان التي يستخدمها الملف

لماذا تعرض الألوان الموضعية باللون الأسود في عارض PDF؟

تعرض الألوان الموضعية باللون الأسود، أو تختفي، عندما يطبق معالج العرض معاملات ألوان الجهاز فقط (rg، وg، وk) ويتجاهل المعاملات العامة. يحدد معيار ISO 32000-1 §8.6 ثلاث مجموعات من مساحات الألوان: مساحات الأجهزة (DeviceGray، وDeviceRGB, وDeviceCMYK)، والمساحات المستندة إلى CIE (CalGray، وCalRGB، وLab، وICCBased)، والمساحات الخاصة (Indexed، وSeparation، وDeviceN، وPattern). يتم تحديد كل شيء خارج مجموعة الأجهزة بالمعاملات العامة: حيث يختار cs وCS مساحة بالاسم من قاموس موارد الصفحة، ثم توفر sc وSC وscn وSCN قيم المكونات. يحتفظ معالج العرض الذي يتخطى هذه المعاملات بأي لون تم تعيينه آخراً، وهو ما يكون بالنسبة لصفحة تبدأ بعنوانها الملون بالألوان الموضعية هو لون DeviceGray الأسود الأولي

أضاف HotPDF مجموعة المعاملات العامة إلى معالج صفحاته في الإصدار v2.333.0، إلى جانب مسار حل موحد: يتم تحليل كل إدخال مورد /ColorSpace، سواء كان اسماً مجرداً أو مصفوفة مضمنة أو مرجعاً غير مباشر، في سجل THPDFColorSpace واحد، ويتم توجيه كل طلب تعبئة أو لون خط عبر استدعاء HPDFResolveColor واحد. يظهر تعداد العائلات التغطية بلمحة

type
  THPDFColorSpaceFamily = (csfDeviceGray, csfDeviceRGB, csfDeviceCMYK,
                           csfIndexed, csfCalGray, csfCalRGB, csfLab,
                           csfICCBased, csfSeparation, csfDeviceN,
                           csfUnsupported);

function HPDFResolveColorSpace(Obj: THPDFObject): THPDFColorSpace;

function HPDFResolveColor(const CS: THPDFColorSpace;
  const Comps: THPDFColorComps; CompCount: Integer): THPDFRenderColor;

يدفع قرار تصميمي واحد ثمنه مراراً وتكراراً: csfUnsupported هي عائلة من الدرجة الأولى وليست خطأ. فالمساحة التي لا يستطيع معالج العرض تفسيرها تتراجع إلى بديل محدد بدلاً من إجهاض الصفحة، وهو ما يتطابق مع سلوك العارضات السائدة ويمنع تعبئة واحدة غريبة من إخلاء مستند يمكن عرضه بغير ذلك

كيف يحول تحويل الظل قيمة حبر واحدة إلى لون حقيقي؟

تحمل مساحة Separation ثلاث قطع من المعلومات: اسم الحبر، ومساحة لون بديلة، ودالة تحويل الظل. تقول المصفوفة [/Separation /PANTONE485 /DeviceCMYK f]: عندما يكتب تدفق المحتوى 0.8 scn، قم بتغذية قيمة الظل 0.8 في الدالة f وارسم رباعية CMYK الناتجة. ويعمم DeviceN هذا على N من الأحبار مع دالة ذات N من المدخلات. اسم الحبر نفسه استشاري فقط على الشاشة؛ وتحويل الظل هو كامل دلالات العرض، لذا فإن معالج العرض الذي يحلل المساحة ولكنه يتخطى الدالة لم يفعل شيئاً مفيداً بعد

تعتبر HPDFEvalTintTransform هي محرك الدالة الكامن خلف تلك الخطوة. بعد إطلاقها في v2.334.0، تقيم الدوال الأسية من النوع Type 2 (وهي C0 + x^N * (C1 - C0) مع تثبيت النطاق والمجال)، ودوال الخياطة من النوع Type 3 (تكرار الدوال الفرعية المحددة بالحدود مع إعادة تعيين الترميز)، ودوال العينات من النوع Type 0 مع عينات 8 و 16 و 32 بت. ويعتبر النوع Type 0 هو نفس آلية جداول البحث التي غطيناها من جانب التأليف في المقالة الخاصة ببناء جداول البحث عن ألوان Type 0؛ ويسير جانب العرض في الهيكل المتطابق نفسه بشكل عكسي، من بايتات العينة المفككة التشفير رجوعاً إلى قيم المكونات

كانت دوال الحاسبة PostScript من نوع Type 4 هي المعقل الأخير. وحتى الإصدار v2.375.0 تراجعت بأمان إلى عنصر نائب محايد؛ ومنذ الإصدار v2.375.0 تنفذ HPDFEvalPostScriptCalculator مجموعة معاملات ISO 32000-1 §7.10.5 الكاملة على مكدس معاملات محدود: الحساب، والمقارنة، والمعاملات المنطقية ومعاملات البتات، والتلاعب بالمكدس بما في ذلك roll، والشرطيات if/ifelse. دلالات الحالات الخاصة أدق مما تبدو. يقرب معامل round في PostScript النصف نحو القيمة الأكبر، لذا لا يمكن استخدام تقريب المصرفيين (banker's rounding) الخاص بـ Round في دلفي؛ وتعمل المعاملات المثلثية بالدرجات، مع إرجاع atan لقيم في النطاق [0, 360)؛ ويعتبر exp قوة ذات معاملين وليس الدالة الأسية الطبيعية. ويقود نفس المقيم أيضاً عمليات التعبئة المتدرجة القائمة على الدوال، ولهذا السبب التقط عرض التظليل المحوري والشعاعي منحدرات مدفوعة بالحاسبة في نفس الإصدار

// Evaluate a Separation/DeviceN tint transform (Type 0/2/3/4).
function HPDFEvalTintTransform(FuncObj: THPDFObject;
  const Inputs: THPDFColorComps; InputCount: Integer;
  out AltComps: THPDFColorComps): Boolean;

// Type 4 PostScript calculator, ISO 32000-1 7.10.5 operator set.
function HPDFEvalPostScriptCalculator(const Prog: TBytes;
  const Inputs: THPDFColorComps; InputCount: Integer;
  var Outputs: THPDFColorComps; OutCount: Integer): Boolean;

الصدق بشأن الدقة: لن تطابق الحاسبة البرمجية التي يتم تقييمها بدقة مزدوجة معالج الصور النقطية (RIP) بت لبت، ويمكن أن يختلف التثبيت عند حدود النطاق ببت واحد أقل أهمية عن تطبيق آخر. أما بالنسبة لعرض الشاشة وعمليات عرض التراجع، فإن هذا ليس ذا صلة؛ وإذا كنت تبني تدقيقاً مداراً بالألوان، فإن تحويل الظل هو المرحلة الأولى فقط وما زلت بحاجة إلى محرك CMM حقيقي في المراحل اللاحقة

CalGray، وCalRGB، وLab、وICCBased بدون محرك ICC

تأخذ العائلات المستندة إلى CIE الفرع الآخر لنفس المحلل. يحول HotPDF قيم Lab عبر سلسلة Lab إلى XYZ إلى sRGB القياسية، بما في ذلك مكعب نقطة التوقف 6/29 في دالة النقل العكسية، ويتعامل مع CalRGB باستخدام جاما لكل قناة بالإضافة إلى مصفوفة خطية 3x3 وCalGray بجاما الفردية الخاصة به. التفصيل ذو الصلة بالأداء هو معالجة نقطة البياض: يتم تعديل مصفوفة التحويل من XYZ إلى sRGB بطريقة Bradford لتناسب نقطة البياض المعلنة في مساحة اللون وتخزينها مؤقتاً في سجل THPDFColorSpace المحلول، وبالتالي يظل العمل لكل بكسل عبارة عن عملية ضرب 3x3 واحدة بغض النظر عن مدى غرابة المصدر الضوئي المعلن

تحصل مساحات ICCBased على معالجة براغماتية متعمدة. تتطلب مواصفات PDF من كل تدفق ICCBased الإعلان عن مساحة /Alternate أو مساحة ضمنية عبر عدد مكوناتها /N، بدقة لكي تتمكن العارضات التي تفتقر لمحرّك إدارة الألوان من العرض بشكل معقول. يحل HotPDF مساحات ICCBased عبر ذلك البديل، أو يخمن DeviceGray أو DeviceRGB أو DeviceCMYK من كون /N هو 1 أو 3 أو 4 عند غياب المدخل، ولا يحلل أبداً بايتات ملف التعريف. يعني هذا عدم وجود تبعية لـ lcms ولا تكلفة للبحث في ملف التعريف، على حساب الدقة اللونية: فالمساحة ICCBased التي ينحرف ملف تعريفها بشدة عن بديلها ستعرض عرض البديل. وبالنسبة للمشاهدة على الشاشة والصور المصغرة، فإن هذه هي نفس المقايضة التي تقوم بها كل عارضة خفيفة الوزن، وهي الحد الذي يجب توضيحه صراحة في وثائقك الخاصة

الخطأ الذي جعل كل بحث عن مساحة لون مسمية يفشل

شحن نظام المعاملات v2.333.0 بخلل ظل غير مرئي لـ اثنتين وأربعين إصداراً: بحث معالجا cs وCS عن معاملهما، مع إبقاء الشرطة المائلة الأمامية سليمة (/CS0), مقابل مفاتيح قاموس الموارد المخزنة بدون الشرطة المائلة (CS0). فشل كل بحث عن مساحة لون مسماة، مائة بالمائة من الوقت، وتراجع الكود بصمت إلى DeviceGray الافتراضي. كان العرض المرئي خفياً بأسوأ طريقة: أصبحت تعبئة Separation لـ 1 scn هي DeviceGray 1.0، والتي ترسم باللون الأبيض، والحبر الأبيض على صفحة بيضاء ليس خطأ عرض يقوم أي شخص بأخذ لقطة شاشة له. وكان الحل في v2.375.0 عبارة عن مساعد مشترك لتطبيع الأسماء يتم تطبيقه عند كل بحث من معامل إلى مورد

سقط خللان شقيقان من نفس التحقيق. أولاً، أعيدت المراجع غير المباشرة إلى كائنات ذات قيم مصفوفة دون حل: كان لوصول مستند معالج العرض محللون محددون للتدفقات والقواميس فقط، لذا فإن /CS0 5 0 R التي تشير إلى مصفوفة [/Separation ...] مستقلة أعيدت كمرجع خام وتحللت المساحة كغير مدعومة. ثانياً، فرضت HPDFReadNumericArray دلالات طول صارمة، تتطلب أن تكون مصفوفة PDF بطول المخزن المؤقت المزود على الأقل. وبالتالي فإن قراءة /C0 و/C1 لدالة Type 2 في مخزن مؤقت مكون من أربعة عناصر فشلت للبدائل ذات المكون الواحد والثلاثة مكونات، مما ترك كلتا المصفوفتين مصفورتين، وعرض كل ظل أسي غير CMYK باللون الأسود حتى قدم الإصدار v2.376.0 قارئ HPDFReadNumericArrayUpTo المتساهل. الدرس القابل للنقل: يجب قراءة أي مفتاح PDF موثق بأنه يحمل مصفوفة رقمية متغيرة الطول باستخدام قارئ يملأ ما هو موجود، لأن المخزن المؤقت ذي الحجم الثابت والمطابقة الصارمة يحول الملفات الصالحة إلى أصفار صامتة

كيف تختبر عرض الألوان الموضعية دون خداع نفسك؟

السؤال المزعج هو لماذا ظلت مجموعة الاختبارات خضراء طوال كل هذا. إن التراجع الأصلي، SeparationRendersDistinguishable، أكد فقط أن الصورة النقطية المعروضة لم تكن سوداء بالكامل. والأنبوبية التي خفضت كل لون موضعي إلى DeviceGray أنتجت مخرجات رمادية وبيضاء، وهي ليست سوداء، لذا مر التأكيد بينما كانت الميزة بأكملها ميتة. التأكيدات الضعيفة من قبيل "ليست فارغة"، أو "ليست سوداء بالكامل"، أو "التجزئة ليست صفراً" لا يمكنها تمييز معالج عرض يعمل عن آخر مكسور، لأن أي وضع فشل تقريباً لا يزال ينتج بعض البكسلات

أسلوب التأكيد الذي يكتشف هذه الإخفاقات فعلياً يقفل اللون المتوقع: اعرض ملف PDF مبنياً يدوياً بالحد الأدنى يحل حبر Separation الخاص به إلى صبغة معروفة، ثم عد البكسلات المهيمنة في تلك الصبغة. ويستخدم العرض في صورة نقطية للفحص نفس نقطة دخول RenderLoadedPageToBitmap الموضحة في دليل عرض الصفحات إلى صورة نقطية

var
  Pdf: THotPDF;
  Bmp: TBitmap;
  X, Y, RedHits: Integer;
  Px: TColor;
begin
  Pdf := THotPDF.Create(nil);
  try
    if Pdf.LoadFromFile('spot-red-fixture.pdf', '') > 0 then
    begin
      Bmp := Pdf.RenderLoadedPageToBitmap(0, 96);
      try
        RedHits := 0;
        for Y := 0 to Bmp.Height - 1 do
          for X := 0 to Bmp.Width - 1 do
          begin
            Px := Bmp.Canvas.Pixels[X, Y];
            if (GetRValue(Px) > 180) and (GetGValue(Px) < 100) and
               (GetBValue(Px) < 100) then
              Inc(RedHits);
          end;
        // Lock the expected ink: demand a real area of red-dominant
        // pixels, never settle for "not all black".
        Assert(RedHits > 500);
      finally
        Bmp.Free;
      end;
    end;
  finally
    Pdf.Free;
  end;
end;

الثابت (fixture) يهم بقدر ما يهم التأكيد. فملف PDF المبني يدوياً بطول بضع مئات من البايتات، مع تعبئة Separation واحدة ولا شيء غير ذلك، لا يترك أي غموض حول ماهية الناتج المتوقع؛ بينما يمرن الملف من العالم الحقيقي المزيد من الأكواد ولكنه لا يستطيع إخبارك بأي مرحلة فشلت. نحن نعامل الآن عد بكسلات الألوان المتوقعة كأدنى شريط لأي اختبار دخان للعرض، لأنه أسلوب التأكيد الوحيد الذي أجبر هذه العيوب على الظهور للعلن

عرض الألوان الموضعية ومساحة ألوان CIE جزء من أنبوبية المستندات المحملة في مكون HotPDF لدلفي وC++Builder، إلى جانب محرك الدوال، وعرض التظليل، ومسارات تصدير الصور النقطية الموضحة أعلاه