title: Twitter image encoding challenge
body: <p><em>If a picture's worth 1000 words, how much of a picture can you fit in 140 characters?</em></p>
  
  <p><strong>Note</strong>: That's it folks! Bounty deadline is here, and after some tough deliberation, I have decided that <a href="https://stackoverflow.com/questions/891643/twitter-image-encoding-challenge/929360#929360">Boojum's entry</a> just barely edged out <a href="https://stackoverflow.com/questions/891643/twitter-image-encoding-challenge/904874#904874">Sam Hocevar's</a>. I will post more detailed notes once I've had a chance to write them up. Of course, everyone should feel free to continue to submit solutions and improve solutions for people to vote on. Thank you to everyone who submitted and entry; I enjoyed all of them. This has been a lot of fun for me to run, and I hope it's been fun for both the entrants and the spectators.</p>
  
  <p>I came across <a href="http://www.flickr.com/photos/quasimondo/3518306770/in/set-72057594062596732/" rel="nofollow noreferrer">this interesting post</a> about trying to compress images into a Twitter comment, and lots of people in that thread (and a <a href="http://www.reddit.com/r/programming/comments/8lwmw/guy_encodes_an_image_in_a_single_tweet140_chars/" rel="nofollow noreferrer">thread on Reddit</a>) had suggestions about different ways you could do it. So, I figure it would make a good coding challenge; let people put their money where their mouth is, and show how their ideas about encoding can lead to more detail in the limited space that you have available.</p>
  
  <p>I challenge you to come up with a general purpose system for encoding images into 140 character Twitter messages, and decoding them into an image again. You can use Unicode characters, so you get more than 8 bits per character. Even allowing for Unicode characters, however, you will need to compress images into a very small amount of space; this will certainly be a lossy compression, and so there will have to be subjective judgements about how good each result looks.</p>
  
  <p>Here is the result that the original author, <a href="http://www.flickr.com/photos/quasimondo/" rel="nofollow noreferrer">Quasimondo</a>, got from his encoding (image is licensed under a <a href="http://creativecommons.org/licenses/by-nc/2.0/deed.en" rel="nofollow noreferrer">Creative Commons Attribution-Noncommercial license</a>):
  <img src="https://farm4.static.flickr.com/3346/3518306770_1de2bc2970.jpg?v=0" alt="Mona Lisa"></p>
  
  <p>Can you do better?</p>
  
  <h3>Rules</h3>
  
  <ol>
  <li>Your program must have two modes: <strong>encoding</strong> and <strong>decoding</strong>.</li>
  <li>When <strong>encoding</strong>:
  
  <ol>
  <li>Your program must take as input a graphic in any reasonable <strong>raster</strong> graphic format of your choice. We'll say that any raster format supported by <a href="http://www.imagemagick.org/script/formats.php" rel="nofollow noreferrer">ImageMagick</a> counts as reasonable.</li>
  <li>Your program must output a message which can be represented in 140 or fewer Unicode code points; 140 code points in the range <code>U+0000</code>–<code>U+10FFFF</code>, excluding non-characters (<code>U+FFFE</code>, <code>U+FFFF</code>, <code>U+</code><em>n</em><code>FFFE</code>, <code>U+</code><em>n</em><code>FFFF</code> where <em>n</em> is <code>1</code>–<code>10</code> hexadecimal, and the range <code>U+FDD0</code>–<code>U+FDEF</code>) and surrogate code points (<code>U+D800</code>–<code>U+DFFF</code>). It may be output in any reasonable encoding of your choice; any encoding supported by <a href="http://www.gnu.org/software/libiconv/" rel="nofollow noreferrer">GNU <code>iconv</code></a> will be considered reasonable, and your platform native encoding or locale encoding would likely be a good choice. See <strong>Unicode notes</strong> below for more details.</li>
  </ol></li>
  <li>When <strong>decoding</strong>:
  
  <ol>
  <li>Your program should take as input the output of your <strong>encoding</strong> mode.</li>
  <li>Your program must output an image in any reasonable format of your choice, as defined above, though for output vector formats are OK as well.</li>
  <li>The image output should be an approximation of the input image; the closer you can get to the input image, the better.</li>
  <li>The decoding process may have no access to any other output of the encoding process other than the output specified above; that is, you can't upload the image somewhere and output the URL for the decoding process to download, or anything silly like that.</li>
  </ol></li>
  <li><p>For the sake of consistency in user interface, your program must behave as follows:</p>
  
  <ol>
  <li>Your program must be a script that can be set to executable on a platform with the appropriate interpreter, or a program that can be compiled into an executable.</li>
  <li>Your program must take as its first argument either <code>encode</code> or <code>decode</code> to set the mode.</li>
  <li><p>Your program must take input in one or more of the following ways (if you implement the one that takes file names, you may also read and write from stdin and stdout if file names are missing):</p>
  
  <ol>
  <li><p>Take input from standard in and produce output on standard out.</p>
  
  <pre><code>my-program encode &lt;input.png &gt;output.txt
  my-program decode &lt;output.txt &gt;output.png
  </code></pre></li>
  <li><p>Take input from a file named in the second argument, and produce output in the file named in the third.</p>
  
  <pre><code>my-program encode input.png output.txt
  my-program decode output.txt output.png
  </code></pre></li>
  </ol></li>
  </ol></li>
  <li>For your solution, please post:
  
  <ol>
  <li>Your code, in full, and/or a link to it hosted elsewhere (if it's very long, or requires many files to compile, or something).</li>
  <li>An explanation of how it works, if it's not immediately obvious from the code or if the code is long and people will be interested in a summary.</li>
  <li>An example image, with the original image, the text it compresses down to, and the decoded image.</li>
  <li>If you are building on an idea that someone else had, please attribute them. It's OK to try to do a refinement of someone else's idea, but you <strong>must</strong> attribute them.</li>
  </ol></li>
  </ol>
  
  <h3>Guidelines</h3>
  
  <p>These are basically rules that may be broken, suggestions, or scoring criteria:</p>
  
  <ol>
  <li>Aesthetics are important. I'll be judging, and suggest that other people judge, based on:
  
  <ol>
  <li>How good the output image looks, and how much it looks like the original.</li>
  <li>How nice the text looks. Completely random gobbledigook is OK if you have a really clever compression scheme, but I also want to see answers that turn images into mutli-lingual poems, or something clever like that. Note that the author of the original solution decided to use only Chinese characters, since it looked nicer that way.</li>
  <li>Interesting code and clever algorithms are always good. I like short, to the point, and clear code, but really clever complicated algorithms are OK too as long as they produce good results.</li>
  </ol></li>
  <li>Speed is also important, though not as important as how good a job compressing the image you do. I'd rather have a program that can convert an image in a tenth of a second than something that will be running genetic algorithms for days on end.</li>
  <li>I will prefer shorter solutions to longer ones, as long as they are reasonably comparable in quality; conciseness is a virtue.</li>
  <li>Your program should be implemented in a language that has a freely-available implementation on Mac OS X, Linux, or Windows. I'd like to be able to run the programs, but if you have a great solution that only runs under <a href="http://en.wikipedia.org/wiki/MATLAB" rel="nofollow noreferrer">MATLAB</a> or something, that's fine.</li>
  <li>Your program should be as general as possible; it should work for as many different images as possible, though some may produce better results than others. In particular:
  
  <ol>
  <li>Having a few images built into the program that it matches and writes a reference to, and then produces the matching image upon decoding, is fairly lame and will only cover a few images.</li>
  <li>A program that can take images of simple, flat, geometric shapes and decompose them into some vector primitive is pretty nifty, but if it fails on images beyond a certain complexity it is probably insufficiently general.</li>
  <li>A program that can only take images of a particular fixed aspect ratio but does a good job with them would also be OK, but not ideal.</li>
  <li>You may find that a black and white image can get more information into a smaller space than a color image. On the other hand, that may limit the types of image it's applicable to; faces come out fine in black and white, but abstract designs may not fare so well.</li>
  <li>It is perfectly fine if the output image is smaller than the input, while being roughly the same proportion. It's OK if you have to scale the image up to compare it to the original; what's important is how it looks.</li>
  </ol></li>
  <li>Your program should produce output that could actually go through Twitter and come out unscathed. This is only a guideline rather than a rule, since I couldn't find any documentation on the precise set of characters supported, but you should probably avoid control characters, funky invisible combining characters, private use characters, and the like.</li>
  </ol>
  
  <h3>Scoring rubric</h3>
  
  <p>As a general guide to how I will be ranking solutions when choosing my accepted solution, lets say that I'll probably be evaluating solutions on a 25 point scale (this is very rough, and I won't be scoring anything directly, just using this as a basic guideline):</p>
  
  <ul>
  <li><strong>15 points</strong> for how well the encoding scheme reproduces a wide range of input images. This is a subjective, aesthetic judgement
  
  <ul>
  <li>0 means that it doesn't work at all, it gives the same image back every time, or something</li>
  <li>5 means that it can encode a few images, though the decoded version looks ugly and it may not work at all on more complicated images</li>
  <li>10 means that it works on a wide range of images, and produces pleasant looking images which may occasionally be distinguishable</li>
  <li>15 means that it produces perfect replicas of some images, and even for larger and more complex images, gives something that is recognizable. Or, perhaps it does not make images that are quite recognizable, but produces beautiful images that are clearly derived from the original.</li>
  </ul></li>
  <li><strong>3 points</strong> for clever use of the Unicode character set
  
  <ul>
  <li>0 points for simply using the entire set of allowed characters</li>
  <li>1 point for using a limited set of characters that are safe for transfer over Twitter or in a wider variety of situations</li>
  <li>2 points for using a thematic subset of characters, such as only Han ideographs or only right-to-left characters</li>
  <li>3 points for doing something really neat, like generating readable text or using characters that look like the image in question</li>
  </ul></li>
  <li><strong>3 points</strong> for clever algorithmic approaches and code style
  
  <ul>
  <li>0 points for something that is 1000 lines of code only to scale the image down, treat it as 1 bit per pixel, and base64 encode that</li>
  <li>1 point for something that uses a standard encoding technique and is well written and brief</li>
  <li>2 points for something that introduces a relatively novel encoding technique, or that is surprisingly short and clean</li>
  <li>3 points for a one liner that actually produces good results, or something that breaks new ground in graphics encoding (if this seems like a low number of points for breaking new ground, remember that a result this good will likely have a high score for aesthetics as well)</li>
  </ul></li>
  <li><strong>2 points</strong> for speed. All else being equal, faster is better, but the above criteria are all more important than speed</li>
  <li><strong>1 point</strong> for running on free (open source) software, because I prefer free software (note that C# will still be eligible for this point as long as it runs on Mono, likewise MATLAB code would be eligible if it runs on GNU Octave)</li>
  <li><strong>1 point</strong> for actually following all of the rules. These rules have gotten a bit big and complicated, so I'll probably accept otherwise good answers that get one small detail wrong, but I will give an extra point to any solution that does actually follow all of the rules</li>
  </ul>
  
  <h3>Reference images</h3>
  
  <p>Some folks have asked for some reference images. Here are a few reference images that you can try; smaller versions are embedded here, they all link to larger versions of the image if you need those:</p>
  
  <p><a href="http://www.cs.cmu.edu/~chuck/lennapg/lena_std.tif" rel="nofollow noreferrer"><img src="https://ephemera.continuation.org/stackoverflow/challenge/lena.png" alt="Lena" title="Lena"></a>
  <a href="http://upload.wikimedia.org/wikipedia/commons/6/6a/Mona_Lisa.jpg" rel="nofollow noreferrer"><img src="https://ephemera.continuation.org/stackoverflow/challenge/mona-lisa.png" alt="Mona Lisa" title="Mona Lisa"></a>
  <a href="http://upload.wikimedia.org/wikipedia/commons/2/24/Cornell_box.png" rel="nofollow noreferrer"><img src="https://ephemera.continuation.org/stackoverflow/challenge/cornell-box.png" alt="Cornell Box" title="Cornell Box"></a>
  <a href="http://ephemera.continuation.org/stackoverflow/challenge/so-logo.png" rel="nofollow noreferrer"><img src="https://ephemera.continuation.org/stackoverflow/challenge/so-logo-small.png" alt="StackOverflow Logo" title="StackOverflow logo"></a></p>
  
  <h3>Prize</h3>
  
  <p>I am offering a <strong>500 rep bounty</strong> (plus the 50 that StackOverflow kicks in) for the solution that I like the best, based on the above criteria. Of course, I encourage everyone else to vote on their favorite solutions here as well.</p>
  
  <h3>Note on deadline</h3>
  
  <p>This contest will run until the bounty runs out, about 6 PM on Saturday, May 30. I can't say the precise time it will end; it may be anywhere from 5 to 7 PM. I will guarantee that I'll look at all entries submitted by 2 PM, and I will do my best to look at all entries submitted by 4 PM; if solutions are submitted after that, I may not have a chance to give them a fair look before I have to make my decision. Also, the earlier you submit, the more chance you will have for voting to be able to help me pick the best solution, so try and submit earlier rather than right at the deadline.</p>
  
  <h3>Unicode notes</h3>
  
  <p>There has also been some confusion on exactly what Unicode characters are allowed. The range of possible Unicode code points is <code>U+0000</code> to <code>U+10FFFF</code>. There are some code points which are never valid to use as Unicode characters in any open interchange of data; these are the <strong>noncharacters</strong> and the <strong>surrogate code points</strong>. Noncharacters are defined in the <a href="http://www.unicode.org/versions/Unicode5.0.0/ch16.pdf" rel="nofollow noreferrer">Unidode Standard 5.1.0 section 16.7</a> as the values <code>U+FFFE</code>, <code>U+FFFF</code>, <code>U+</code><em>n</em><code>FFFE</code>, <code>U+</code><em>n</em><code>FFFF</code> where <em>n</em> is <code>1</code>–<code>10</code> hexadecimal, and the range <code>U+FDD0</code>–<code>U+FDEF</code>. These values are intended to be used for application-specific internal usage, and conforming applications may strip these characters out of text processed by them. Surrogate code points, defined in the <a href="http://www.unicode.org/versions/Unicode5.0.0/ch03.pdf" rel="nofollow noreferrer">Unicode Standard 5.1.0 section 3.8</a> as <code>U+D800</code>–<code>U+DFFF</code>, are used for encoding characters beyond the Basic Multilingual Plane in UTF-16; thus, it is impossible to represent these code points directly in the UTF-16 encoding, and it is invalid to encode them in any other encoding. Thus, for the purpose of this contest, I will allow any program which encodes images into a sequence of no more than 140 Unicode code points from the range <code>U+0000</code>–<code>U+10FFFF</code>, excluding all noncharacters and surrogate pairs as defined above.</p>
  
  <p>I will <em>prefer</em> solutions that use only assigned characters, and even better ones that use clever subsets of assigned characters or do something interesting with the character set they use. For a list of assigned characters, see the <a href="http://unicode.org/Public/UNIDATA/UnicodeData.txt" rel="nofollow noreferrer">Unicode Character Database</a>; note that some characters are listed directly, while some are listed only as the start and end of a range. Also note that surrogate code points are listed in the database, but forbidden as mentioned above. If you would like to take advantage of certain properties of characters for making the text you output more interesting, there are a <a href="http://unicode.org/Public/UNIDATA/" rel="nofollow noreferrer">variety of databases of character information</a> available, such as a <a href="http://unicode.org/Public/UNIDATA/Blocks.txt" rel="nofollow noreferrer">list of named code blocks</a> and <a href="http://unicode.org/Public/UNIDATA/PropList.txt" rel="nofollow noreferrer">various character properties</a>.</p>
  
  <p>Since Twitter does not specify the exact character set they support, I will be lenient about solutions which do not actually work with Twitter because certain characters count extra or certain characters are stripped. It is preferred but not required that all encoded outputs should be able to be transferred unharmed via Twitter or another microblogging service such as <a href="http://identi.ca/" rel="nofollow noreferrer">identi.ca</a>. I have seen some documentation stating that Twitter entity-encodes &lt;, &gt;, and &amp;, and thus counts those as 4, 4, and 5 characters respectively, but I have not tested that out myself, and their JavaScript character counter doesn't seem to count them that way.</p>
  
  <h3>Tips &amp; Links</h3>
  
  <ul>
  <li>The definition of valid Unicode characters in the rules is a bit complicated. Choosing a single block of characters, such as CJK Unified Ideographs (U+4E00–U+9FCF) may be easier.</li>
  <li>You may use existing image libraries, like <a href="http://www.imagemagick.org/" rel="nofollow noreferrer">ImageMagick</a> or <a href="http://www.pythonware.com/products/pil/" rel="nofollow noreferrer">Python Imaging Library</a>, for your image manipulation.</li>
  <li>If you need some help understanding the Unicode character set and its various encodings, see <a href="http://www.azillionmonkeys.com/qed/unicode.html" rel="nofollow noreferrer">this quick guide</a> or <a href="http://www.cl.cam.ac.uk/~mgk25/unicode.html" rel="nofollow noreferrer">this detailed FAQ on UTF-8 in Linux and Unix</a>.</li>
  <li>The earlier you get your solution in, the more time I (and other people voting) will have to look at it. You can edit your solution if you improve it; I'll base my bounty on the most recent version when I take my last look through the solutions.</li>
  <li>If you want an easy image format to parse and write (and don't want to just use an existing format), I'd suggest using the <a href="http://en.wikipedia.org/wiki/Netpbm_format" rel="nofollow noreferrer">PPM format</a>. It's a text based format that's very easy to work with, and you can use <a href="http://www.imagemagick.org/" rel="nofollow noreferrer">ImageMagick</a> to convert to and from it.</li>
  </ul>