hackification

Homepage

...rediscover the joy of coding

Stack-Based Processing, Part 2

In Part 1 I discussed stack-based representations of functions in very general terms. Now I'm going to present a real-world example.

I've been working on a new feature for EasyAs123Web.com recently - image cropping. When building your web-pages, we allow you to upload images, and then use them in the web-page, either as simple images in the normal flow of things, or merged into the website theme itself. Since many themes need odd-shaped images (e.g. letterbox formats in the header), we desperately needed a way for the user to control which bits of the image would be displayed.

(I'm using this jQuery plug-in to handle the client-side stuff).

Now to merge these images into the website theme, I've been writing handlers that spit out an image, based on certain parameters. For example, I had one that resized an image from the database; another that combined two images (one from the database, one from the theme); one that cross-faded two images; and so forth.

The problem is that these handlers all start resembling each other. They all need to do a bit of resizing, a bit of aspect ratio calculating, and with the new cropping feature, they'd all have to support cropping, and so the code was getting messy and repeated.

So I needed a new approach. I needed something that was easy to encode and decode in a URI; something that could be modified (for example to insert a crop operation); and something that would keep my code tidy.

Stacks!

I based my approach around a Stack<Bitmap>. My handler parses its query string into a sequence of operations. Each operation is then applied in turn, with the stack as the only parameter. At the end, I expect the stack to contain exactly one image, which is returned by the handler.

My operations now become really really simple. For example, I have simple load operations: I have simple combining operations: I have manipulation operations: And finally, I have a handy "swap" operation [POP A; POP B; PUSH A; PUSH B].

Examples

Let's suppose I have two images, A and B:

A - a picture of a tree, with a transparent background.

B - a picture of some sort of sky-like background.

I can combine them as follows:

PUSH COLOR - #F00 ; PUSH A ; COMBINE

PUSH B ; PUSH A ; COMBINE

PUSH B ; PUSH A ; CROP - 0.0, 0.4, 1.0, 0.7 ; COMBINE

Hopefully you can see that I can get a variety of effects simply by combining a variety of simply stack operations. I can very easily represent a sequence of operations in a URI too, since they're sequential.