Friday, August 14, 2009

GWT Image Dimensions and Pre-loading

I've run across this problem several times when programming in both JavaScript and in GWT (Google Web Toolkit). I need to fit an image in a specific space while maintaining aspect ratio, but I don't know the image dimensions.

For example I have a 100px by 100px space in my layout for a users profile picture, but the actual picture might be 300 x 200 or 200 x 400 or any other size. So half the time need to contrain the width of the image to get the correct aspect ratio, and half the time the height.

Luckily, we can count on browsers supporting the image "onload" event which is fired when the image fully loads. If we have not given the image any size constraints, the browser will display the image full size and we will be able to get it's dimensions at that point. An finally we can use those to resize it.

This method works, but it can get pretty complicated to try to hide the image so that it doesn't mess up the layout while it's loading and deal with race conditions that come with cashed images as well as several other cross-browser support issues. To make all of this much easier for us all, there is an open-source utility written for GWT that wraps all of the messy details in a simple and reliable interface.

The utility can be found at http://code.google.com/p/gwt-image-loader/. There are good examples on the site, but here's a preview.

To solve my problem of the 100px by 100px profile space, I have two options.

1) Have the ImagePreloader tell me what the image dimensions are and then resize my profile picture.

ImagePreloader.load(<IMAGE URL>, new ImageLoadHander() {
public void imageLoaded(ImageLoadEvent event) {
if (!event.isLoadFailed()) {
int originalWidth = event.getDimensions().getWidth();
int originalHeight = event.getDimensions().getHeight();

//add my logic here to resize image to fit in 100x100 space
}
}
});

2) Let the utility take care of this for me. Use the FitImage class which is a subclass of Image that allows me to set the maximum width and height, just like I want to do in my example. The image will automatically resize it self to fit within the 100 by 100 box while maintaining aspect ratio.

FitImage image = new FitImage(<IMAGE URL>, 100, 100);

If this sounds like something you could use, check it out (http://code.google.com/p/gwt-image-loader/). It's free and open source.