Pix-It War!

So-called custom HTTP handlers can be incredibly useful. It’s almost laughably easy to write your own handler, and it enables some scenarios that might be difficult, cumbersome or inelegant to support otherwise. It’s definitely something you’ll want in your repertoire if you’re an ASP.NET programmer.

In essence, what a custom HTTP handler gives you is the ability to respond to an HTTP request by creating arbitrary content on the fly and have it pushed out to the client making the request. This content could be any type of file you like. In theory it could be HTML for the browser to render, but it typically won’t be (you have regular ASP.NET pages for that, remember?). Rather, you’ll have some way of magically conjuring up some binary artefact, such as an image or a PDF document. You could take various kinds of input to your spell, such as data submitted with the request, data from a database, the phase of the moon or what have you.

I’m sure you can imagine all kinds of useful things you might do with a custom HTTP handler. On a recent project, I used it to generate a so-called bullet graph to represent the state of a project. If you use ASP.NET’s chart control, you’ll notice that it too is built around a custom HTTP handler. Any time you need a graphical representation that changes over time, you should think of writing a custom HTTP handler to do the job.

Of course, you can use custom HTTP handlers to do rather quirky things as well, just for kicks. Which brings us to the meat of this blog post.

This particular HTTP handler is inspired by the phenomenon known as Post-It War, show-casing post-it note renderings of images (often retro game characters). Unfortunately, I’m too lazy to create actual, physical post-it figures, so I figured I’d let the ASP.NET pipeline do the heavy lifting for me. I am therefore happy to present you with a custom HTTP handler to produce 8-bit-style images, using a simple JSON interface. Bet you didn’t know you needed that.

The basic idea is for the user to POST a description of the image as JSON, and have the HTTP handler turn it into an actual image. Turns out it’s really easy to do.

We’ll let the user specify the number of coarse-grained “pixels” in two dimensions, as well as the size of the “pixels”. Based on this, the HTTP handler lays out a grid constituting the image. By default, all pixels are transparent, except those that are explicitly associated with a color. For each color, we indicate coordinates for the corresponding thus-colored pixels within the grid.

So, say we wanted to draw something simple, like the canonical space invader. We’ll draw a grid by hand, and fill in pixels as appropriate. A thirteen by ten pixel grid will do nicely.

Invader-skisse-w350

We can glean the appropriate pixels to color black from the grid, which makes it rather easy to translate into a suitable JSON file. The result might be something like:

Is this the optimal textual format for describing a retro-style coarse-pixeled image? Of course not, I made it up in ten seconds (about the same time Brendan Eich spent designing and implementing JavaScript, or so I hear). Is it good enough for this blog post? Aaaabsolutely. But the proof of the pudding is in the eating. So let’s eat!

We’ve established that the user will be posting data like this to our custom HTTP handler; our task is to translate it into an image and feed it into the response stream. Most of this work can be done without considering the context of an HTTP handler at all. The HTTP handler is just there to expose the functionality over the web, really. It’s almost like a web service.

Unfortunately, getting the JSON from the POST request is more cumbersome than it should be. I had to reach for the request’s input stream in order to get to the data. Once you get the JSON, however, the rest is smooth sailing.

I use Json.NET‘s useful Linq-to-JSON capability to coerce the JSON into a .NET object, which I feed to the image-producing method. The Linq-to-JSON code is pretty simple, once you get used to the API:

You might be able to do this even simpler by using Json.NET’s deserialization support, but this works for me. There’s a little bit of fiddling in order to allow for the optional specification of a background color for the image.

The .NET type looks like this:

The Pixel type simply represents an (X, Y) coordinate in the grid:

Creating the image is really, really simple. We start with a blank slate that’s either transparent or has the specified background color, and then we add colored squares to it as appropriate. Here’s how I do it:

That’s just about all there is to it. The entire HTTP handler looks like this:

Warning: I take it for granted that you won’t put code this naïve into production, opening yourself up to denial-of-service attacks and what have you. It takes CPU and memory to produce images, you know.

Of course, as always when using a custom HTTP handler, we must add the handler to web.config. Like so:

Note that we restrict the HTTP verb to POST, since we need the JSON data to produce the image.

Now that we have the HTTP handler in place, we can try generating some images. A simple way to invoke the handler is to use Fiddler. Fiddler makes it very easy to build your own raw HTTP request, including a JSON payload. Just what we need. Let’s create a space invader!

All we need to do is add the appropriate headers and the JSON payload.

Fiddler-request-builder

The image only includes the headers for the request, but Fiddler also has a text area for the request body, which is where you’ll stick the JSON data.

The PNG-file returned by our HTTP handler looks like this:

Invader-black

Nice!

Of course, we could create more elaborate images, using more pixels and more colors. For instance, the following JSON could be used to evoke the memory of a certain anti-hero named Larry, hailing from the hey-day of Sierra On-Line.

The result?

Larry-4

You might say “that’s a big file to create a small image”, but that would be neglecting the greatness of the Laffer, and his impact on a generation of young adolescents.



Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s