提供されるインタフェースは非常に不透明なため、初期の開発段階では、イメージのピクセルデータに直接アクセスする方法はありませんでした。開発者が難解で複雑な ImageConsumer インタフェースを積極的に学習すれば、データにアクセスすることは可能でした。このインタフェースは、イメージデコーダから画面へピクセルデータを交信するためにイメージサブシステムが使用するものです。しかし、ほとんどの開発者は、このデータを一般的なケースで取得する簡単な機構を望んでいました。
このニーズに応えるために、ユーティリティクラスが作成され、「位置 (x, y) のピクセルは何色か」を指定するだけで済ませたい場合に、開発者の代わりに ImageConsumer インタフェースを制御します。PixelGrabber クラスは、ピクセルの矩形領域をイメージソースから Java 整数配列にスナップショットを作成する機能を提供しました。
このクラスが提供するインタフェースで、次の 3 つの重要な機能が不足していました。
new PixelGrabber(Image img, int x, int y, int w, int h, boolean forceRGB) startGrabbing() abortGrabbing() getWidth() getHeight() getPixels() getColorModel()
元の形式で、未知の次元のイメージのピクセルをグラブするための新しい API の使用方法を示すサンプルコードを次に示します。
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 + " "); } } } } }