Monitoring Image I/O Events
From: Core Java Technologies Tech Tips for February 2007
Monitoring Image I/O Events
by Brian Burkhalter
The JavaTM Image I/O API provides a framework for working with images on the Java platform. Within this framework, the javax.imageio.event package defines several interfaces for monitoring synchronous events that are emitted while reading or writing images.
You can use these interfaces for the following purposes:
1.monitor the progress of image reading
2.receive notifications as each region of an image is read
3.trap warning messages about image reading
Each of these varieties of event monitoring is enabled by registering a listener with the ImageReader being used. You can obtain an ImageReader instance from the ImageIO class. The following code shows how to retrieve a reader for the TIFF image format:
ImageReader reader;
Iterator<ImageReader> readers =
ImageIO.getImageReadersByMIMEType("image/tiff");
if (readers.hasNext()) {
reader = readers.next();
}
Monitoring reading progress
The IIOReadProgressListener interface is used to monitor image reading progress. An implementation of IIOReadProgressListener is registered with an ImageReader using the addIIOReadProgressListener method. For example, the following code uses a ProgressMonitor to display image reading progress:
Component parentComponent;
String imageName;
ImageReader reader;// Create a ProgressMonitor which displays percentage completed.
final ProgressMonitor pm =
new ProgressMonitor(parentComponent, imageName, "0 %", 0, 100);// Register an anonymous inner class implementing IIOReadProgressListener
reader.addIIOReadProgressListener(new IIOReadProgressListener() {
// Close the ProgressMonitor if the read is aborted.
public void readAborted(ImageReader source) {
pm.close();
}public void imageStarted(ImageReader source,
int imageIndex) {
// Abort the read if "cancel" pressed.
if(pm.isCanceled()) {
source.abort();
}
}// Set image progress to 100% upon completion.
public void imageComplete(ImageReader source) {
imageProgress(source, 100.0F);
}
// Update the progress bar and its label each time the reader
// notifies the IIOReadProgressListener of a new percentage.
public void imageProgress(ImageReader source, float percentageDone) {
// Abort the read if "cancel" pressed.
if(pm.isCanceled()) {
source.abort();
return;
}
// Update the progress and label.
final int nv = (int)percentageDone;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
pm.setProgress(nv);
pm.setNote(nv+" %");
}
});
}
public void thumbnailStarted(ImageReader source, int imageIndex,
int thumbnailIndex) {
}
public void thumbnailProgress(ImageReader source, float percentageDone) {}
public void thumbnailComplete(ImageReader source) {}
public void sequenceStarted(ImageReader source, int minIndex) {}
public void sequenceComplete(ImageReader source) {}
});
The ProgressMonitor displays a progress bar which is filled from left to right as image loading progresses. When image reading begins, the reader invokes the imageStarted method, and the listener checks whether the ProgressMonitor's "cancel" button has been pressed. If canceled, the reading stops. When canceled, the reader calls the readAborted method, which closes the ProgressMonitor.
During reading, the reader will periodically invoke the imageProgress method with an updated progress value. After checking whether reading has been canceled, the listener updates the ProgressMonitor with the new progress value and percentage value string. Note that the listener updates the ProgressMonitor on the Swing event thread, not on the thread which invoked the imageProgress method. When image reading is complete, the reader invokes the imageComplete method to set the percentage completion value to 100.
The following image shows the ProgressMonitor as it updates its progress bar:
You can use the thumbnail methods of the IIOReadProgressListener class to monitor the progress of thumbnail loading when applicable.
Receiving region update notifications
The IIOReadUpdateListener interface is used to receive notifications when each region of an image is read. An image region could consist of a single row of pixels for scanline-oriented imagery or of a single tile for tiled imagery. Use the addIIOReadUpdateListener method to register an IIOReadUpdateListener implementation with an ImageReader instance.
For example an image display component might implement IIOReadProgressListener as follows:
public void imageUpdate(ImageReader reader, BufferedImage image,
int minX, int minY, int width, int height,
int periodX, int periodY, int[] bands) {
// Set the displayed image to the parameter image.
setImage(image);
// Repaint the sections of the image just updated.
repaint(0L, minX, minY, width, height);
}
public void passStarted(ImageReader reader, BufferedImage image,
int pass, int minPass, int maxPass,
int minX, int minY,
int periodX, int periodY, int[] bands) {}
public void passComplete(ImageReader reader, BufferedImage image) {}
public void thumbnailPassStarted(ImageReader reader, BufferedImage image,
int pass, int minPass, int maxPass,
int minX, int minY,
int periodX, int periodY, int[] bands) {}
public void thumbnailPassComplete(ImageReader reader,
BufferedImage image) {}
When an ImageReader invokes the imageUpate method, the method first calls the setImage method to perform any initialization that might be required for the display component:
/** Instance variable for the image being displayed. */
BufferedImage theImage = null;/** Initialize the display component using the provided image. */
protected void setImage(BufferedImage image) {
if(image != theImage) {
// Save the reference.
theImage = image;
// Initialize the display component as needed.
// --- CODE OMITTED ---
}
}
The display component then calls the repaint method to draw the image region that has just been loaded.
Being notified when an image region is updated is especially important when reading large images. The update notification permits the display component to paint each region as it is read rather than wait for the entire image to load before drawing any of the image.
Trapping warning messages
The IIOReadWarningListener interface is used to trap warning messages emitted by an ImageReader while reading an image. An implementation of IIOReadWarningListener is registered with an ImageReader using the addIIOReadWarningListener() method. For example, this code uses a JDialog to display the text of warning messages:
Component parentComponent;
String imageName;
ImageReader reader;// Create a text area to contain the warning message(s).
final JTextArea text = new JTextArea();
text.setColumns(60);
text.setLineWrap(true);
text.setWrapStyleWord(true);// Create a warning option pane to contain the text area.
JOptionPane opt = new JOptionPane(new JScrollPane(text),
JOptionPane.WARNING_MESSAGE, JOptionPane.DEFAULT_OPTION);// Create a modal dialog for the option pane.
final JDialog dialog =
opt.createDialog(JOptionPane.getFrameForComponent(parentComponent),
"Warnings: "+imageName);
dialog.setModal(false);// Register an anonymous inner class implementing IIOReadWarningListener
reader.addIIOReadWarningListener(new IIOReadWarningListener() {
public void warningOccurred(ImageReader source,
final String warning) {
// Append the current warning to the text area.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
text.append("[WARNING]: "+ warning+"\n");
dialog.pack();
dialog.setVisible(true);
}
});
}
});
When the ImageReader emits a warning message, it invokes the warningOccured method, which appends the message to the text area and displays the warning dialog. Note that the warning dialog is updated on the Swing event thread, not on the thread which invoked the warningOccurred method.
The following image shows the warning dialog:
Monitoring image writing events
Monitoring Image I/O events while writing images is very similar to monitoring events while reading images. The IIOWriteProgressListener and IIOWriteWarningListener interfaces are analogs of IIOReadProgressListener and IIOReadWarningListener, respectively. Use them with an ImageWriter like the latter interfaces are used with an ImageReader as described above.