The interface provided is so opaque that in the initial development stages there was no direct way to access the pixel data of an image. The data could be accessed if a developer were willing to learn the intricacies of the complex ImageConsumer interface which is used by the image subsystem to communicate pixel data from image decoders to the screen, but most developers wanted an easier mechanism to get this data for the general case.
To satisfy this need a utility class was created to manage the ImageConsumer interface on behalf of the average developer who simply wanted to answer the question "What color is the pixel at location (x, y)?" The PixelGrabber class provided the ability to snapshot a rectangular region of pixels directly from an image's source to a Java integer array.
Three primary oversights have been identified with the interface provided by this class:
new PixelGrabber(Image img,
int x, int y, int w, int h,
boolean forceRGB)
startGrabbing()
abortGrabbing()
getWidth()
getHeight()
getPixels()
getColorModel()
Following is sample code showing the use of the new API to grab
the pixels of an image of unknown dimensions in its original format:
import java.awt.*;
import java.awt.image.*;
import java.applet.*;
public class GrabExample extends Applet implements Runnable {
Thread grab;
Image img;
PixelGrabber pg;
public void init() {
img = getImage(getDocumentBase(), "theImage.gif");
pg = new PixelGrabber(img, 0, 0, -1, -1, false);
// In reality, the init method shouldn't be kicking off
// heavyweight operations like an image download, but
// this demonstrates use of the asynchronous grabbing...
pg.startGrabbing();
}
public void start() {
grab = new Thread(this);
grab.start();
}
public synchronized void stop() {
grab.interrupt();
grab = null;
}
public synchronized void run() {
try {
pg.grabPixels();
repaint();
} catch (InterruptedException e) {
System.err.println("grab was interrupted");
return;
}
}
public void paint(Graphics g) {
// Display some pixel values
int status = pg.getStatus();
if ((status & ABORT) != 0) {
g.drawString("Image grab was aborted", 10, 100);
} else if ((status & ALLBITS) != 0) {
g.drawString("Image grab is complete", 10, 100);
} else if ((status & FRAMEBITS) != 0) {
g.drawString("Frame grab is complete", 10, 100);
} else if ((status & SOMEBITS) != 0) {
g.drawString("Image grab is under way", 10, 100);
}
if ((status & (WIDTH|ALLBITS|FRAMEBITS)) != 0) {
FontMetrics fm = g.getFontMetrics();
String caption = "First 3 pixels: ";
int x = 10;
int w = pg.getWidth();
Object pix = pg.getPixels();
ColorModel cm = pg.getColorModel();
g.drawString(caption, x, 50);
x += fm.stringWidth(caption);
if (pix instanceof byte[]) {
for (int i = 0; i < Math.min(3, w); i++) {
String s = Integer.toString(((byte[])pix)[i]&0xff, 16);
g.drawString(s, x, 50);
x += fm.stringWidth(s + " ");
}
} else {
for (int i = 0; i < Math.min(3, w); i++) {
String s = Integer.toString(((int[])pix)[i], 16);
g.drawString(s, x, 50);
x += fm.stringWidth(s + " ");
}
}
}
}
}