# ASCII art compression

The following challenge is basically a simpler version of the one proposed by Dennis (Lossy ASCII art compression). I found the idea super interesting but a bit too convulted, and seeing as it didn't seem to be getting much attention I decided to modify it a little bit.

You'll be downloading 5 ASCII art text files, each of them composed only of the following characters:

@#+';:,.


Each char represents a different brightness level (1-10 from @ to the whitespace).

Given a quality ratio q, which varies from 0.5 to 0.9 in 0.1 increments, your job is to output a compressed version of each ASCII file, while making those files able to decompress themselves.

That is to say, ImageX.txt is compressed by Program.py into CompImageX-xx.cpp (xx being the quality of the compressed image). Once CompImageX-xx.c is executed, a final decompressed image ImageX-xx.txt is created.

The .py and .c extensions are just an example, you can write the compressor and compressed images in any language that you want (doesn't have to be the same language for both, but you can't use different languages for different images).

The quality changes the image output in a relatively simple way. We'll call the array of usable chars Arr. Each char of ImageX becomes Arr[RoundHalfDown((Arr.Index(char)*q))], with the exception of the whitespace which remains the same no matter the quality.

RoundHalfDown(0.6) = RoundHalfDown(0.7) = RoundHalfDown(1) = 1

RoundHalfDown(0.5) = RoundHalfDown(0.4) = RoundHalfDown(0) = 0


For a short example:

 '#;@


at q=0.5 would become

 #@+@


You have to implement your own compressor, can't use any libraries that handle it for you.

Your score is the square root of the size of your compressor, multiplied by the sum of the size of all the compressed files --> sqrt(c)*sum(f). Lowest score wins.

USER                    LANGUAGE                    SCORE
Dennis                  CJam                        1046877

• If I'm correctly interpreting it, Arr[RoundHalfDown((Arr.Index(char)*q))] is hideous. With q=0.4 you're mapping 1 2 3 4 5 6 7 8 9 10 to 1 2 2 3 3 3 4 4 5 10. You would actually get a better quality reduction by mapping them to 1 1 4 4 4 7 7 7 10 10, which uses fewer output values but spaces them evenly across the brightness. Unless you're assuming a crazy gamma value in the input images? Jul 17, 2015 at 16:39
• Arrays are zero indexed. Jul 17, 2015 at 18:51

# CJam → CJam, score 1046877.4413

I'm not going to participate in my own challenge, but since this one doesn't contain its core part (figuring out the optimal transformation to make the original image more compressible), here I go:

q"@#+';:,. ":P9,easdf*.4f+:iPf=S+er_N/z,:L;N-__&W%:Pf#2f+e{(2b1>}%
e_P,2+b256b:cP":P,2+\256b\b{_2,#)_(@a?)+}%{(2-a\2b)*}%e_Pf="L"/N*"


The linefeed is for "readability" only.

It should be possible to improve the score by improving or simplifying the compression.

### Summary

e# Read the input and modify the palette according to the quality.

q"@#+';:,. ":P9,easdf*.4f+:iPf=S+er

e# Compute the line length and the unique characters of the palette.

_N/z,:L;N-__&W%:P

e# Replace each character by its index in the palette, plus two.

f#2f+

e# Perform run-length ecnoding, saving the runs using bijective base-2 numeration.
e# http://codegolf.stackexchange.com/a/53065

e{(2b1>}%

e# Convert from base length(palette)+2 to byte array (string).

e_P,2+b256b:c

e# Push the palette and the code for the decoder.

P":P,2+\256b\b{_2,#)_(@a?)+}%{(2-a\2b)*}%e_Pf="L"/N*"


### Score

$LANG=en_US$ for i in {1..5}; do for q in 0.{5..9}; do
> cjam comp.cjam $q < image$i.txt > image-$i-$q.cjam
> done; done
$wc -c comp.cjam 136 comp.cjam$ wc -c image*.cjam
2131 image-1-0.5.cjam
2248 image-1-0.6.cjam
2346 image-1-0.7.cjam
2350 image-1-0.8.cjam
2446 image-1-0.9.cjam
3006 image-2-0.5.cjam
3718 image-2-0.6.cjam
3894 image-2-0.7.cjam
3356 image-2-0.8.cjam
4064 image-2-0.9.cjam
2949 image-3-0.5.cjam
2947 image-3-0.6.cjam
3582 image-3-0.7.cjam
3784 image-3-0.8.cjam
3745 image-3-0.9.cjam
2879 image-4-0.5.cjam
2887 image-4-0.6.cjam
3379 image-4-0.7.cjam
3615 image-4-0.8.cjam
3537 image-4-0.9.cjam
4427 image-5-0.5.cjam
4802 image-5-0.6.cjam
5536 image-5-0.7.cjam
6030 image-5-0.8.cjam
6111 image-5-0.9.cjam
89769 total