On this vacation, given that Lauren is seven months pregnant, we picked something that was low-stress and low-adventure (starting with the location; there’s a direct Vancouver-to-Kona flight). I like lounging by the pool and sampling the local beverages as much as anyone, but with a deadline-free week, I also found time for some recreational programming. The result is something I call “Framer”, which generates borders and/or drop shadows for images in most popular formats. It writes PNGs with variable alpha channel so the drop shadows will look OK on any color background. It has some options and you’re free to use it, but it’s not problem-free and unless there’s a lot of interest I’m not going to open-source it. Illustrated with groovy Big Island sunset photos.

Getting and Using It · Download the JAR here and the Javadocs tarball here. No warranties, in fact I’m sure some input files and combinations of options will make it blow chunks; you have been warned. To figure out the arguments and defaults, type java -jar Framer.jar -help, or look at the Javadocs (Java 1.5 required). You can change the color and thickness of the border and drop-shadow. The defaults look like the pictures here at ongoing:

Big Island sunset from South Kohala

Why I Did It · Well,the little random picture in the right margin has been drop-shadowed for a couple of years, using the List Apart CSS technique augmented by professional help from Dave Shea; that story here).

I’ve wanted the photos I showpiece in the mainline of the stories shadowed as well, but the ALA/Shea technique interacted toxically with the rest of the layout, and trying to debug it led down a maze of twisty little CSS passages, all different.

Poking around the Web produced lots of commentary along the lines of “You should be able to do this with ImageMagick”, or by scripting the Gimp or PhotoShop, but nowhere did I find an actual example of something I could wire into the Perl script that publishes ongoing.

So, I thought, how hard can it be? And indeed, it wasn’t too hard.

Status · As of now, all the drop shadows you see here at ongoing are courtesy of Framer. I’m actually kind of glad to be getting rid of the CSS drop shadows, which were at best a hack; it’s a reasonable thing to want to be able to do picture-decoration in a stylesheet, I think but if you want to do that, CSS should provide something like:

img { shadow: 8px 315deg #003434; }

Anyhow, Framer does what I need here at ongoing, and in the short term I need to turn my attention back to my real-world deliverables. If other people want to use Framer, and if other people are getting bit by its shortcomings, well then maybe some more work is called for.

In which case I really ought to slap an OSS license on it, but because I happen to work for maybe the world’s largest publisher of open-source software, that means that There Are Procedures, and I’d rather avoid doing the work for 493 lines of Java, the damn license boilerplate would probably double the size of the code.

Problems · It’s painfully slow. First you have to start a JVM (so you should do lots of pictures at once), and then Framer burns way too long for even a modest picture. For some reason NetBeans here on my Mac doesn’t include the profiler (Not available? Download required?), so I don’t yet know why it’s slow.

The variable shadow depth doesn’t work all that well; when you make it too big, it looks gross not only because drop shadows should be modest in size, but because the shadowed corners are at a funny (funny as in wrong) angle.

You should be able to select the shadow angle, right now it’s illuminated from the top left which is the typical default in most graphics packages but it should be variable and I thought I’d figured out how to do that but it’s harder than I thought, so maybe someday.

The drop shadows aren’t as polished, if you look real close, as those produced by actual professional graphics programs written by actual professional graphics programmers who understand the theory. The fall-off in shadow darkness (really a fall-off in PNG alpha) isn’t quite feathery enough, and the shading in the corners is really kind of kludgy.

Why Java? · Because I’d already used Java’s java.awt.image.BufferedImage and java.imageio.ImageIO APIs, and since those are core APIs, I could go on vacation and be sure that everything I needed would be on the laptop.

That ImageIO library is really first-rate, unusually for Java it’s fairly abstraction-free and automated: “Here’s the name of a file I claim contains an image, please go read it and either give me a BufferedImage or toss me an exception.”

If you want to draw rectangles efficiently, there are some abstractions you have to soak up, but since it has a SetRGB(x, y, color) method, who needs ’em? Hmm, maybe that’s why it’s slow.

Palm trees, drop-shadowed

Math Fun · Well, I blew up the drop-shadows produced by a couple of my fave graphics apps, and the way the darkness falls off is subtly nonlinear. In fact, I couldn’t spot the pattern, so I looked at the differences in color values between successive lines in the shadow, and those delta values looked not unlike a parabola; so I asserted that they were sorta kinda like a derivative and integrated it and got a cubic function that actually produces a drop-off not unlike the pros use. But it could still be better.

It’s also possible that repeatedly computing a double-precision cubic polynomial is a suboptimal way of generating 8-bit alpha-channel values. Do ya think?

And the way that the pro programs do the drop-shadows on the corners is still better than Framer’s, my attempts to bend those polynomial parameters around a corner are pretty ugly inside.


author · Dad · software · colophon · rights

April 08, 2006
· Arts (11 fragments)
· · Photos (900 more)
· Technology (77 fragments)
· · Java (123 more)
· · Presentation (18 more)
· The World (107 fragments)
· · Places
· · · Hawaii (25 more)

By .

I am an employee
of Amazon.com, but
the opinions expressed here
are my own, and no other party
necessarily agrees with them.

A full disclosure of my
professional interests is
on the author page.