GIF एनकोडर लिखें


9

हाँ, अच्छा पुराने GIF। अपनी बहुमुखी प्रतिभा के लिए पसंद किया, अपने पेटेंट के लिए नफरत और आंशिक रूप से अपनी सीमाओं (और पेटेंट) के कारण obifleted, GIF होते हैं, रंग पैलेट के कोर पर, और पैलेट-अनुक्रमित छवि LZZ एल्गोरिथ्म का उपयोग कर संकुचित।

आपका कार्य एक प्रोग्राम लिखना है जो मानक इनपुट से एएससीआईआई पीपीएम प्रारूप ("पी 3" मैजिक नंबर) में एक छवि पढ़ता है , और जीआईएफ प्रारूप में समान छवि (समान पिक्सेल-बाय-पिक्सेल) को मानक आउटपुट में लिखता है। आउटपुट या तो बाइनरी फॉर्म में हो सकता है, या एएससीआईआई पाठ प्रत्येक बाइट के साथ 0 और 255 (समावेशी) के बीच एक संख्या द्वारा दर्शाया जाता है, जिसे व्हाट्सएप द्वारा अलग किया जाता है।

इनपुट छवि को 256 से अधिक विभिन्न रंगों के नहीं होने की गारंटी है।

स्कोरिंग:

आपके कार्यक्रम को 3 नमूना चित्रों पर परीक्षण किया जाएगा, और आपके स्कोर की गणना इस प्रकार की जाएगी:
कार्यक्रम का आकार + योग (आउटपुट आकार - प्रत्येक नमूना छवि के लिए संदर्भ आकार)
सबसे कम स्कोर जीतता है।

आवश्यकताएँ:

  • आपके कार्यक्रम को विभिन्न आकारों की किसी भी प्रकार की छवियों के साथ काम करना चाहिए, और नमूना छवियों तक सीमित नहीं होना चाहिए। उदाहरण के लिए, आप आयामों को 2 के गुणक होने के लिए सीमित कर सकते हैं या मान सकते हैं कि पीपीएम अधिकतम रंग 255 है, लेकिन यह अभी भी इनपुट छवियों की एक विस्तृत विविधता के साथ काम करना चाहिए।
  • आउटपुट एक वैध जीआईएफ फ़ाइल होनी चाहिए जिसे किसी भी आज्ञाकारी कार्यक्रम के साथ लोड किया जा सकता है (एएससीआईआई आउटपुट विकल्प का उपयोग करने पर बाइनरी में वापस कनवर्ट करने के बाद)।
  • आप किसी भी इमेज प्रोसेसिंग फ़ंक्शंस (बिल्ट-इन या थर्ड-पार्टी) का उपयोग नहीं कर सकते, आपके प्रोग्राम में सभी प्रासंगिक कोड होने चाहिए।
  • आपका प्रोग्राम लिनक्स में स्वतंत्र रूप से उपलब्ध सॉफ्टवेयर का उपयोग करके चलाने योग्य होना चाहिए।
  • स्रोत कोड को केवल ASCII वर्णों का उपयोग करना चाहिए।

नमूना चित्र:

यहां 3 नमूना चित्र दिए गए हैं जो स्कोरिंग के लिए उपयोग किए जाएंगे। आप पीपीएम फ़ाइलों के साथ एक ज़िप संग्रह डाउनलोड कर सकते हैं (उस पृष्ठ के शीर्ष पर डाउनलोड बटन का उपयोग करें)। या आप उन्हें नीचे दिए गए png चित्रों से परिवर्तित कर सकते हैं, निम्नलिखित कमांड के साथ ImageMagick का उपयोग कर सकते हैं:

convert file.png -compress none file.ppm

मैं पुष्टि के लिए पीपीएम फाइलों के एमडी 5 चेकसम भी प्रदान कर रहा हूं।

1. अम्बर

amber.png

संदर्भ का आकार: 38055
एमडी 5 पीपीएम का चेकसम: d1ad863cb556869332074717272780

2. नीलापन

blueeyes.png

संदर्भ का आकार: 28638
एमडी 5 पीपीएम का चेकसम: e9ad410057a5f6c25a22a534259dcf3a

3. मिर्च

peppers.png

संदर्भ का आकार: 53586
एमडी 5 पीपीएम का चेकसम: 74112dbbb8b7de5216f9e24c2e1a627


1
मॉडरेटर नोट: हटाए गए विषय / अप्रचलित टिप्पणियां। कृपया इस प्रश्न में नमूना चित्रों पर चर्चा के लिए मेटा देखें
दरवाज़े

ऐसा लगता है कि दूसरी छवि को इस तरह से व्यवहार किया गया था: websiteoptimization.com/speed/tweak/lossy जो बेहतर संपीड़न अनुपात की व्याख्या करेगा और LZW एनकोडर tweaks के प्रति संवेदनशीलता होगी।
नटकी

1
"स्रोत कोड को केवल ASCII वर्णों का उपयोग करना चाहिए।" - इसलिए, दूसरे शब्दों में, हमें एपीएल में इस चुनौती को करने की अनुमति नहीं है?
फ़ूजज़नल

@FUZxxl सच है, लेकिन आप J. का उपयोग कर सकते हैं। आपको Aheui का उपयोग करने या GolfScript / CJam में आधार रूपांतरण ट्रिक करने की भी अनुमति नहीं है।
एडित्सो ने छोड़ दिया क्योंकि एसई

जवाबों:


4

पर्ल, 515 + -2922 + 0 + -2571 = -4978

एक और दृष्टिकोण। इस बार मैं 64xH आकार की टाइल में छवि को बचाने की कोशिश कर रहा हूं। यह चश्मा के अनुसार ठीक है, लेकिन कुछ सॉफ्टवेयर केवल पहली टाइल या एक एनीमेशन दिखा सकते हैं। बेहतर स्थानिक इलाके के कारण टाइलें बेहतर संपीड़ित होती हैं। मैं अभी भी दूसरी छवि के लिए सामान्य संपीड़न करता हूं और जो भी कम आया उसे चुनें। चूंकि यह छवि को दो बार संकुचित करता है, यह मेरे पिछले समाधान की तुलना में दोगुना है।

#!perl -n0
sub r{$r.=1&"@_">>$_ for 0..log(@d|256)/log 2}
@k=/(\d+) (\d+)/;
@l=map{$$_||=(push(@t,split$"),++$i)}/\d+ \d+ \d+/g;
print+GIF89a,pack(vvCxxC768,@k,~8,@t);
sub v{($w,$h)=@_;for$k(0.."@k"/$w-1){
$k*=$w;$r='';@d=();@p=grep+($z++-$k)%"@k"<$w,@l;
$"=' ';$_="@p ";$"='|';while(/./){
r 256;%d=map{($_,$_-1)}@d=1..256;
$d{$&}=@d+2,r$d{$1},unshift@d,$&while@d<4095&&s/^(@d) (\d*)/$2/}
r 257;$_=pack"b*",$r;
$h.=pack"Cv4n(C/a)*",44,$k,0,$w,$k[1],8,/.{0,255}/gs
}$b=$h if!$b||length$b>length$h}
"@k"%64||v 64;v"@k";print"$b;"

पर्ल, 354 + 12 + 0 + -1 = 365 418 9521 51168 56639

या तो मेरे कोड में कुछ बग है या दूसरी छवि एक विशिष्ट एनकोडर के लिए अनुकूलित है क्योंकि प्रतीत होता है कि महत्वहीन परिवर्तन ने आकार को संदर्भ में बिल्कुल कम कर दिया। प्रति छवि लगभग 30s-60s लेता है।

गोल्फ संस्करण।

#!perl -n0
sub r{$r.=1&"@_">>$_ for 0..log(@d|256)/log 2}
@k=/(\d+) (\d+)/;
@p=map{$$_||=(push(@t,split$"),++$i)}/\d+ \d+ \d+/g;
$_="@p ";$"='|';while(/./){
r 256;%d=map{($_,$_-1)}@d=1..256;
$d{$&}=@d+2,r$d{$1},unshift@d,$&while@d<4095&&s/^(@d) (\d*)/$2/}
r 257;$_=pack"b*",$r;
print+GIF89a,pack(vvCxxC768,@k,~8,@t),
pack("Cx4vvn(C/a)*",44,@k,8,/.{0,255}/gs),';'

जीआईएफ कंप्रेसर को रीसेट करने का एकमात्र निर्णय जीआईएफ कंप्रेसर ही ले सकता है। सामान्य तौर पर इस कार्य के लिए छवियों को सबसे अच्छा क्षण कैसे चुना जाता है ऐसा करने के लिए प्रत्येक 4096 कोड है जो कि उस पल है जब शब्दकोश अतिप्रवाह होगा। इस तरह की सीमा के साथ शब्दकोश कभी भी ज़रूरत से ज़्यादा नहीं होता है जो कार्यान्वयन में कुछ बाइट्स बचाता है। यह इस तरह से विस्तार से काम करता है:

#!perl -n0
# function to add one codeword to the output stream @r.
# the current codeword length is based on the dictionary size/
sub r{push@r,map"@_">>$_,0..log(@d|256)/log 2}
# get the dimensions into @k
@k=/(\d+) (\d+)/;
# get pixel indexes to @p and palette to @t
@p=map{$$_||=(push(@t,split$"),++$i)}/\d+ \d+ \d+/g;
# convert index table into space separated string 
$_="@p ";$"='|';
# LZW encoder; while something to encode
while(/\S/){
# output reset code
r 256;
# reset code dictionary $d is the last code number,
# %d is the map of codes and @d list of codes
$d=257;%d=map{($_,$_-1)}@d=1..256;
# find codes using regexp, stop at dictionary overflow
while($d<4096&&s/^(@d) (\d*)/$2/){
unshift@d,$&;$d{$&}=++$d;r$d{$1}}}
# end LZW encoder; output end code
r 257;
# convert bit string @r to bytes $f
vec($f,$j++,1)=$_ for@r;
# output header up to the color table
print+GIF89a,pack(vvCvC768,@k,~8,0,@t),
# output rest of the header
pack(Cv4CC,44,0,0,@k,0,8),
# output the LZW compressed data $f slicing into sub-blocks
$f=~s/.{0,255}/chr(length$&).$&/egsr,';'

पर्ल, 394 + -8 + 0 + -12 = 374

रीसेट बिंदु का अनुमान लगाने के लिए एक अनुमान को जोड़ने से संपीड़न में थोड़ा सुधार होता है लेकिन अतिरिक्त कोड को सही ठहराने के लिए पर्याप्त नहीं है:

#!perl -n0
sub r{$r.=1&"@_">>$_ for 0..log(@d|256)/log 2}
@k=/(\d+) (\d+)/;
@p=map{$$_||=(push(@t,split$"),++$i)}/\d+ \d+ \d+/g;
$_="@p ";$"='|';while(/./){
r 256;%d=map{($_,$_-1)}@d=1..256;
$d{$&}=@d+2,r$d{$1},unshift@d,$&while
(@d<4001||(/((@d) ){11}/,$&=~y/ //>12))&@d<4095&&s/^(@d) (\d*)/$2/}
r 257;$_=pack"b*",$r;
print+GIF89a,pack(vvCxxC768,@k,~8,@t),
pack("Cx4vvn(C/a)*",44,@k,8,/.{0,255}/gs),';'

बहुत अच्छा! हालांकि यहां प्रति छवि 30 से अधिक बार लगती है। मैं पिछले संस्करण से -30 से काफी प्रभावित था, मुझे आश्चर्य है कि क्या आप विधियों को जोड़ सकते हैं और कम स्कोर प्राप्त कर सकते हैं। इसके अलावा, क्या आप इस बारे में थोड़ा लिख ​​सकते हैं कि कार्यक्रम क्या करता है?
एडित्सू ने छोड़ दिया क्योंकि SE EVIL

64 की एक बहु होने के लिए चौड़ाई की आवश्यकता थोड़ी अधिक लगती है ...
विज्ञापन छोड़ दें क्योंकि SE EVIL

@aditsu, इसकी आवश्यकता नहीं है, यदि चौड़ाई 64 से अधिक नहीं है, तो टाइलिंग विधि की कोशिश नहीं की जाती है और नियमित संपीड़न का उपयोग किया जाता है। बेशक एक और ~ 100 वर्णों की लागत पर मैं अंतिम टाइल चर आकार बना सकता था।
नटकी

बहुत धीमी गति से, और टाइल की गई छवियां एनिमेशन के रूप में दिखाती हैं, लेकिन .. अच्छी तरह से किया, यह देखने के लिए काफी प्रभावशाली है कि आप वास्तव में उन्हें छोटा बना सकते हैं।
एडिट्स ने छोड़ दिया क्योंकि SE

2

सीजाम, स्कोर 155 + 35306 + 44723 + 21518 = 101702

बस एक गूंगा संदर्भ कार्यान्वयन। यह धीमा है, कोई वास्तविक संपीड़न नहीं करता है और यह गोल्फ नहीं है।

"GIF89a":iS*SqN/S*S%1>:i3/:M0=2<256f{md\}S*:ZS247S0S0SM1>_|:PL*_,768\m0a*+S*S44S0S0S0S0SZS0S8SM1>Pf{\a#}254/256a*{512+2b1>W%}%:+8/{W%2b}%255/{_,S@S*S}/0S59
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.