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:
- Load an image from database, push it onto the stack.
- Load a static image, push it onto the stack.
- Load a field of solid colour at a particular size, and push it onto the stack.
- Pop two images; draw one on top of the other; push the resulting single image back onto the stack.
- Pop two images; tile one as background; draw the other as foreground; push the resulting single image back onto the stack.
- Pop an image; resize it; push it back onto the stack.
- Pop an image; crop it; push it back onto the stack.