Serverside Image Observing in Java

I ran into the problem of needing to load a BufferedImage on the serverside of a Java web application. I’m manipulating images dynamically in code that are then served to the web browser. Java loads images asynchronously by default, and you can track progress using the ImageObserver interface, but it might not be as easy as you think.


Waiting for images to load is a common enough problem that the JDK comes with MediaTracker to make it easy:

Image image = getToolkit().getImage("/image.gif");
MediaTracker tracker = new MediaTracker(this);
tracker.addImage(image, 0);
tracker.waitForAll();

Unfortunately, MediaTracker requires a java.awt.Component, limiting it to code that is written with a toolkit user interface. Since I needed to load an image in serverside Java code, I would need to implement the ImageObserver interface. Here’s what I came up with:

public class WaitingImageObserver implements ImageObserver {

    public WaitingImageObserver() {
    }

    public boolean imageUpdate(Image image, int flags, int x, int y, int width, int height) {
        synchronized (this) {
            boolean result = false;
            if ((flags & ALLBITS) == 0) {
                result = true;
            }
            notifyAll();
            return result;
        }
    }

    public void waitForImage(Image image) {
        Toolkit toolkit = Toolkit.getDefaultToolkit();

        synchronized (this) {
            int flags = toolkit.checkImage(image, -1, -1, this);
            while ((flags & ALLBITS) == 0 && (flags & ABORT) == 0) {
                try {
                    wait();
                }
                catch (InterruptedException e) {}
                flags = toolkit.checkImage(image, -1, -1, this);
            }
        }
    }
}

The flags integer contains information about progress of the image loading. Here are the flag constants and what they mean:


































Flag Description
HEIGHT The height of the image is ready
WIDTH The width of the image is ready
FRAMEBITS A frame is complete
SOMEBITS
An arbitrary number of pixels have arrived
ALLBITS
The image is complete
ABORT
The image loading has been aborted
ERROR
An error occurred during image processing;
attempts to display the image will fail


Once I had a WaitingImageObserver class that I could use on the server, I created a small helper method in a utility class to load a BufferedImage:

public class Util {

    public static BufferedImage getBufferedImage(String imageName) {
        URL url = Util.class.getResource(imageName);
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        Image image = toolkit.createImage(url);
        WaitingImageObserver observer = new WaitingImageObserver();
        toolkit.prepareImage(image, -1, -1, observer);
        observer.waitForImage(image);

        BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_BYTE_INDEXED);
        Graphics2D graphics = bufferedImage.createGraphics();
        graphics.drawImage(image, 0, 0, Color.WHITE, observer);
        observer.waitForImage(bufferedImage);
        return bufferedImage;
    }
}

2 Responses to “Serverside Image Observing in Java”

  1. Joel Says:

    E,

    What is all of this strange syntactical verbage that you put in your post? Semi-colons? Brackets? When did you start speaking in this language? It appears vaguely similar to something that we used to call “code” back in school. What happened to all of the flowcharts and diagrams that you were creating at work? They seemed so much prettier and easier to understand…

    Joel

  2. Eric Says:

    At work I program in the familiar Integrated Developer Environments … Word, Excel, Powerpoint, Visio, and Outlook. But just recently, I’ve been using a strange tool called Eclipse. When I show the work I’ve done in Eclipse to my manager, he looks puzzled. Fortunately, we only have to use Eclipse for a few weeks. Then I can get back to more satisfying work that is more productive for the organization.

Leave a Reply

You must be logged in to post a comment.