Python 2.7 - 10971 8077 bytes
update:
LZMA actually for some reason doesn't work for me, so I went back to Deflate.
I found an online tool to compress the PNG even further (they say they use lossy compression, but the array remains unchanged)
- I golfed the
__main__.py
script a bit more...
- I found I was omitting a step (extracting the data files from zip archive)
- Added DL link (see bottom)
Most compression algorithms look at data as a 1 dimensional array, and therefore cannot capture the repeating 2 dimensional characters displayed in the cosmic call (IMO also makes it harder for aliens to understand too :P).
First, I selected each character as a 7*5 array and made a list of all unique characters (101 if I recall). Then I iterated over the image, and when a character was found, the position and index of that character (in the character list) were recorded.
Those positions could be represented with a single int, however with over 2K chars found, and positions ranging from 0-370966 (divmod form) require up to 3 bytes each. I collected the character positions in order however, so I instead converted absolute position to offset position, making most of the numbers less than 1 byte. I encoded this list in utf-8 to account for the few numbers that were greater than 1 byte
After recording and removing all the matched characters, I saved the png with maximum compression. I then packaged the python reconstruction script (reverse same process), the png, the chatacter template, and the character position list all into a zip file to take advantage of the fact that python can take a folder or zip file as an argument, and it will begin execution at any file in the top level named __main__.py
. I played around with 7z a bit to get the best compression, which turned out to be LZMA with a 1M dict and 32bit words.
here's the decoder script (golfed but with comments still)
import sys,zipfile as z
z.ZipFile(sys.argv[0]).extractall() #extract data files from zip to cwd
from numpy import*
o=open #next line overwrites open, which I need
from PIL.Image import*
from scipy.ndimage import*
a=imread('p')[:,:,0]/255 #read image file
a[:2414,0]=0 #draw vertical borders
a[2541:,0]=0
a[2412:,-1]=0
a[:2287,-1]=0
for x in range(0,2921,127):a[[x,x+126],:]=0 #draw horizontal borders
with o('c','rb') as f:t=f.read();C=[int(i)for c in t for i in'{0:08b}'.format(ord(c))] #read character template file and convert to list of bytes
C=array(C[:-1]).reshape([101,7,5]) #re-slice (extra 0 appended to make even number of bytes) and re-shape
with o('l','rb') as f:L=array([ord(x)for x in f.read().decode('utf_8')]).reshape([2158,2]) #read decode and reshape positional list
p=0 #relative position accumulator
for e in L:p+=e[0];x,y=p%127,p/127;a[y:y+7,x:x+5]=C[e[1]] #divmod for x,y position and paste character template onto array at position
i=fromarray(a*255)
i.show()
link to download for the zip file...
19“It is allowed to write many programs (like, one for each page) and sum their size to determine your score.” This is dangerous: the empty Jelly program prints
0
, the empty Snails program prints1
, and the empty GolfScript program prints a newline. Someone might submit a 0-byte, 373888-program answer :) – Lynn – 2016-06-13T14:20:08.857Haha, okay, so I'll limit the number of programs to 23. – xem – 2016-06-13T14:29:28.010
Are trailing newlines / spaces permitted? – Loovjo – 2016-06-13T16:12:50.223
yep . . . . . . – xem – 2016-06-13T16:49:30.090
Can we use another file or do we have to work solely on the source file ? Eg. can I use IO to store a compressed version and then decompress it or does everything need to be a literal in the code. – HopefullyHelpful – 2016-06-17T04:34:29.177
you can count external files size in your score :) – xem – 2016-06-17T08:48:58.490