{"id":274,"date":"2015-03-09T03:30:35","date_gmt":"2015-03-09T01:30:35","guid":{"rendered":"http:\/\/blog.teleranek.org\/?p=274"},"modified":"2025-06-29T12:29:13","modified_gmt":"2025-06-29T10:29:13","slug":"flower-fractals-super-squished-edition","status":"publish","type":"post","link":"https:\/\/blog.teleranek.org\/?p=274","title":{"rendered":"Flower fractals super squished edition"},"content":{"rendered":"<p>Recently I stumbled upon a challenge on challengepost.com &#8211; &#8220;20 lines of JavaScript&#8221;. The goal was to write a 20 line JS\u00a0code that does something that can make the challenge judges vote for you. I thought the best idea would be to\u00a0treat this challenge\u00a0like a good ol&#8217; demoscene compo. I&#8217;ve already had a good effect &#8211; the <a href=\"http:\/\/blog.teleranek.org\/?p=177\" target=\"_blank\" rel=\"noopener noreferrer\">flower fractals<\/a>. Unfortunately, after porting it to JavaScript it was\u00a0<a title=\"11 kilobytes\" href=\"http:\/\/blog.teleranek.org\/wp-content\/uploads\/2015\/03\/foil-g.html\" target=\"_blank\" rel=\"noopener noreferrer\">11 KB<\/a>ytes\u00a0:( and 383 lines of code, not always shorter than the required 80 chars (or maybe even more, but I don&#8217;t remember where I put the first version).\u00a0I used <a href=\"http:\/\/www.pixijs.com\" target=\"_blank\" rel=\"noopener noreferrer\">PIXI<\/a>, great 2D javascript library because it uses several enhancements for JS canvas (it also supports WebGL, but WebGL isn&#8217;t really a vector-like\u00a0drawing thing, the lines are aliased and poor quality, to obtain better quality I&#8217;d need to use textures and stuff, I thought it would be too complicated for 20 lines of code).<\/p>\n<p>OK, so I&#8217;ve got 383 lines and 11 kilobytes. As we all know, 20 lines of 80 char code is 1600 bytes, so there&#8217;s way to go&#8230; I checked with google closure compiler, how I could squish that &#8211; after compressing, it was about 5 kilos. Still too much. After hours of merging functions, deleting smooth line bezier-based rendering, reusing some vars, it went down to about 3 kilos.<\/p>\n<p>I started to think that its impossible to do, unless some miracle happens.<\/p>\n<p>Then I stumbled upon this great method of utilising somehow buggy behaviour of browsers &#8211; treating PNG files like HTML, when compressed PNG data resembles HTML data. After changing the JS to one big eval(&#8230;) function and compressing it to PNG I went down to 1600 bytes. Well, exactly 1595. Changing some things inside eval and making the code larger allowed PNG to compress it enough. So there&#8217;s this curiosity &#8211; PNG JavaScript:\u00a0<a href=\"http:\/\/blog.teleranek.org\/wp-content\/uploads\/2015\/03\/1600BYTES.html\">1600BYTES<\/a><\/p>\n<p>This was of course no-go, because it wasn&#8217;t really javascript &#8211; it was png, and I it would be really really hard to intoduce line breaks inside zipped\u00a0binary data. Also, it&#8217;s very ugly, you can see some errors appearing when running this code &#8211; some PNG IHDR data is displayed for a short period of time. I had to come up with something else. But how to squish the code better than the zip algorithm itself?<\/p>\n<p>Then I had a moment of enlightning &#8211; it&#8217;s 20 lines of 80 characters challenge, not 1600 bytes challenge. How about UTF-16? I could write 2 bytes inside 1 UTF16 character.<\/p>\n<p>It worked! Excited, I searched on google if anyone else did it &#8211; of course someone already came up with that idea ;\/ And the idea was better because the decoder is like:<br \/>\n<code>eval(unescape(escape('SOME STRING').replace(\/uD.\/g,'')))<\/code><\/p>\n<p>And mine was\u00a0much longer and 2 lines:<br \/>\n<code>function(s){A=[];for(i=0;i&lt;s.length;i++){c=s.charCodeAt(i);A.push(c&amp;255);<br \/>\nc&gt;&gt;8?A.push(c&gt;&gt;8):c;}return String.fromCharCode.apply(String,A)}(\"SOME STRING\");<\/code><\/p>\n<p>But my method used a bit different technique, so I could use normal letters and fit some ASCII art inside the code, not only some strange chinese letters.<\/p>\n<p>OK, so after compiling with google closure, making big eval and changing to UTF-16, the code looks like this:<\/p>\n<p><a href=\"http:\/\/blog.teleranek.org\/wp-content\/uploads\/2015\/03\/Zrzut-ekranu-2015-03-09-02.21.38.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-280\" src=\"http:\/\/blog.teleranek.org\/wp-content\/uploads\/2015\/03\/Zrzut-ekranu-2015-03-09-02.21.38.png\" alt=\"Zrzut ekranu 2015-03-09 02.21.38\" width=\"996\" height=\"341\" srcset=\"https:\/\/blog.teleranek.org\/wp-content\/uploads\/2015\/03\/Zrzut-ekranu-2015-03-09-02.21.38.png 996w, https:\/\/blog.teleranek.org\/wp-content\/uploads\/2015\/03\/Zrzut-ekranu-2015-03-09-02.21.38-300x103.png 300w, https:\/\/blog.teleranek.org\/wp-content\/uploads\/2015\/03\/Zrzut-ekranu-2015-03-09-02.21.38-900x308.png 900w\" sizes=\"auto, (max-width: 996px) 100vw, 996px\" \/><\/a><\/p>\n<p>And can be seen on the challengepost&#8217;s winners&#8217;\u00a0( ?\u00b0 ?? ?\u00b0)\u00a0\u00a0gallery:<br \/>\n<a href=\"http:\/\/challengepost.com\/software\/20-lines-of-green\"><strong>http:\/\/challengepost.com\/software\/20-lines-of-green<\/strong><\/a><\/p>\n<p>or\u00a0<a href=\"http:\/\/blog.teleranek.org\/wp-content\/uploads\/2015\/03\/final_hypercomp.html\">here<\/a><br \/>\nor JSFiddle: <a href=\"http:\/\/jsfiddle.net\/to267224\/tbgad7uz\/\">http:\/\/jsfiddle.net\/to267224\/tbgad7uz\/<\/a><\/p>\n<p>ps. I will enhance this post later maybe, to provide some missing info on technical things and add some images, cause there&#8217;s too much unformatted text ; )<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Recently I stumbled upon a challenge on challengepost.com &#8211; &#8220;20 lines of JavaScript&#8221;. The goal was to write a 20 line JS\u00a0code that does something that can make the challenge judges vote for you. I thought the best idea would be to\u00a0treat this challenge\u00a0like a good ol&#8217; demoscene compo. I&#8217;ve already had a good effect [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[89,90,50,88,87],"class_list":["post-274","post","type-post","status-publish","format-standard","hentry","category-flash-experiments","tag-challenge","tag-challengepost","tag-experiments","tag-javascript","tag-js"],"_links":{"self":[{"href":"https:\/\/blog.teleranek.org\/index.php?rest_route=\/wp\/v2\/posts\/274","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.teleranek.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.teleranek.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.teleranek.org\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.teleranek.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=274"}],"version-history":[{"count":9,"href":"https:\/\/blog.teleranek.org\/index.php?rest_route=\/wp\/v2\/posts\/274\/revisions"}],"predecessor-version":[{"id":345,"href":"https:\/\/blog.teleranek.org\/index.php?rest_route=\/wp\/v2\/posts\/274\/revisions\/345"}],"wp:attachment":[{"href":"https:\/\/blog.teleranek.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=274"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.teleranek.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=274"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.teleranek.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=274"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}