New MiniApp: Storm Drain

While playing around some more with this miniapp idea, I came across geographer Tyler Mitchell's weblog post about hurricane tracking using Web Map Service urls. I thought this would make an interesting MiniApp and give me a good opportunity to play with a few webservices. Starting from his base (and with some greatly appreciated clarification emails from Tyler), I've created StormDrain, a simple program that loads WMS data and displays it graphically. Here's what it looks like:

Storm Drain: Jeanne Data

WMS data services give you access to lots of useful information. It can render storm data for any geographic area and resolution you want, returned in a variety of image formats. It also has a discovery mechanism that lets you programmically find out what storm data is available. http://dev.gomoos.org/cgi-bin/wms_nhc?request=getcapabilities will provide you with a XML list of every request and format the service understands.

In my program you can left click to recenter and zoom, and right click to zoom out. The Storms menu gives you the list of storms generated by the GetCapabilities request type. It uses a zoom factor to determine which latitude and longitude to use when requesting the maps.

The land map images have a light blue background that I wanted to replace with something more oceany. To pull this off I created a color swap filter that will replace one color with another. For the land data it replaces the background with a dark blue. For the storm data it replaces the background with the transparent color (0,0,0,0) so that the other layers will shine through.

Java2D's image APIs make this kind of a color filter quite easy to implement. First you need a custom RGBImageFilter called ColorSwapFilter:

class ColorSwapFilter extends RGBImageFilter {
private int target;
private int replacement;
public ColorSwapFilter(Color target,
Color replacement) {
this.target = target.getRGB();
this.replacement = replacement.getRGB();
}

public int filterRGB(int x, int y, int rgb) {
if(rgb == target) {
return replacement;
}
return rgb;
}
}

Any RGBImageFilter must implement the filterRGB method, which will return a new color based on the input color at the current x and y coordinates. In this case it returns the replacment color when the current color matches a target, otherwise it just returns the original color. Note that I've used getRGB() to work with the colors as integers instead of color objects.

Filter in hand, you can now filter any image to swap the colors. This is a utility function that gets the source image, creates a new filter to swap the target color with a transparent color, then executes the filter with a call to createImage() on any component (a new JPanel in this case). It's that simple

public Image loadTransImage(URL url, Color target) {
Image src = new ImageIcon(url).getImage();
ImageFilter imgfilter =
new ColorSwapFilter(target,new Color(0,0,0,0));
Image img = new JPanel().createImage(
new FilteredImageSource(src.getSource(),imgfilter));
Image imgx = new ImageIcon(img).getImage();
return imgx;
}

StormDrain loads data from a WMS service provided by GoMoos.org

Storm Drain webstart link

updated webstart link

Talk to me about it on Twitter

Posted September 22nd, 2004

Tagged: java.net