CSSfuscator

08/10/2015

My relationship with CSS is, let’s say, complicated. I know just enough to style bare-bones websites, yet every time I want to get fancy I run into this hell of not having any clue what knobs to tweak to get the desired results, especially if it’s got to look the same on all relevant browsers. My cure for any hard feelings towards a tool has been abusing it for something it hasn’t been designed for, like I’ve been doing way too often with Emacs already.

I do occasionally enjoy clicking pixels into place and follow other people doing the same. Some of them do specialize in small icons and game sprites, so they usually offer a magnified version of their work, be it with an extra link or some Javascript to toggle between scaled versions. This made me wonder whether you couldn’t simply scale the image itself in the browser without introducing any smoothing. It turns out you can with CSS as demonstrated on piCSSel.

The idea behind this hack is pretty simple. A block element can have a box-shadow property which allows you to put a shadow with a specific color and position close to it. As you aren’t limited to a single shadow and can use many of these with distinct colors and positions, it’s possible to arrange them into a picture. Inspired by this discovery, I did draw a jar in GIMP and wrote some CSS3 by hand to have an animated version of it on http://brause.cc.

On my way to ICC 2015, it occurred me how nice it would be to not have to write this CSS by hand again, so I started writing a CLI utility. It’s using imlib2 to extract the colors of each pixel, then turns each of these into a box shadow specification and inserts them in some CSS and HTML boilerplate which is then written out to disk.

smugleaf.html for instance was generated from a sprite of a fictional Pokemon with the following invocation:

cssfuscator -uem -s0.25 -O --html-title=Smugleaf --stylesheet=split \
--stylesheet-name=smugleaf.css -i smugleaf.gif -o smugleaf.html

You can hit C-+ and C-- for resizing the image up to a certain limit. While the rendering isn’t perfect yet[1], it is satisfactory. A side effect of this technique is that it’s no longer possible to download an image of the result. If you’re tempted to use this tool as an image gallery protection, think again. This is probably the most inefficient way to encode an image[2], even with --optimize the resulting files are larger by a factor between 20x and 2000x.

There’s no animation support yet. imlib2 does have an egg, but giflib doesn’t. I’ve been reading the original GIF specifications and its documentation in order to build a simple tool and prepare myself for writing CHICKEN bindings to the library. Once that’s done, there will be a follow-up post on the gnarly details.

[1]Not sure why, but I get white gridlines at some magnifications. Another weird thing is that Chromium does allow for resizing images with pixel dimensions while Firefox doesn’t.
[2]Right after HTML obfuscation which would use a HTML table and each cell as pixel. See a speed drawing demo on Youtube for someone doing this in Notepad(!) with judicious use of search and replace.