السلام عليكم ورحمة الله وبركاته
سُعدت بالمشاركة في مشروع MushafImad — تطبيق iOS لقراءة القرآن الكريم مفتوح المصدر، يُقدّم مصحفاً رقمياً احترافياً يعتمد على تقنيات مثل تتبع العين (Eye Tracking) لتسجيل تقدم القراءة.
كانت مساهمتي في Issue #69 الخاصة بتوليد صور الصفحات الكاملة من صور الأسطر المنفردة.
رابط المشكلة:
Issue #69 — Composite 604 page images from the line images
المشكلة
يحتوي المشروع على 604 × 15 = 9,060 صورة سطر منفردة (كل سطر 1440×232 بكسل). المهمة كانت كتابة أداة تدمج هذه الصور سطراً فوق سطر لتكوين صورة صفحة كاملة لكل صفحة من صفحات المصحف الـ 604.
التحدي الفعلي لم يكن مجرد دمج الصور، بل كانت الإشكاليات التالية:
التطابق البصري مع القارئ:
العارض في التطبيق لا يرسم الأسطر بارتفاعها الكامل (232px)، بل يضعها في خانة بارتفاع lineHeight × 0.73 = 169.36px، مما يعني تداخل الأسطر بنسبة 27%. الخطأ الأولي كان تجميع الأسطر بفراغ 232px بينها، فتنتج صورة 1440×3480 لا تطابق ما يراه المستخدم فعلاً في التطبيق.
خطأ صامت عند فقدان الملفات:
كان السكريبت يكمل عمله ويكتب صوراً شفافة فارغة على القرص حتى عند غياب بعض الصور المدخلة، دون إعلام أو فشل.
موقع الإخراج:
المسار الافتراضي كان داخل Sources/ مما أثار تحذيرات من مدير الحزم SwiftPM.
طريقة الحل
التجميع بالـ Pitch الصحيح:
استخدمت 169.36px بدلاً من 232px لتطابق منطق العارض، فتنتج صورة 1440×2603 تطابق ما يراه المستخدم بصرياً 1:1 في الوضع العمودي.
توثيق ثنائية الأبعاد للمساهمين القادمين (مهمة #70):
إصلاح الخطأ الصامت:
يتوقف السكريبت الآن عن الكتابة فوراً عند أول سطر مفقود أو تالف، ويخرج بكود خطأ غير صفري.
إضافة واجهة CLI:
دعم خيارات --page و--all و--lines-dir و--output-dir لتيسير التجربة السريعة والمسارات المخصصة.
نقل موقع الإخراج:
إلى build/page-images/ خارج Sources/ بالكامل.
ملاحظة من المشرف أثناء المراجعة
من بين ما لاحظه المشرف أثناء المراجعة، أن حجم صور الصفحات على القرص يبدو أكبر بثلاثة أضعاف من صور الأسطر المصدر. وكنت أظن في البداية أن هذا عيب في الحل نفسه.
لكن المشرف قاس الأمر بطريقة أدق، وتبيَّن أن المعلومات الفعلية في الصورتين متساوية — أي أن صورة الصفحة لا تحتوي على بيانات أكثر من صور الأسطر التي صُنعت منها.
سبب الفرق في الحجم على القرص هو طريقة الحفظ: الأداة التي استخدمناها (CGImageDestination) تكتب الصور بصيغة غير مضغوطة، بينما صور الأسطر الأصلية محفوظة بصيغة أكفأ. إعادة ضغط الصور الناتجة بأداة مثل oxipng تُعيد حجمها إلى نفس حجم الأسطر الأصلية.
بمعنى أبسط: الحل صحيح، والحجم الزائد ليس من صميم التصميم، وإنما من طريقة الحفظ،.
رابط الـ Pull Request
Pull Request #93
نسأل الله أن يجعل هذا العمل صدقةً جاريةً لكل مسلم يقرأ القرآن بهذا التطبيق. جزاكم الله خيراً.