AWT PixelGrabber API updates

last updated: November 14, 1996

The Issue

The AWT image facility provides ways to retrieve or create images from many sources and to automate the process of displaying those images on the screen. The facility performs all of the required manipulations necessary on the image data behind an opaque external interface which shields users from all but the most abstract of image data information.

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:

The new PixelGrabber methods

To enhance the capabilities of the PixelGrabber, new methods and constructors are being added: new PixelGrabber(Image img, int x, int y, int w, int h, boolean forceRGB) startGrabbing() abortGrabbing() getWidth() getHeight() getPixels() getColorModel()

Sample Code

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 + " "); } } } } }

Send feedback
Copyright © 1996, Sun Microsystems, Inc. All rights reserved.