مقال تقني

نوى تصغير الصور والديثرينج الطباعي في HotPDF

يكشف HotPDF ثلاث نوَى لتصغير الصور عبر خاصية ImageDownsampleKernel، وتمريرة Floyd-Steinberg منفصلة عبر RenderOutputDither. فالأولى تتحكم في مظهر الصور الفوتوغرافية بعد تصغيرها لتحقيق ميزانية حجم، والثانية تتحكم في مظهرها بعد اختزال صفحة إلى أبيض وأسود. ولا واحدة منهما مفعلة افتراضيًا، وكلاهما اختياري للسبب نفسه: كلتيهما تكلف وقتًا حقيقيًا

والضغط الذي يقود الناس إلى هنا مألوف. عقد ممسوح ضوئيًا بحجم 60 MB يجب أن يخرج عبر بوابة بريد ترفض ما فوق 10 MB، أو دفعة كشوف حساب يجب أن تهبط على جهاز أحادي اللون من طراز الفاكس يصيّر كل بكسل رمادي إما ورقًا وإما حبرًا. وكلا المشكلتين مشكلتا إعادة أخذ عينات، ولكليهما جواب سريع يبدو قبيحًا وجواب بطيء يبدو صحيحًا

فيما تختلف النوى الثلاث فعلًا

لـ THPDFResampleKernel ثلاث قيم، وهي تجلس على نقاط مختلفة فعلًا على منحنى السرعة والجودة. فـ rkHalftone يفوّض إلى مسار GDI التاريخي StretchBlt بوضع HALFTONE، وهو رغم الاسم ترشيح من فئة bilinear: سريع، وكافٍ لفن الخطوط ولقطات الشاشة، ومعرَّض للحواف المتكسرة التي تتعرف عليها فورًا في الصور المصغرة. وrkBicubic يشغّل نواة Catmull-Rom قابلة للفصل، وrkLanczos3 يشغّل نواة windowed-sinc قابلة للفصل بدعم ثلاثة فصوص

وكلا النواتين القابلتين للفصل تجريان بتمريرتين، أفقيًا ثم رأسيًا، بـ 6 إلى 12 لقطة لكل بكسل وجهة بـ Pascal بحت. وهذا أبطأ بمقدار رتبة تقريبًا من مسار GDI، وهو تحديدًا سبب بقاء rkHalftone الافتراضي. في دفعة ليلية من آلاف الصفحات يكون الفرق قرار جدولة لا تفضيلًا. وفي وثيقة واحدة ينتظرها مستخدم، فإن Lanczos3 شبه مجانية وأفضل بجلاء

منحنيات الأوزان لنوى تصغير الصور الثلاث في HotPDF: rkHalftone يفوّض إلى مسار GDI HALFTONE من فئة bilinear بدعم واحد، وrkBicubic يشغّل تكعيبي Catmull-Rom قابلاً للفصل بدعم اثنين، وrkLanczos3 يشغّل windowed sinc بدعم ثلاثة، مقايضًا نحو رتبة كاملة من السرعة مقابل صور أفضل بجلاء
قيم النوى الثلاث تجلس على نقاط مختلفة فعلًا على منحنى السرعة والجودة: مسار GDI من فئة bilinear، وتكعيبي Catmull-Rom، وwindowed sinc ثلاثي الفصوص، والنواتان القابلتان للفصل تطبعان الأوزان فلا يظهر رنين بعد الأسود أو الأبيض

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

var
  Pdf: THotPDF;
  Info: THPDFLoadedResourceOptimizationInfo;
  Changed: Integer;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.LoadFromFile('scanned-contract.pdf');
    Pdf.ImageDownsampleKernel := rkLanczos3;   // اضبطها قبل الاستدعاء
    Changed := Pdf.DownsampleLoadedImages(150, 82, 4096, Info);
    if Changed > 0 then
    begin
      Writeln('resampled images: ', Info.DownsampledImageCount);
      Writeln('kept calibrated : ', Info.PreservedCalibratedImageCount);
      Pdf.SaveToFile('scanned-contract-150dpi.pdf');
    end;
  finally
    Pdf.Free;
  end;
end;

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

لماذا يصعب كشف معامل كثير حدود خاطئ

لأن نواة الاستقراء المعطوبة لا تنهار ولا ترمي، بل تنتج صورة تبدو خاطئة بخفة بطريقة لا يستطيع أحد نسبتها لسبب. فنواة Catmull-Rom تكعيبية قطعية، وفرعها الخارجي بصيغة Horner المتداخلة هو ((-0.5t + 2.5)t - 4)t + 2. اكتب ذلك المعامل الأوسط -5 بدل -4 والدالة ما زالت تُقيَّم، وما زالت تعيد أعدادًا في مجال معقول، وما زالت تنتج صورة

والضرر يظهر في W(1) تُقيَّم -1 حيث يجب أن تكون 0. تتراكم الأوزان السالبة، ويُقص المجموع عند الصفر، والعرض المرئي تدرّج صار طرفه الأيسر أسود، وحافة درجية فقدت درجاتها الوسطية. ولا شيء في الفشل يشير إلى كثير حدود. والفحص الذي يكشفه في ثوان حسابي لا بصري: على نواة استقراء أن تحقق W(0) = 1 وW(±1) = W(±2) = 0، وأي نواة تفوّت تلك النقاط الثلاث فيها خطأ معامل، نقطة. اتحقق من تلك القيم الثلاث في اختبار وحدة ويختفي صنف عيوب الخطأ المطبعي كله

رسم للفرع الخارجي لتكعيبي Catmull-Rom في HotPDF يبين لماذا يختبئ معامل خاطئ: الخطأ المطبعي الذي يكتب -5 بدل -4 في صيغة Horner المتداخلة ما زال يُقيَّم ويترك W(1) عند -1 وW(2) عند -2 حيث يُشترط الصفر، لذا فإن التحقق من W(0) تساوي 1 مع القيدَين الصفريين يكشفه في ثوان
النواة المعطوبة لا تنهار أبدًا، بل تعيد أعدادًا تبدو معقولة، ولهذا لا تلتقط العين خطأ معامل مطبعيًا. W(0) = 1 مع أصفار عند زائد وواحد وناقص واثنين اختبار وحدة من ثلاثة أسطر

ديثرينج Floyd-Steinberg وموضعه في خط المعالجة

تمريرة الديثرينج مشكلة مختلفة عن إعادة أخذ العينات وتسكن موضعًا مختلفًا في خط المعالجة. فـ RenderOutputDither تطبق نشر خطأ Floyd-Steinberg بعد تركيب الصفحة، وهو الموضع الوحيد الذي يرجح لمعاينة طباعة أحادية أو تصدير بطراز الفاكس: العملية تتعلق بخفض صورة نقطية نهائية إلى بت واحد لكل بكسل، لا بكيفية تغيير مقياس الصور المنفردة في طريق دخولها

والخوارزمية نفسها قصيرة. يُعتَبر الإضاءة عتبةً عند 50 بالمئة، وينشر خطأ التكميم إلى أربعة جيران بأوزان 7/16 و3/16 و5/16 و1/16 الكلاسيكية، نحو اليمين وأسفل اليسار وأسفل وأسفل اليمين. وبكسل المخرج 0 أو 255 في كل قناة. أما ما يعطيك إياه البديل الساذج — عتبة صارمة بلا نشر — فيحوّل صورة فوتوغرافية إلى ظلٍّ وسطوري ويضيع كل درجة وسطى كانت تحمل المحتوى

موضع ديثيرينج Floyd-Steinberg في خط معالجة الرسم في HotPDF: RenderOutputDither تجري بعد تركيب الصفحة على الصورة النقطية النهائية ذات 24-بت، تعتبر الإضاءة عتبة عند 50 بالمئة وتنشر كل خطأ تكميم يمينًا وأسفل بأوزان 7/16 و3/16 و5/16 و1/16 عبر ذاكرة صف يجب أن تتراكم، منتجة مخرجًا أحادي اللون ببت واحد
الديثرينج مكانه بعد التركيب لأنه يخفض صورة نقطية نهائية إلى بت واحد، لا بسبب كيفية تغيير مقياس الصور. أوزان النشر تجمع إلى واحد، وذاكرة الصف يجب أن تتراكم لا أن تستبدل
// ديثيرينج وقت الرسم لجهاز معاينة أحادي اللون
Pdf.RenderOutputDither := True;

// أو طبّق التمريرة نفسها على bitmap تملكه أصلًا. يجب أن يكون
// الـ bitmap بـ pf24bit؛ فالدالة تعيد False بدل التخمين
if not HPDFFloydSteinbergDitherBitmap(Preview) then
  raise Exception.Create('dither expects a 24-bit bitmap');

// وصول مباشر إلى النواة حين تعيد أخذ العينات خارج خط معالجة الوثيقة
Small := HPDFResizeBitmapKernel(Large, 640, 480, rkLanczos3);
try
  Small.SaveToFile('thumb.bmp');
finally
  Small.Free;
end;

وهناك تفصيلة تنفيذ واحدة في نشر الخطأ تعض كل شخص مرة. فذاكرة خطأ الصف-إلى-الصف يجب أن تتراكم. فكل بكسل في الصف التالي يتلقى إسهامات من ثلاثة بكسلات مختلفة في الصف الحالي، لقطات 3/16 و5/16 و1/16، وإذا أسند الكود بدل أن يجمع، ألغى كل كتاب الإسهام السابق وبقيت اللقطة الأخيرة وحدها. وما زالت الصورة تبدو مترذذة، وهذا ما يجعل الأمر صعب الملاحظة، لكن الملمس خاطئ وإعادة إنتاج الدرجات تنحرف. والاختبار الذي يكشفه كمي: طبّق الديثرينج على حقل رمادي وسطي موحد واطلب أن تبلغ تغطية الداخل بين 40 و60 بالمئة

أي تركيبة ينبغي لخط معالجة خفض الحجم أن يستخدم

طابق النواة مع ما هي الصور فعلًا، واعتبر الديثرينج شأن جهاز لا شأن ضغط. فللمسوحات الفوتوغرافية التي يجب أن تنجو من ميزانية حجم، يحفظ rkLanczos3 عند 150 أو 200 DPI التفاصيل التي يلاحظها الناس مع قطع عدد البكسلات بعامل أربعة أو أكثر. فلقطات الشاشة والمخططات وفن الخطوط، فـ rkHalftone جيد فعلًا وأسرع بكثير، لأن تلك الصور قليلة التدرجات اللونية المطلوب حفظها. ولدفعة مختلطة لا تستطيع فحص كل صورة فيها، فـ rkBicubic هو الوسط المعقول: أفضل من bilinear، ونحو نصف عدد لقطات Lanczos3

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

وإن كنت تبني سطح المعاينة الذي يعرض النتيجة، فمسار التصيير نفسه الموثق في تصيير صفحة PDF إلى bitmap هو حيث تسري RenderOutputDither، فتأتي معاينة مترذذة ومخرج مترذذ من مسار كود واحد لا من تنفيذين يفترقان مع الزمن

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