MemoryImageSource クラスはこの機能を提供しますが、静的なイメージ機能を実装するだけです。prepareImage メソッドを使用してイメージを描画するか、あるいは MediaTracker を使用してイメージを構築することにより、画面用に最初にイメージが準備されるとき、配列内のピクセルのスナップショットが画面表示用に変換されます。すると、イメージが同じスケールで再描画されるたびに、同じバッファの画面表示が使用され、開発者がその間に元のピクセルの配列に対して行なった変更が無視されます。
この実装は各レンダリング操作に対して、ピクセル情報の元の配列を再読み込みすることはありません。これは、イメージ変換が、変換されたピクセルを画面に単に移動することに比べて遅い処理だからです。drawImage を速くするためには、表示ハードウェアがピクセルを表示するために使用するフォーマット内に既存のイメージのコピーを使用すると、うまく機能します。このため、イメージを変更していないときには速く表示することと、動的に元のイメージデータへの変更を取り込むことの両方に使用できます。
この実装は、一度計算されその結果が最終であるイメージに対してはうまく機能しました。また、めったに変更されないイメージに対しても機能しました。これは、まれに行われる各変更のあとで新しい MemoryImageSource イメージを構築できたこと、または元のイメージを Image.flush() メソッドを使用してフラッシュし、既存のすべての画面表示をキャッシュから削除できたためです。これらの作業はアニメーションなどの、より頻繁な更新に対しては不十分だったり非実用的でした。イメージ全体を、データへの小さな修正に対してさえも再変換する必要があったからです。さらにまた、この作業はイメージの廃棄された古いバージョンが使用した空間を取り戻すために正確に必要な以上に、ガベージコレクションを要求します。
setAnimated(boolean animated) setFullBufferUpdates(boolean animated) newPixels() newPixels(int x, int y, int w, int h) newPixels(int x, int y, int w, int h, boolean framenotify) newPixels(byte[] newpix, ColorModel newmodel, int offset, int scansize) newPixels(int[] newpix, ColorModel newmodel, int offset, int scansize)これらの新しいメソッドによって、開発者は、いつ画面の表示を更新するのか、ピクセルのどの領域を更新するのか、いつ ImageObserver.FRAMEBITS 通知 (アニメーションの単一「フレーム」が完了したときを示す) をイメージオブザーバーに送るのかを制御し、ピクセルと ColorModel の新しいセットへの切り替え機能などを制御できるようになります。
メモリイメージバッファアニメーションを実行する古い API の使用方法を示すサンプルコードを、次に示します。
import java.awt.*;
import java.awt.image.*;
import java.applet.*;
public class AnimationExample extends Applet implements Runnable {
Thread anim;
MemoryImageSource imgsrc;
Image memimg;
int[] pixels;
public void init() {
pixels = new int[100 * 100];
imgsrc = new MemoryImageSource(100, 100, pixels, 0, 100);
memimg = createImage(imgsrc);
}
public void start() {
anim = new Thread(this);
anim.start();
}
public synchronized void stop() {
anim = null;
notify();
}
public synchronized void run() {
while (Thread.currentThread() == anim) {
int x = (int) (Math.random() * 100);
int y = (int) (Math.random() * 100);
int r = (int) (Math.random() * 255);
int g = (int) (Math.random() * 255);
int b = (int) (Math.random() * 255);
pixels[y * 100 + x] =
((int) (Math.random() * 0xffffff)) | (0xff<<24);
memimg.flush();
repaint();
try {wait(100);} catch (InterruptedException e) {return;}
}
}
public void paint(Graphics g) {
// Draw the animated image
g.drawImage(memimg, 0, 0, this);
}
}
メモリイメージバッファアニメーションを実行する新しい API の使用方法を示すサンプルコードを、次に示します。
import java.awt.*;
import java.awt.image.*;
import java.applet.*;
public class AnimationExample extends Applet implements Runnable {
Thread anim;
MemoryImageSource imgsrc;
Image memimg;
int[] pixels;
public void init() {
pixels = new int[100 * 100];
imgsrc = new MemoryImageSource(100, 100, pixels, 0, 100);
imgsrc.setAnimated(true);
memimg = createImage(imgsrc);
}
public void start() {
anim = new Thread(this);
anim.start();
}
public synchronized void stop() {
anim = null;
notify();
}
public synchronized void run() {
while (Thread.currentThread() == anim) {
int x = (int) (Math.random() * 100);
int y = (int) (Math.random() * 100);
int r = (int) (Math.random() * 255);
int g = (int) (Math.random() * 255);
int b = (int) (Math.random() * 255);
pixels[y * 100 + x] =
((int) (Math.random() * 0xffffff)) | (0xff<<24);
imgsrc.newPixels(x, y, 1, 1);
repaint();
try {wait(100);} catch (InterruptedException e) {return;}
}
}
public void paint(Graphics g) {
// Draw the animated image
g.drawImage(memimg, 0, 0, this);
}
}