مقال تقني

خلفيات مرمز JBIG2 ورابط Free Pascal

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

في Delphi وC++Builder الخلفية الخارجية مجموعة ملفات كائنات ساكنة جاهزة البناء. وفي Free Pascal اضطرت إلى أن تصبح DLL، والطريق إلى تلك النتيجة حكاية روابط تفي بأي شخص حاول ربط كائنات C++ في برنامج Free Pascal

التسجيل هو العقد

تسجل وحدة الخلفية نفسها من قسم التهيئة لديها عبر استدعاء RegisterJBIG2EncoderBackend. ويطلبها المستدعون إما عبر بت الخيارات PDF_JBIG2_OPTION_EXTERNAL_ENCODER الذي قيمته 4، وإما عبر المعامل UseExternalEncoder في نقاط دخول الصور الموسعة. ومظلة المكتبة لا تسحب وحدة الخلفية عن قصد، لأن حمل مجموعة كائنات كبيرة ينبغي أن يكون قرار كل مشروع؛ ففي شجرة C++Builder مثلا تضمّنها صراحة المشاريع التي تريدها

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

مسار طلب ترميز JBIG2 في PDFlibPas حيث يعود تفضيل المرمز الخارجي بصمت إلى مسار Pascal MMR الأصلي دون وحدة الخلفية
طلب المرمز الخارجي لقاموس الرموز تفضيل: مربوطا يتقلص الناتج؛ وغير مربوط يعمل مسار Pascal MMR بصمت بملفات أكبر
uses
  PDFlibrary,
{$IFDEF FPC}
  PDFlibJBIG2EncDLL;    // الخلفية الديناميكية لـ Free Pascal
{$ELSE}
  PDFlibJBIG2EncC;      // مجموعة الكائنات الساكنة لـ Delphi / C++Builder
{$ENDIF}

var
  Pdf: TPDFlib;
  ImageId: Integer;
begin
  Pdf := TPDFlib.Create(nil);
  try
    Pdf.NewDocument;
    Pdf.NewPage;
    // Interpolate وSymbolExtract وUseExternalEncoder وSkipBlackDots
    // وBlackDotSize وLossyLevel
    ImageId := Pdf.AddImageJBIG2FromFileEx('scan-page-1.tif',
      0, 1, 1, 0, 0, 0);
    if ImageId = 0 then
      raise Exception.Create('JBIG2 encoding failed');
    Pdf.SaveToFile('archive.pdf');
  finally
    Pdf.Free;
  end;
end;

ترجمة الوحدة كانت سطرين. الرموز كانت الشغل الحقيقي

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

جانب الرموز كان الشغل الحقيقي. مجموعة الكائنات تشير إلى 176 رمزا بلغة C. منها 128 كان لديها تنفيذات Pascal داخل الوحدة ولم تحتاج سوى إلحاق أسماء تصدير، لأن Delphi يستخدم اسم الدالة كاسم الرمز بينما يشترط Free Pascal إعلان اسم عام صريحا. وسبعة وعشرون كانت مشتركة مع مرمز JPEG 2000 وجب تصديرها من مكان واحد بالضبط، لأن تعريفها مرتين يكسر أي برنامج يربط كليهما. والـ 21 الباقية كانت مدخلات منصة وزمن تشغيل C، ست عشرة دالة ملفات Win32 مع حفنة من نداءات المكتبة القياسية، وذهبت إلى وحدة توافق جديدة

لا شيء من ذلك صعب مفاهيميا، وكلها ضروري قبل أن يجرب الرابط المحاولة أصلا. وعند الرابط توقف كل شيء

ثلاث طرق ربط وثلاث طرق مسدودة

الرابط الداخلي لـ Free Pascal لا يستطيع قراءة ملفات الكائنات، لأن المترجم المنتج لها يصدر مقاطع COMDAT ترابطية، ويفيد الرابط الداخلي بأنه لا يدعمها. وهذا رفض قاطع لا تحذير

بدت محاولة الانتقال إلى رابط خارجي وكأنها الجواب. فرابط binutils المرفق مع Free Pascal ينهار نهائيا أثناء تطبيق جمع القمامة على المقاطع لهذا الأرشيف، وذلك العلم جزء من مجموعة المعاملات الثابتة التي يمررها Free Pascal لهدف Windows ذات 64 بت، فلا يمكن إزالته من سطر الأوامر؛ والمفاتيح الموثقة لكبحه تُتجاهل في هذا المسار. أما تزويد binutils أحدث بكثير فيفشل بطريقة أخرى: لا يستطيع معالجة سكربت الربط الخاص بـ Free Pascal إطلاقا، فينتج مخرجات فارغة من دون السكربت وجدارا من أخطاء إعادة التوطين معه

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

ثلاثة مسارات روابط فاشلة لكائنات مرمز JBIG2 بلغة C++ تحت Free Pascal ومكتبة DLL التي كشفت نقطتي دخول C مسطحتين حلتا المشكلة
مقاطع COMDAT تسقط الرابط الداخلي ويفشل الرابطان الخارجيان معا، فالمُرمز بلغة C++ يُشحن كـ DLL واحدة تربط ديناميكيا بواسطة وحدة الخلفية

لماذا لا يفيد مترجم C++ آخر

الفكرة التالية البديهية هي إعادة بناء جانب C++ بمترجم تقرأ Free Pascal كائناته. وهو لا يعمل هو الآخر، والسبب جوهري لا علاقة له بالمفاتيح. وحدة ترجمة C++ دنيا تحتوي قالبا، تترجم مع إطفاء كل ميزات توليد الكود، ما تزال تصدر رموزا خارجية ضعيفة، لأن التمثيل الفوري للقوالب والدوال المدمجة ينتجها بالبناء ذاته. ويرفض Free Pascal ذلك الصنف من الرموز قاطعا. والاتجاه المعاكس يفشل هو الآخر: لا يستطيع رابط C++ السائد استهلاك كائنات المترجم الآخر بسبب معالجة مقاطع COMDAT نفسها

فلا يمكن تسليم كود C++ إلى Free Pascal ككائنات عبر أي طريق متاح. لكنه يمكن تسليمه كـ DLL، وهو ما حدث: بنى المرمز واعتماديته لمعالجة الصور في مكتبة واحدة تكشف نقطتي دخول C مسطحتين، وتربط وحدة الخلفية في Free Pascal تلك النقاط ديناميكيا وتسجل نفسها تماما كما تفعل الخلفية الساكنة. ولم يلمس مسار Delphi وC++Builder إطلاقا، وهذه هي النتيجة الصحيحة؛ فمشكلة قابلية نقل على سلسلة أدوات واحدة لا ينبغي أن تزعزع السلسلة التي كانت تعمل أصلا

الاستقطاب هو الأمر الوحيد الذي سيتسبب في مشكلة

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

اصطلاحا الاستقطاب في DIB أحادي البت وفي JBIG2 حيث البت المضبوط أبيض في خط المسح وأسود في المرمز، ويصلح بعكس كل بايت
بايتات ذاتها ومعنى معاكس: من دون عكس كل بايت ينتج المرمز مسار JBIG2 صالحا للسالب الفوتوغرافي
// DIB أحادي البت: البت المضبوط يعني الأبيض. مرمز JBIG2: البت المضبوط يعني
// الأسود. اعكس كل بايت في الطريق إلى الداخل
for I := 0 to RowBytes - 1 do
  Row[I] := Row[I] xor $FF;

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

أي خلفية تستخدم

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

السؤال المنبع، كيف تُنتج الصورة ثنائية المستوى أصلها، لا يقل أهمية عن حجم المخرجات؛ التصيير أحادي اللون المبني على المناطق مشمول في مقال التصيير أحادي اللون للمناطق، واستراتيجية الحجم على مستوى المستند في تحسين حجم ملف PDF وتجزئة الخطوط. وللحزم الممسوحة ذات الصفحات المتكررة، إزالة التكرار تتفوق غالبا على ضغط أفضل، وهو موضوع إزالة تكرار الصور الإدراكية. وتوافر سلاسل الأدوات والخلفيات لكل منصة مدرج في صفحة منتج losLab PDF Developer Library