الجواب القصير
ملفُّ GIF لوحةٌ، وقائمةُ مستطيلات تُطلى عليها، وجدولُ ألوان يقول ما تعنيه الأرقامُ في تلك المستطيلات. وكلُّ مستطيل يحمل ثلاثة أشياء: كم يبقى معروضاً، وماذا يُفعَل به بعدها، وجدولَ ألوان خاصاً به اختيارياً.
وكلُّ ما يجده الناسُ مفاجئاً في الصيغة تقريباً يخرج من تلك القائمة. فإن كان ملفُّك ضخماً، فلأن المستطيلات هي اللوحةُ كلُّها في كل مرة، أو لأن فيه ثلاثمئة جدول ألوان. وإن كان يُشغَّل ببطء شديد، فلأن التأخيرات دون أرضيةٍ لن ينزل تحتها أيُّ متصفح. وإن كان يلطّخ، فذلك هو الحقلُ المسمّى التخلّص.
ولترى أيُّها هو في ملف بعينه، افتح محلّل GIF وأفلِته فيه. وبقيةُ هذه الصفحة هي ما تعنيه الأرقام.
الإطاراتُ مستطيلات، لا صور
وهذا هو الجزءُ الذي يفاجئ من لم يرَ ملفات GIF إلا مشغَّلة. فالإطارُ ليس صورةً للحركة عند تلك اللحظة. بل هو مستطيل، له موضعٌ ومقاسٌ خاصّان به، مطليٌّ فوق ما تركته الإطاراتُ السابقة.
وذلك المستطيلُ قد يكون اللوحةَ كلَّها، وفي ملف سيّئ الصنع هو كذلك دائماً. لكنّ ملفَّ GIF مسموحٌ له أن يخزّن الجزءَ الذي تغيّر منذ الإطار الأخير لا غير — وحيث يكون معظمُ الصورة ساكناً، فذلك هو الفرقُ بين ملف بـ 12 ميغابايتاً وملفٍ بـ 900 كيلوبايت. وهو سببُ أن تسجيلَ شاشة لنافذة ساكنة في معظمها يمكن أن يكون صغيراً، وأن التسجيل نفسه الخارجَ من محوِّل غافل ليس كذلك.
ولا تستطيع معرفة أيَّهما عندك بمشاهدة الحركة. فكلاهما يبدو متطابقاً. والسبيلُ الوحيد إلى رؤية ذلك هو النظرُ إلى ما يخزّنه كلُّ إطار، وذلك عرضٌ عند المحلّل لهذا السبب بالضبط: بدّله إلى ما يخزّنه كلُّ إطار وحده فترى إما صفّاً من أشكال صغيرة على خلفية شفافة، ومعناه أن المرمِّز أدّى عمله، أو ترى الصورة كلَّها مرةً بعد مرة، ومعناه أنه لم يؤدِّه.
وليس ثمّة تعويضُ حركة في أي موضع من الصيغة. فلا شيء يُخزَّن أبداً «كالمرة الماضية لكن مزاحاً أربعةَ بكسلات إلى اليسار»، كما يفعل مرمِّزُ فيديو. فحيلةُ المستطيل المتغيّر هي التوفيرُ الوحيد عند GIF، وهي تساوي كثيراً.
التأخيرات، والأرضيةُ التي يفرضها كلُّ متصفح
كلُّ إطار يخزّن كم يُمسَك، بأجزاء من مئة من الثانية. وتلك هي الوحدةُ الوحيدة عند الصيغة، فأسرعُ ما يستطيع ملفٌّ طلبَه 0.01 ثانية — مئةُ إطار في الثانية — وأطولُه نحو 655 ثانية.
ولن يحصل على مئة إطار في الثانية. فكلُّ متصفح يقرّب تأخيراً دون 0.02 ثانية إلى 0.10. وقد كُتِبت القاعدةُ في Netscape Navigator سنة 1996، للكرات الدوّارة ولافتات «تحت الإنشاء» المتحرّكة في ذلك الزمن، وكلُّ متصفح بعده نسخها. ولم يزلها شيءٌ قط، ولن يزيلها شيء.
فملفُّ GIF الذي تقول إطاراتُه كلُّها 0.01 ثانية يُشغَّل عند عشرة إطارات في الثانية، لا مئة. فهو يعمل أبطأ عشر مرات ممّا أراده صانعه، والملفُّ لا يلمّح إلى هذا: فالتأخيراتُ فيه هي ما طُلِب بالضبط. وهذه أشيعُ مفاجأة واحدة في الصيغة، ولهذا يعرض المحلّلُ مدّتين — ما يقوله الملف، وما سيفعله المتصفحُ به فعلاً.
والعلاجُ، أيّاً كان مكانُ صنع الملف، أن تُكتَب 0.02 لا 0.01. فذلك يعطي 50 إطاراً في الثانية، وهو السقفُ الحقيقي، وهو أسرعُ ممّا يحتاجه أيُّ شيء. وعملياً 0.05 ثانية — عشرون إطاراً في الثانية — هي نحو أسرعِ ما يستحقّ الطلب.
وشيءٌ آخر تقوله لك التأخيرات. فإن كانت كلُّها متطابقة، فالملفُّ صُنِع من مجموعة إطارات بمعدّل ثابت. وإن تناثرت — 0.04 هنا و0.11 هناك — فشيءٌ حوّل فيديو وأسقط إطارات، ومطّ الجيرانَ لتغطية الفجوات. وإن كان الأخيرُ أطولَ كثيراً من البقية، فذلك عن قصد: فهكذا تجعل حركةً تتوقّف قبل أن تعيد.
التخلّص: الحقلُ الذي يقرّر أتلطّخ أم لا
كلُّ إطار يقول ما ينبغي أن يُترَك على الشاشة حين ينقضي وقته. وثمّة أربعةُ أجوبة ممكنة وهي جديرةٌ بالمعرفة، لأن ثلاثاً من الطرق الأربع التي تبدو بها الحركةُ خطأً هي هذا الحقل خطأً.
- يبقى في مكانه. فالإطارُ التالي يطلي فوقه مباشرةً. صحيحٌ حين تكون الإطاراتُ معتمةً وتغطّي بعضها بعضاً تماماً، وهو الخيارُ الأرخص، لأنه ليس ثمّة ما يُمسَح.
- يُمسَح رجوعاً إلى الخلفية. فيُمسَح مستطيلُ الإطار قبل أن يرسم التالي. وهذا ما تحتاجه الشفافية: فبدونه، تعرض الأجزاءُ الشفافة من الإطار التالي الإطارَ السابق تحتها، وتصير حركةٌ من صور منفصلة كومةً منها.
- يعيد ما كان تحته. فيُعاد ما كان على اللوحة قبل أن يرسم هذا الإطار. وهكذا يُخزَّن جسمٌ صغير يتحرّك فوق خلفية ساكنة — فكلُّ إطار يطلي الجسم، ثم تعود الخلفية، ولا يُكتَب إلا مستطيلُ الجسم أبداً.
- غيرُ محدَّد. فالملفُّ لم يقل. وكلُّ عارض يعامله معاملة «يبقى في مكانه»، وهو صحيحٌ عادةً وهو أحياناً سببُ تلطّخ ملف GIF شفاف.
وتفصيلةٌ تفترق فيها المواصفةُ عن الواقع. فـ «يُمسَح رجوعاً إلى الخلفية» تسمّي لونَ خلفية في ترويسة الملف، وكلُّ متصفح يتجاهله ويمسح إلى الشفاف بدلاً منه. وقد فعلوا ذلك خمساً وعشرين سنة. فالملفُّ الذي يعوّل على ظهور لون الخلفية ذاك سيبدو صحيحاً لصانعه فيما صنعه به، وخطأً في كل مكان آخر.
جداولُ الألوان، و768 بايتاً تكلّفها
بكسلُ GIF ليس لوناً. بل هو رقمٌ يشير إلى جدول فيه 256 لوناً على الأكثر، كلٌّ مخزَّنٌ بثلاثة بايتات. فالجدولُ الكامل إذن 768 بايتاً، والملفُّ يستطيع أن يكون له واحدٌ يتشاركه كلُّ شيء، أو واحدٌ لكل إطار، أو الاثنان.
والترتيبان مشروعان وهما يقايضان على وجهين:
- جدولٌ واحد مشترك هو 768 بايتاً للملف كلِّه، وهو يبقي الألوان ثابتةً بين الإطارات. وارتعاشُ GIF — ذلك التلألؤ المزعج في ملف مصنوع من فيديو — كثيراً جداً ما يكون اللوحةَ تتخبّط من إطار إلى إطار لا غير.
- وجدولٌ لكل إطار يتيح لكل إطار استعمالَ ألوان ليست عند المشترك، وذلك يهمّ حين يتغيّر المشهد تماماً. وهو يكلّف 768 بايتاً في كل مرة. وفي حركة من 300 إطار ذلك 230 كيلوبايتاً من جداول الألوان قبل تخزين بكسل واحد.
وثمّة كلفةٌ ثانية أهدأ. فطولُ جدول الألوان لا بدّ أن يكون قوّةً للعدد اثنين، فالإطارُ الذي يستعمل تسعة ألوان يحصل رغم ذلك على جدول من ستة عشر والإطارُ الذي يستعمل 130 يحصل رغم ذلك على 256. وبعضُ التقريب إلى أعلى لا مفرّ منه. أما الملفُّ الذي تعلن جداولُه خمسة آلاف لون لا تشير إليها بكسلاتُه قط فشيءٌ آخر: لوحاتٌ بُنِيت لصورة غير التي انتهت في الإطار. والمحلّلُ يعلّم المداخل غير المستعملة فيصير شكلُ ذلك مرئياً بنظرة.
أين تذهب البايتات فعلاً
كلُّ بايت في ملف GIF في واحد من عدد صغير من المواضع، ويجدر أن تعرف ما هي قبل أن تقرّر أن ملفاً كبيرٌ جداً.
- البكسلاتُ المضغوطة. في ملف سليم، هي كلُّه تقريباً. الصورةُ نفسها، ممرَّرةً عبر LZW — مخطَّطُ ضغط من 1984 صُمِّم للقطات شاشة لجداول بيانات، ولهذا يُبلي حسناً في اللون المسطّح وسيّئاً في الصور الفوتوغرافية.
- جداولُ الألوان. 768 بايتاً لكل جدول كامل، كما سبق.
- ترويساتُ كل إطار. ثمانيةُ بايتات من التوقيت وأحدَ عشرَ من الواصف لكل إطار. ولا شيء في ملف عادي؛ وفي حركة من ألفَي إطار ضئيل، 38 كيلوبايتاً.
- تأطيرُ الكتل. فالبياناتُ المضغوطة تُقطَّع مجارٍ لا تزيد على 255 بايتاً، لكلٍّ بايتُ طول أمامه. ونحو بايت من كل 256، لا مفرّ منه، وجديرٌ بأن يُرى لأنه غيرُ مرئي بغير ذلك.
- البياناتُ الوصفية. التعليقات، وملفاتُ تعريف الألوان، وحزمُ XMP. وهذه هي التي تنتج نتائج سخيفة حقاً: فمحرِّرُ صور قد يترك 40 كيلوبايتاً من XML يصف تحريراً جرى قبل سنين، وفي ملف GIF صغير ذلك معظمُ الملف. ولا يرسم أيُّ عارض شيئاً منه.
والسببُ في النظر إلى هذا جدولاً بدل التخمين أن الجواب مختلفٌ باختلاف الملفات، والعلاجُ يتبع الجواب. فالملفُّ الذي 95% منه بكسلاتٌ مضغوطة هو ببساطة صورةٌ كثيرة، ولن يفيد إلا إطاراتٌ أقلُّ أو مقاسٌ أصغر أو ألوانٌ أقلّ. والملفُّ الذي 30% منه جداولُ ألوان أو 40% منه XMP مشكلتُه أرخصُ بكثير.
التكرارُ ليس جزءاً من الصيغة
ليس في مواصفة GIF حقلٌ يقول إن حركةً تتكرّر. فالتكرارُ يأتي من كتلة اخترعتها Netscape سنة 1995 — «امتدادُ تطبيق» فيه السلسلة NETSCAPE2.0 — نفّذها كلُّ شيء على أي حال وهي الآن في كل ملف GIF متحرّك على الإنترنت.
ومعنى ذلك أن ملفاً بلا تلك الكتلة يُشغَّل مرةً واحدة بالضبط ويتوقّف، في كل متصفح، ويبدو مكسوراً لصانعه. فإن كانت حركةٌ تُشغَّل مرةً واحدة لا غير، فتلك الكتلةُ ناقصة؛ وهي من أوائل ما يستحقّ الفحص وهي غيرُ مرئية في أي عارض.
والكتلةُ تستطيع كذلك تسميةَ عدد — شغّل خمس مرات وتوقّف. والصفرُ يعني إلى الأبد، وهو ما يقوله كلُّ ملف تقريباً.
الأشياءُ الأخرى التي يستطيع ملفُّ GIF حملَها
ثلاثُ كتل لا تحمل صورةً ويتخطّاها كلُّ عارض:
- التعليقات. نصٌّ حرّ، عادةً اسمُ ما كتب الملف، وأحياناً شيءٌ ما كان صاحبُه ليختار نشره. ولا شيء يعرضه، وكلُّ نسخة من الملف تحمله.
- XMP. بياناتُ Adobe الوصفية بلغة XML: ما حرّر الملف، ومتى، وأحياناً من. وهي تصل ومعها مقطورةٌ سحرية من 258 بايتاً في آخرها، حيلةٌ لتخرج أطوالُ الكتل صحيحة، ولهذا تعطيك قراءةُ واحدة على وجه ساذج ملءَ شاشة من ثنائيات.
- النصُّ السادة. كتلةٌ من مواصفة 1989 تطلب من العارض رسمَ نصّ فوق الصورة في شبكة خلايا. ولم ينفّذها شيءٌ قط. فإن كانت في ملف واحدة، فما تقوله لن يظهر.
والثلاثةُ جديرةٌ بالمعرفة قبل إرسال ملف إلى مكان ما: فهي أجزاءُ ملف GIF التي تستطيع أن تقول شيئاً عنك، وهي تنجو من كل نسخ وإعادة رفع ما لم يجرّدها شيءٌ عن قصد.
قراءةُ ملف تالف
ملفاتُ GIF تُبتَر — تنزيلٌ توقّف، أو ملفٌّ استُرجِع من قرص يعطب، أو شيءٌ كتب تطبيقٌ نصفه. ولأن الصيغة مجرى كتل لا بنيةً واحدة مفهرَسة، فملفُّ GIF المبتور يظلّ مقروءاً عادةً حتى النقطة التي يتوقّف عندها: فكلُّ إطار قبل القطع سليمٌ وكامل.
وذلك جديرٌ بالمعرفة لأن معظم البرمجيات سترفض الملف ببساطة. والمحلّلُ الذي يقرأ أقصى ما يستطيع ويقول أين توقّف سيقول لك على الأقل كم نجا، وأالجزءُ الناقص إطارٌ واحد أم المئتان الأخيرة.
والمشكلةُ المعاكسة موجودةٌ كذلك: بايتاتٌ قابعةٌ بعد علامة نهاية الملف. فكلُّ فاكّ ترميز يتوقّف عند تلك العلامة، فهي لا تُقرأ أبداً ولا تُرسَم أبداً، وهي عادةً ملفٌّ ثانٍ أُلحِق بالأول بشيء فسد. وهي وزنٌ صافٍ وقطعُها لا يفقد شيئاً.
لا شيء من هذا يحتاج رفعاً
قراءةُ بنية ملف GIF ليست عملاً شاقاً — بل هي مشيٌ في قائمة كتل وفاكُّ ضغط صغير واحد — ولم يكن ثمّة قط سببٌ تقني لإرسال الملف إلى خادم لفعلها. ومحلّل GIF هنا يفعل ذلك كلَّه في الصفحة: المشيَ في الكتل، وLZW، والإطاراتِ مرسومةً على الشاشة، وحسابَ البايتات.
وذلك يهمّ في هذا العمل أكثر من معظم غيره، لأن الملفات التي يودّ الناسُ تفكيكها أكثرَ من غيرها هي كثيراً ما تكون التي هم أقلُّ ثقةً بمشاركتها — شيءٌ استُرجِع، أو شيءٌ أرسله إليهم أحد، أو شيءٌ فيه كتلةُ تعليق لم يقرؤوها بعد. والحجّةُ الأطول عن رفع الملفات تنطبق هنا بقوّتها في أي مكان آخر من هذا الموقع.