Image class given the URL of a file containing image data. Then, in last month's column, I showed you how to create an instance of the Image class given an instance of a class that implemented the ImageProducer interface. In both examples the rest of the application didn't know (or care, for that matter) how the Image object was created.Let's examine the second case in a bit more detail.
True to its name, an image producer produces image data. The image producer in last month's column produced an image showing a color gradient. However, an image producer is not limited to generating (and regenerating) a single, static frame of image data; in fact, it is free to redefine the image data at any time.
Perhaps you can guess where I am going with this. After an image producer has produced one frame of image data, it is free to draw right on top of that frame to produce yet another frame of image data. Repeat this process a couple of times and, bam, you've got animation!
Whoah! Animation that easy? You bet. Let's take a closer look at how we can actually do this repetitive drawing.
Take a look at the illustration below, which shows the relationship between an image producer and one or more image consumers. As you know from our previous discussions, the image producer communicates information about the image data it is producing to one or more image consumers by invoking public methods on the image consumer. Image consumers then use this image information in a variety of ways -- to draw the image on the screen, for example. If you're feeling little lost about the whole concept of image producers and image consumers, take a quick detour back to last month's column before we move on.

The interface between an image producer and an image consumer dictates the type of images that can be produced. With that
in mind, let's look at two of the methods the ImageConsumer interface defines and the parameters those methods expect. The methods are the setHints() and imageComplete() methods. Let's begin at the end with the imageComplete() method, shown next:
imageComplete(int nStatus)
When an image producer calls an image consumer's imageComplete() method, it does so with the intent of informing the consumer about the status of the image reconstruction. The imageComplete() method requires an integer argument, which can be one of four values: IMAGEABORTED, IMAGEERROR, STATICIMAGEDONE, and SINGLEFRAMEDONE.
An image producer uses the arguments IMAGEABORTED and IMAGEERROR to indicate that something has gone wrong during the process of image production. It uses the argument STATICIMAGEDONE to indicate that image production is completely finished. Last of all, but central to our plan, it uses the argument SINGLEFRAMEDONE to indicate it has produced a single frame of image data but more frames may follow.
The following snippet demonstrates how an image producer would indicate to an image consumer that image production is complete:
Image API:ImageProducer API:ImageConsumer API:ImageObserver API: