छोटा जवाब
GIF एक कैनवस है, उस पर पोतने के लिए आयतों की एक सूची है, और रंगों की एक तालिका है जो बताती है कि उन आयतों के भीतर लिखी संख्याओं का मतलब क्या है। हर आयत तीन चीज़ें साथ लाता है: उसे कितनी देर टिकाए रखना है, बाद में उसका क्या करना है, और चाहे तो अपनी अलग रंग-तालिका।
इस फ़ॉर्मैट के बारे में लोगों को जो कुछ अचरज भरा लगता है, वह लगभग सब उसी सूची से निकलता है। अगर आपकी GIF बहुत बड़ी है, तो या तो आयत हर बार पूरा कैनवस हैं, या उसमें तीन सौ रंग-तालिकाएँ पड़ी हैं। अगर वह बहुत धीमी चलती है, तो देरियाँ उस फ़र्श से नीचे हैं जिसके नीचे कोई ब्राउज़र नहीं जाता। और अगर वह लकीर छोड़ती है, तो वजह वह खाना है जिसे निपटान कहते हैं।
किसी खास फ़ाइल में इनमें से क्या है, यह देखने के लिए GIF एनालाइज़र खोलिए और उसे भीतर छोड़ दीजिए। इस पेज का बाकी हिस्सा बताता है कि वे संख्याएँ क्या कहती हैं।
फ़्रेम आयत हैं, तस्वीरें नहीं
जिन्होंने GIF सिर्फ़ चलती हुई देखी है, उन्हें यही हिस्सा चौंकाता है। फ़्रेम उस पल की ऐनिमेशन की तस्वीर नहीं है। वह एक आयत है, अपनी जगह और अपने आकार के साथ, और वह उसी के ऊपर पोता जाता है जो पहले के फ़्रेम छोड़ गए थे।
वह आयत पूरा कैनवस भी हो सकता है, और खराब बनी फ़ाइल में वह हमेशा होता ही है। पर GIF को इसकी छूट है कि वह सिर्फ़ तस्वीर का वही हिस्सा रखे जो पिछले फ़्रेम के बाद बदला — और जहाँ तस्वीर का ज़्यादातर हिस्सा स्थिर है, वहाँ यही 12 MB की फ़ाइल और 900 KB की फ़ाइल के बीच का फ़र्क है। इसीलिए लगभग स्थिर खिड़की की स्क्रीन रिकॉर्डिंग छोटी हो सकती है, और वही रिकॉर्डिंग किसी लापरवाह कन्वर्टर से निकलकर छोटी नहीं होती।
ऐनिमेशन देखकर आप नहीं बता सकते कि आपके पास कौन-सी है। दोनों एक जैसी दिखती हैं। देखने का अकेला तरीका यह है कि हर फ़्रेम क्या रखता है वह देखा जाए, और एनालाइज़र में वह नज़र ठीक इसीलिए है: उसे हर फ़्रेम जो रखता है सिर्फ़ वही पर कर दीजिए, और या तो आपको पारदर्शी पृष्ठभूमि पर छोटी-छोटी आकृतियों की एक कतार दिखेगी, जिसका मतलब है कि एनकोडर ने अपना काम किया, या फिर बार-बार पूरी तस्वीर दिखेगी, जिसका मतलब है कि नहीं किया।
इस फ़ॉर्मैट में कहीं भी मोशन कंपेंसेशन नहीं है। कुछ भी कभी “पिछली बार जैसा ही, बस चार पिक्सल बाएँ” की तरह नहीं रखा जाता, जैसा कोई वीडियो कोडेक करता। बदले हुए आयत वाली तरकीब ही GIF की अकेली बचत है, और वह बहुत कीमती है।
देरियाँ, और वह फ़र्श जो हर ब्राउज़र लागू करता है
हर फ़्रेम रखता है कि उसे कितनी देर थामे रखना है, सेकंड के सौवें हिस्सों में। फ़ॉर्मैट के पास यही एक इकाई है, इसलिए कोई फ़ाइल सबसे तेज़ जो माँग सकती है वह 0.01 सेकंड है — यानी सौ फ़्रेम प्रति सेकंड — और सबसे लंबी करीब 655 सेकंड।
उसे सौ फ़्रेम प्रति सेकंड मिलेंगे नहीं। हर ब्राउज़र 0.02 सेकंड से कम देरी को बढ़ाकर 0.10 कर देता है। यह नियम 1996 में Netscape Navigator में लिखा गया था, उस ज़माने के घूमते हुए ग्लोब और चलते हुए “निर्माण जारी” वाले बोर्डों के लिए, और उसके बाद हर ब्राउज़र ने उसे नकल कर लिया। किसी ने उसे कभी हटाया नहीं, और कोई हटाएगा भी नहीं।
तो जिस GIF के सारे फ़्रेम 0.01 s कहते हैं, वह सौ नहीं, दस फ़्रेम प्रति सेकंड चलती है। जिसने उसे बनाया उसके इरादे से दस गुना धीमी, और फ़ाइल इसका कोई इशारा नहीं देती: उसमें लिखी देरियाँ ठीक वही हैं जो माँगी गई थीं। इस फ़ॉर्मैट का यह सबसे आम अचरज है, और इसीलिए एनालाइज़र दो अवधियाँ बताता है — जो फ़ाइल कहती है, और जो ब्राउज़र असल में करेगा।
इलाज, फ़ाइल जहाँ भी बनी हो, यह है कि 0.01 की जगह 0.02 लिखा जाए। उससे 50 फ़्रेम प्रति सेकंड मिलते हैं, जो असली छत है, और किसी भी ज़रूरत से तेज़ है। व्यवहार में 0.05 s — बीस फ़्रेम प्रति सेकंड — लगभग उतना ही तेज़ है जितना माँगना समझदारी है।
देरियाँ एक बात और बताती हैं। अगर वे सब एक जैसी हैं, तो फ़ाइल तय दर वाले फ़्रेमों के समूह से बनी है। अगर वे बिखरी हुई हैं — यहाँ 0.04, वहाँ 0.11 — तो किसी चीज़ ने वीडियो बदला है और फ़्रेम गिराए हैं, और खाली जगह ढँकने के लिए पड़ोसी फ़्रेमों को खींच दिया है। और अगर आखिरी वाली बाकी सबसे कहीं लंबी है, तो वह जानबूझकर है: ऐनिमेशन को दोबारा शुरू होने से पहले ठहरने का तरीका यही है।
निपटान: वह खाना जो तय करता है कि लकीर छूटेगी या नहीं
हर फ़्रेम बताता है कि उसका समय पूरा होने पर स्क्रीन पर क्या छूटना चाहिए। चार संभव जवाब हैं और उन्हें जानना ठीक रहता है, क्योंकि ऐनिमेशन के गलत दिखने के चार में से तीन तरीके इसी खाने के गलत होने से आते हैं।
- वहीं छोड़ दीजिए। अगला फ़्रेम सीधे उसके ऊपर पोत देता है। जब फ़्रेम अपारदर्शी हों और एक-दूसरे को पूरा ढँकते हों तब यही ठीक है, और यही सबसे सस्ता भी, क्योंकि कुछ मिटाना नहीं पड़ता।
- पृष्ठभूमि तक साफ़ कर दीजिए। अगला फ़्रेम बनने से पहले इस फ़्रेम का आयत पोंछ दिया जाता है। पारदर्शिता को यही चाहिए: इसके बिना अगले फ़्रेम के आर-पार दिखने वाले हिस्सों से पिछला फ़्रेम झाँकता है, और अलग-अलग तस्वीरों का ऐनिमेशन तस्वीरों का ढेर बन जाता है।
- नीचे जो था उसे लौटा दीजिए। इस फ़्रेम के बनने से पहले कैनवस पर जो था, वह वापस रख दिया जाता है। स्थिर पृष्ठभूमि पर चलती हुई कोई छोटी चीज़ ऐसे ही रखी जाती है — हर फ़्रेम उस चीज़ को बनाता है, फिर पृष्ठभूमि लौट आती है, और लिखा हमेशा सिर्फ़ उस चीज़ का आयत जाता है।
- कुछ नहीं कहा गया। फ़ाइल ने बताया ही नहीं। हर व्यूअर इसे “वहीं छोड़ दीजिए” मान लेता है, जो आम तौर पर सही होता है और कभी-कभी पारदर्शी GIF के लकीर छोड़ने की वजह बन जाता है।
एक जगह स्पेसिफ़िकेशन और हकीकत अलग हो जाते हैं। “पृष्ठभूमि तक साफ़” फ़ाइल के हेडर में लिखे एक पृष्ठभूमि रंग की ओर इशारा करता है, और हर ब्राउज़र उसे अनदेखा करके पारदर्शी तक साफ़ करता है। पच्चीस साल से यही चल रहा है। जो फ़ाइल उस पृष्ठभूमि रंग के दिखने के भरोसे बनी है, वह उसके बनाने वाले को उसी सॉफ़्टवेयर में सही दिखेगी, और बाकी हर जगह गलत।
रंग-तालिकाएँ, और उनके 768 बाइट
GIF का पिक्सल कोई रंग नहीं है। वह एक संख्या है जो ज़्यादा से ज़्यादा 256 रंगों की तालिका की ओर इशारा करती है, और हर रंग तीन बाइट में रखा जाता है। इसलिए पूरी तालिका 768 बाइट की होती है, और एक फ़ाइल में या तो सबके लिए एक साझा तालिका हो सकती है, या हर फ़्रेम की अपनी, या दोनों।
दोनों इंतज़ाम जायज़ हैं और दोनों का सौदा अलग है:
- एक साझा तालिका पूरी फ़ाइल के लिए 768 बाइट है, और वह फ़्रेमों के बीच रंगों को स्थिर रखती है। GIF की टिमटिमाहट — वीडियो से बनी फ़ाइल में वह चुभने वाली झिलमिलाहट — अक्सर बस पैलेट का हर फ़्रेम पर उछलना ही होती है।
- हर फ़्रेम की अपनी तालिका हर फ़्रेम को ऐसे रंग देती है जो साझा तालिका के पास नहीं हैं, और जब दृश्य पूरी तरह बदलता है तब यह मायने रखता है। कीमत हर बार 768 बाइट है। 300 फ़्रेम के ऐनिमेशन पर यह एक भी पिक्सल रखे जाने से पहले 230 KB की रंग-तालिकाएँ हैं।
एक दूसरी, चुपचाप लगने वाली कीमत भी है। रंग-तालिका की लंबाई दो की घात होनी चाहिए, इसलिए नौ रंग वाले फ़्रेम को भी सोलह की तालिका मिलती है और 130 रंग वाले को 256 की। कुछ हद तक ऊपर की ओर गोल करना टाला नहीं जा सकता। पर जिस फ़ाइल की तालिकाएँ पाँच हज़ार ऐसे रंग घोषित करती हों जिनका उसके पिक्सल कभी हवाला ही नहीं देते, वह अलग बात है: वे पैलेट किसी और तस्वीर के लिए बने थे, उस तस्वीर के लिए नहीं जो आखिर में फ़्रेम में पहुँची। एनालाइज़र बिना इस्तेमाल वाली प्रविष्टियों पर निशान लगा देता है, ताकि यह शक्ल एक नज़र में दिख जाए।
बाइट असल में जाते कहाँ हैं
GIF का हर बाइट गिनी-चुनी जगहों में से किसी एक में होता है, और यह तय करने से पहले कि फ़ाइल बहुत बड़ी है, यह जान लेना अच्छा है कि वे जगहें कौन-सी हैं।
- कंप्रेस किए हुए पिक्सल। स्वस्थ फ़ाइल में लगभग सब कुछ। तस्वीर खुद, LZW से गुज़री हुई — 1984 की एक कंप्रेशन योजना, जो स्प्रेडशीट के स्क्रीनशॉट के लिए बनी थी, और इसीलिए सपाट रंगों पर अच्छी और तस्वीरों पर खराब रहती है।
- रंग-तालिकाएँ। ऊपर की तरह, हर पूरी तालिका पर 768 बाइट।
- हर फ़्रेम के हेडर। हर फ़्रेम के लिए आठ बाइट समय के और ग्यारह बाइट विवरण के। सामान्य फ़ाइल में कुछ भी नहीं; दो हज़ार नन्हे फ़्रेमों के ऐनिमेशन में 38 KB।
- ब्लॉक की पैकिंग। कंप्रेस किया हुआ डेटा ज़्यादा से ज़्यादा 255 बाइट के टुकड़ों में काटा जाता है, और हर टुकड़े के आगे एक लंबाई-बाइट लगता है। हर 256 में लगभग एक बाइट, जिससे बचा नहीं जा सकता, और जिसे देख लेना अच्छा है क्योंकि वरना वह दिखता ही नहीं।
- मेटाडेटा। टिप्पणियाँ, कलर प्रोफ़ाइल और XMP पैकेट। सचमुच बेतुके नतीजे यही देता है: कोई इमेज एडिटर सालों पुरानी किसी एडिट का ब्योरा देती 40 KB की XML छोड़ सकता है, और छोटी GIF पर वही पूरी फ़ाइल का बड़ा हिस्सा होता है। कोई व्यूअर उसमें से कुछ भी नहीं बनाता।
इसे अंदाज़े से नहीं, तालिका की तरह देखने की वजह यह है कि जवाब हर फ़ाइल के लिए अलग होता है, और इलाज जवाब से ही निकलता है। जो फ़ाइल 95 % कंप्रेस किए पिक्सल है वह सीधे-सीधे बहुत सारी तस्वीर है, और वहाँ कम फ़्रेम, छोटा आकार या कम रंग ही काम आएँगे। जो फ़ाइल 30 % रंग-तालिकाएँ या 40 % XMP है, उसकी समस्या कहीं सस्ती है।
लूप इस फ़ॉर्मैट का हिस्सा है ही नहीं
GIF की स्पेसिफ़िकेशन में ऐसा कोई खाना नहीं है जो कहे कि ऐनिमेशन दोहराई जाएगी। लूप एक ऐसे ब्लॉक से आता है जो Netscape ने 1995 में गढ़ा था — एक “ऐप्लिकेशन एक्सटेंशन” जिसमें NETSCAPE2.0 लिखा होता है — जिसे सबने वैसे भी लागू कर लिया और जो आज इंटरनेट की हर चलती GIF में है।
यानी जिस फ़ाइल में वह ब्लॉक नहीं है, वह हर ब्राउज़र में ठीक एक बार चलकर रुक जाती है, और बनाने वाले को टूटी हुई लगती है। अगर कोई ऐनिमेशन सिर्फ़ एक बार चलकर रह जाती है, तो वही ब्लॉक गायब है; सबसे पहले जाँचने लायक चीज़ों में यह एक है, और किसी भी व्यूअर में यह दिखता नहीं।
ब्लॉक एक गिनती भी बता सकता है — पाँच बार चलाइए और रुक जाइए। शून्य का मतलब है हमेशा, और लगभग हर फ़ाइल यही कहती है।
GIF और क्या-क्या ढो सकती है
तीन ब्लॉक ऐसे हैं जिनमें कोई तस्वीर नहीं होती और जिन्हें हर व्यूअर छोड़ देता है:
- टिप्पणियाँ। खुला पाठ, आम तौर पर उस सॉफ़्टवेयर का नाम जिसने फ़ाइल लिखी, कभी-कभी कुछ ऐसा जिसे लेखक ने छापने के लिए नहीं चुना होता। इसे कोई दिखाता नहीं, और फ़ाइल की हर नकल इसे साथ ले जाती है।
- XMP। Adobe का XML मेटाडेटा: फ़ाइल को किसने संपादित किया, कब, और कभी-कभी किसने। यह अंत में 258 बाइट की एक जादुई पूँछ के साथ आता है, जो ब्लॉक की लंबाइयाँ सही बिठाने की तरकीब है, और इसीलिए सीधे-सादे तरीके से इसे पढ़ने पर स्क्रीन भर बाइनरी सामने आ जाती है।
- सादा पाठ। 1989 की स्पेसिफ़िकेशन का एक ब्लॉक, जो व्यूअर से कहता है कि तस्वीर के ऊपर खानों की जाली में लिखा हुआ पाठ बनाए। इसे किसी ने कभी लागू नहीं किया। अगर किसी फ़ाइल में यह हो, तो उसमें जो लिखा है वह दिखेगा नहीं।
फ़ाइल कहीं भेजने से पहले तीनों के बारे में जान लेना अच्छा है: ये GIF के वे हिस्से हैं जो आपके बारे में कुछ कह सकते हैं, और जब तक कोई जानबूझकर इन्हें हटाए नहीं, ये हर नकल और हर दोबारा अपलोड में बचे रहते हैं।
खराब हो चुकी फ़ाइल पढ़ना
GIF कट जाती हैं — बीच में रुका डाउनलोड, खराब होती डिस्क से बचाई गई फ़ाइल, कोई ऐसी चीज़ जिसका आधा हिस्सा ही किसी ऐप ने लिखा। चूँकि यह फ़ॉर्मैट एक अनुक्रमित ढाँचा नहीं बल्कि ब्लॉकों की धारा है, कटी हुई GIF आम तौर पर वहीं तक पढ़ी जा सकती है जहाँ तक वह गई है: टूटन से पहले का हर फ़्रेम पूरा और सही सलामत होता है।
यह जानना काम का है क्योंकि ज़्यादातर सॉफ़्टवेयर ऐसी फ़ाइल को बस मना कर देते हैं। जो एनालाइज़र जहाँ तक पढ़ सकता है पढ़ता है और बता देता है कि वह कहाँ रुका, वह कम-से-कम यह तो बता देगा कि कितना बचा है, और जो नहीं है वह एक फ़्रेम है या आखिरी दो सौ।
उलटी समस्या भी होती है: फ़ाइल के अंत के निशान के बाद बैठे हुए बाइट। हर डिकोडर उस निशान पर रुक जाता है, इसलिए वे कभी पढ़े नहीं जाते और कभी बनते नहीं, और आम तौर पर वे किसी गड़बड़ी में पहली फ़ाइल के पीछे जुड़ गई दूसरी फ़ाइल होते हैं। वे बस वज़न हैं, और उन्हें काट देने से कुछ नहीं जाता।
इनमें से किसी के लिए अपलोड की ज़रूरत नहीं
GIF का ढाँचा पढ़ना कोई भारी काम नहीं है — यह ब्लॉकों की सूची पर एक टहलना है और एक छोटा-सा डीकंप्रेसर — और इसे करने के लिए फ़ाइल को सर्वर पर भेजने की कोई तकनीकी वजह कभी रही ही नहीं। यहाँ का GIF एनालाइज़र पूरा काम पेज के भीतर करता है: ब्लॉकों पर टहलना, LZW, स्क्रीन पर बनते फ़्रेम, और बाइटों का हिसाब।
इस काम में यह बाकी ज़्यादातर कामों से भी ज़्यादा मायने रखता है, क्योंकि जिन फ़ाइलों को लोग सबसे ज़्यादा खोलकर देखना चाहते हैं, वही अक्सर वे होती हैं जिन्हें साझा करने में वे सबसे कम आश्वस्त होते हैं — कहीं से बचाई गई कोई चीज़, किसी की भेजी हुई कोई चीज़, ऐसी कोई चीज़ जिसमें टिप्पणी वाला ब्लॉक है और जिसे उन्होंने अभी पढ़ा नहीं। फ़ाइलें अपलोड करने पर वह लंबी बात यहाँ उतनी ही लागू होती है जितनी इस साइट पर कहीं और।