مقال تقني

الأقنعة الناعمة وتسطيح الشفافية في Delphi

تنشئ PDF Library for Delphi كلا نوعي القناع الناعم في PDF من Delphi. تُرفق SetImageSoftMaskEx صورة قناع بصورة هدف ويمكنها كتابة إدخال /Matte الذي يحتاجه الرسم مُسبَق الضرب. وتبني NewSoftMaskGraphicsState قناع ألفا أو لمعان من محتوى مُلتقَط وتُعيد حالة رسوميات تُطبِّقها على الرسم اللاحق. وعندما لا يستطيع مستهلك التعامل مع الشفافية إطلاقًا، تُرسِم FlattenTransparency النتيجة البصرية وتستبدل كل صفحة بها

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

نوعا القناع، وما يقرأه كل منهما

يأخذ قناع ألفا قيمه من قناة ألفا للمحتوى المُقنِّع. ويأخذ قناع اللمعان قيمه من سطوع المحتوى المُقنِّع، بحيث تكون المنطقة البيضاء معتمة تمامًا والمنطقة السوداء شفافة تمامًا. واللمعان هو ما يلجأ إليه المصممون، لأن رسم تدرج رمادي طريقة طبيعية لوصف تلاشٍ

وتُبنى الأقنعة الناعمة من نوع Form من محتوى مُلتقَط، وعدة تفاصيل ثابتة لا اختيارية. يصبح المحتوى المُلتقَط مجموعة شفافية معزولة بصيغة DeviceRGB، بحيث يُقيَّم القناع في فضاء ألوان معروف. لذلك يجب أن يحمل لون الخلفية ثلاثة مكونات، مطابقًا لتلك المجموعة. وتقبل دالة النقل /Identity أو كائن دالة صالحًا، مما يتيح لك إعادة تشكيل منحنى القناع دون إعادة رسم العمل الفني

رسم تخطيطي يقارن أقنعة اللمعان وألفا الناعمة وهي تغذّي NewSoftMaskGraphicsState، مع تذكير بأن حالة الرسوميات تستمر حتى تُمسح
تقرأ أقنعة اللمعان السطوع بينما تقرأ أقنعة ألفا التغطية، وتُغلِّف NewSoftMaskGraphicsState أيًا منهما في حالة رسوميات مستمرة
uses
  PDFlibrary;

var
  Lib: TPDFlib;
  MaskCapture, MaskGS, PhotoID: Integer;
begin
  Lib := TPDFlib.Create;
  try
    Lib.LoadFromFile('brochure.pdf', '');

    // الصفحة 4 تحمل تدرجًا رماديًا مرسومًا للاستخدام كقناع
    MaskCapture := Lib.CapturePage(4);

    MaskGS := Lib.NewSoftMaskGraphicsState(MaskCapture,
      PDF_SOFT_MASK_LUMINOSITY, '0 0 0', '/Identity');

    Lib.SelectPage(1);
    Lib.SetGraphicsState(MaskGS);
    PhotoID := Lib.AddImageFromFile('hero.jpg', 0);
    Lib.SelectImage(PhotoID);
    Lib.DrawImage(40, 700, 515, 260);        // يتلاشى تحت القناع

    // إعدادات ExtGState تستمر: أنهِ النطاق صراحة
    Lib.SetGraphicsState(Lib.NewSoftMaskGraphicsState(0,
      PDF_SOFT_MASK_NONE, '', ''));

    Lib.SaveToFile('brochure-masked.pdf');
  finally
    Lib.Free;
  end;
end;

وتلك الخطوة الأخيرة ليست زخرفة. فمعاملات حالة الرسوميات تستمر حتى تتغير، وتطبيق حالة رسوميات عادية بعد ذلك لا يمسح قناعًا ناعمًا نشطًا. وبدون /SMask /None صريحة، يرث كل شيء يُرسم بعد العمل الفني المُقنَّع ذلك القناع، وهذا أحد الأخطاء الأكثر إرباكًا في التشخيص بصريًا

أقنعة الصور وإدخال Matte

بالنسبة للتقنيع على مستوى الصورة، تُطبَّع صورة القناع أولاً إلى DeviceGray، بحيث يتصرف قناع مُقدَّم بأي فضاء ألوان بشكل متوقع. ويخبر إدخال /Matte الاختياري، من مكون واحد إلى أربعة حسب فضاء ألوان الصورة، مستهلكًا بأن بيانات الصورة مضروبة مسبقًا بذلك اللون، مما يمنع الهالة الداكنة التي تظهر عندما يُركَّب عمل فني مضروب مسبقًا كما لو كان ألفا مستقيمًا

رسم تخطيطي يُظهر إدخال Matte مفقودًا ينتج هالات داكنة بينما يُركِّب إدخال Matte مُعلَن بنظافة، إلى جانب حواجز حماية PDF 1.4 و PDF/A و PDF/X
إدخال /Matte مُعلَن يمنع الهالة الداكنة لعمل فني مضروب مسبقًا، بينما تُرفض ملفات PDF/A-1 و PDF/X-1 قبل أي تغيير في الكائنات

وحاجزا حماية مهمان هنا. يحظر PDF/A-1 و PDF/X-1 الشفافية، ويرفض الاستدعاء قبل تعديل أي كائن بدلاً من إنتاج ملف يفشل التحقق لاحقًا. ويتطلب قناع ناعم ناجح PDF 1.4، الذي تضبطه المكتبة تلقائيًا — فالشفافية لم تكن موجودة قبل ذلك الإصدار، وترويسة 1.3 على ملف يحتوي أقنعة ناعمة خاطئة ببساطة

وتُعاد استخدام الحالات المتكررة: النموذج المُلتقَط نفسه، ونوع القناع، والخلفية، وتوقيع دالة النقل نفسها تنتج كائن حالة رسوميات واحدًا نفسه بدلاً من كائن جديد لكل استدعاء. وعلى مستند يُقنِّع مئة صورة بشكل متطابق، ذلك تسعة وتسعون كائنًا لا تُكتب أبدًا

لماذا التسطيح، وما الذي يفعله فعليًا

لا تزال الشفافية المصدر الأكثر شيوعًا لظاهرة "يبدو صحيحًا على الشاشة وخاطئًا على المطبعة". فأجهزة RIP الأقدم، وبعض أنظمة التقديم التنظيمي، وملفات PDF/X-1a جميعها تتطلب ملفًا بلا شفافية حية إطلاقًا

والتسطيح هنا حرفي عمدًا: تُرسَم كل صفحة في النطاق المطلوب بدقة نقاط في البوصة مختارة فوق خلفية معتمة، ويُستبدل محتوى الصفحة ومواردها بتلك الصورة الواحدة. ولأن الراسم ينتج النتيجة المُركَّبة النهائية، يغطي هذا كل شيء دفعة واحدة — مجموعات الشفافية، وأنماط المزج، والأقنعة الناعمة، والأنماط، والنماذج المتداخلة — دون منطق تقريب لكل بنية على حدة يمكن أن يخطئ. وتبقى ذاكرة الصور النقطية القصوى محدودة بصفحة واحدة

رسم تخطيطي لخط أنابيب FlattenTransparency وهو يرسم كل صفحة مطلوبة بدقة 300 نقطة في البوصة فوق خلفية معتمة ويحفظ ملف PDF 1.3 مسطَّحًا جاهزًا للمطبعة
تُرسَم كل صفحة مطلوبة مرة واحدة بالدقة المختارة وتعود كصورة معتمة واحدة محفوظة في ملف PDF 1.3 صادق
// سطّح الصفحات 1-8 بدقة 300 نقطة في البوصة على أبيض، ثم احفظ كـ PDF 1.3
Lib.FlattenTransparency('1-8', 300, $FFFFFF, 0);
Lib.SaveToFile('press-ready.pdf');

والمقايضة حرفية بالقدر نفسه: المخرجات صورة، بحيث لم يعد النص قابلاً للتحديد أو البحث وتُعاد أخذ عيّنات حواف المتجهات بالدقة المختارة. والتسطيح خطوة تسليم لا خطوة تحرير. احتفظ بالأصل الشفاف وسطّح نسخة

الصفحات المُدارة، ووحدات المستخدم، وصناديق الصفحة

تحتاج صفحة مُدارة عناية يتخطاها تنفيذ ساذج. فبعد الرسم، يُكتب العرض والارتفاع البصريان مرة أخرى في MediaBox، وتُطوى وحدة المستخدم في دقة النقاط في البوصة الفعلية وحجم الصفحة الجديد، وتُزال قيمة /Rotate ووحدة المستخدم وصناديق الصفحة المساعدة

وتخطي ذلك ينتج ملفًا تكون فيه الصورة المُسطَّحة صحيحة لكن يعيد عارض إدارتها مرة أخرى، أو يحجّمها بوحدة مستخدم لم تعد تنطبق. وإزالة الصناديق بدلاً من إعادة حسابها هي القرار الصحيح، لأن TrimBox يصف الهندسة قبل التسطيح أسوأ من عدم وجود TrimBox إطلاقًا

وتُرسَم الحواشي التوضيحية وحقول النماذج في الصورة الثابتة افتراضيًا وتُزال الكائنات التفاعلية، وهذا ما يريده منتج جاهز للطباعة. وإذا احتفظت بالكائنات التفاعلية بدلاً من ذلك، تُعطَّل تمريرة الحاشية التوضيحية للراسم بحيث لا يُرسَم شيء مرتين

فحص الإصدار الذي يمسح كل شيء

يتطلب الحفظ كـ PDF 1.3 ألا تبقى أي شفافية في أي مكان، ويفحص التحقق قبل الحفظ كل كائن غير مباشر، لا فقط الكائنات القابلة للوصول من الصفحات. وهذا أكثر صرامة مما يبدو للوهلة الأولى وهو صحيح: فقناع ناعم يتيم تركه تحرير سابق لا يزال في الملف، وسيجده مستهلك يجتاز الكائنات لا الصفحات

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

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

يأتي إنشاء الأقنعة الناعمة والتسطيح ومحرك الرسم الذي يقف خلفهما في مكتبة واحدة لـ Delphi و C++Builder و Free Pascal؛ وقائمة الميزات الكاملة على صفحة PDF Library لـ Delphi