目次 | 前の項目 | 次の項目 | Java 2D API |
BufferedImage クラスは、即時イメージングモードのサポートで中心となるクラスです。メモリ内のイメージを管理し、ピクセルデータを格納および解釈したり、Graphics コンテキストまたは Graphics2D コンテキストにピクセルデータをレンダリングしたりする手段を提供しています。
BufferedImage を作るには、Component.createImage メソッドを呼び出します。このメソッドからは BufferedImage が返され、その描画特性は、オブジェクトの作成に使われたコンポーネントの描画特性に対応しています。作成されるイメージは不透明で、Component のフォアグラウンドとバックグラウンドの色を持ち、イメージの透明度を調節することはできません。この技法を使うと、コンポーネントのアニメーションでダブルバッファリングの描画を行うことができます。詳細については、「オフスクリーンバッファへの描画」を参照してください。
public Graphics2D createDemoGraphics2D(Graphics g) { Graphics2D g2 = null; int width = getSize().width; int height = getSize().height; if (offImg == null || offImg.getWidth() != width || offImg.getHeight() != height) { offImg = (BufferedImage) createImage(width, height); } if (offImg != null) { g2 = offImg.createGraphics(); g2.setBackground(getBackground()); } // .. clear canvas .. g2.clearRect(0, 0, width, height); return g2; }
いくつか提供されているコンストラクタメソッドを使って、空の BufferedImage をメモリ内に作成することもできます。
BufferedImage クラスを使うと、グラフィック要素をオフスクリーンの状態で用意し、それを画面にコピーすることができます。この方法は、グラフィックが複雑な場合、または 1 つのグラフィックを繰り返し使う場合に、特に有効です。たとえば、複雑な図形を何度も表示する必要がある場合は、オフスクリーンバッファにその図形を 1 度描画してから、ウィンドウの別の場所にそれをコピーします。1 度描画した図形をコピーすることで、グラフィックの表示を高速化できます。java.awt パッケージでは、ウィンドウに描画する場合と同じ方法で Image オブジェクトに描画できるので、簡単にオフスクリーンバッファを使うことができます。オフスクリーンイメージに描画するときも、Java 2D API のすべてのレンダリング機能を使用できます。
オフスクリーンバッファは、アニメーションでよく使われます。たとえば、オフスクリーンバッファを使ってオブジェクトを 1 回描画し、ウィンドウの中でそれを動き回らせるような使い方をします。同様に、ユーザがマウスを使ってグラフィックを移動させるときのフィードバックにも、オフスクリーンバッファを利用します。すべてのマウス位置でグラフィックを描画するのではなく、1 度オフスクリーンバッファに描画したグラフィックを、ユーザがマウスをドラッグするのに合わせて、マウスの位置にコピーします。1
図 5-3 は、オフスクリーンイメージに描画してからそのイメージをウィンドウに何回もコピーしているプログラムの例です。最後にイメージをコピーするときは、イメージを変換しています。変換を指定してイメージを再描画する代わりに描画されているイメージを変換すると、不十分な結果になる場合があることに注意してください。
オフスクリーンバッファとして使用できるイメージを作る場合は、Component.createImage メソッドを使うのがもっとも簡単な方法です。カラー領域、発色数、およびピクセルレイアウトが描画先のウィンドウと正確に一致するイメージを作ることで、イメージをグラフィックス装置に効率よく移すことができます。これにより、drawImage は処理をすばやく実行できます。
BufferedImage オブジェクトを直接作成し、オフスクリーンバッファとして使うこともできます。この方法は、オフスクリーンイメージの種類または透明度を制御する必要がある場合に便利です。
次は、BufferedImage でサポートされている定義済みのイメージです。
BufferedImage オブジェクトは、アルファチャネルを含むことができます。図 5-3 では、アルファチャネルを使って、描画される領域と描画されない領域を区別し、すでに描画されているグラフィック (この場合はシェーディングされた矩形) の上に不規則な図形を表示できます。また、アルファチャネルを使うと、既存のイメージの色と新しいイメージの色を混合することもできます。注: 透明度の指定のためにアルファイメージデータが必要な場合以外は、つまり図 5-2 に示す不規則な形状のイメージを描画するような場合は、アルファ情報を持つオフスクリーンバッファの作成を避ける必要があります。必要がない場合にアルファ値を使うと、レンダリングのパフォーマンスが低下します。
GraphicsConfiguration では、使っている構成と互換性のある形式で、バッファリングされたイメージを自動的に作成する便利なメソッドが提供されています。また、ウィンドウが存在するグラフィックス装置に関するグラフィックス構成を問い合わせて、互換性のある BufferedImage オブジェクトの作成に必要な情報を取得することもできます。
バッファのイメージに描画するには、その BufferedImage.createGraphics メソッドを呼び出します。このメソッドからは、Graphics2D オブジェクトが返されます。このオブジェクトを使うと、すべての Graphics2D 系メソッドを呼び出して、グラフィックスプリミティブを描画したり、テキストを配置したり、イメージにほかのイメージをレンダリングしたりできます。この描画技法は、2D イメージングパッケージで提供されているディザリングなどの拡張機能をサポートしています。次のコードは、オフスクリーンバッファリングの使用方法を示したものです。
public void update(Graphics g){ Graphics2D g2 = (Graphics2D)g; if(firstTime){ Dimension dim = getSize(); int w = dim.width; int h = dim.height; area = new Rectangle(dim); bi = (BufferedImage)createImage(w, h); big = bi.createGraphics(); rect.setLocation(w/2-50, h/2-25); big.setStroke(new BasicStroke(8.0f)); firstTime = false; } // Clears the rectangle that was previously drawn. big.setColor(Color.white); big.clearRect(0, 0, area.width, area.height); // Draws and fills the newly positioned rectangle to the buffer. big.setPaint(strokePolka); big.draw(rect); big.setPaint(fillPolka); big.fill(rect); // Draws the buffered image to the screen. g2.drawImage(bi, 0, 0, this); }
BufferedImage に直接描画する以外に、2 種類の方法で、イメージのピクセルデータに直接アクセスして操作することができます。「イメージの処理と拡張」で説明されているように、この技法は、BufferedImageOp のフィルタリングインタフェースを実装する場合に役に立ちます。BufferedImage.setRGB メソッドを使うと、ピクセルまたはピクセル配列の値に特定の RGB 値を直接設定できます。ただし、ピクセルを直接変更すると、ディザリングは行われません。また、BufferedImage に関連する WritableRaster オブジェクトを操作することによってピクセルデータを操作することもできます。詳細については、「Raster の管理と操作」を参照してください。
BufferedImage インタフェースを実装するオブジェクトを使って、BufferedImageOp にフィルタリング操作を適用できます。フィルタリングおよびこのフィルタリングインタフェースを提供するクラスについては、「イメージの処理と拡張」を参照してください。
バッファリングされたイメージを特定のコンテキストにレンダリングするには、コンテキストの Graphics オブジェクトで提供されている drawImage メソッドのどれかを呼び出します。たとえば、Component.paint メソッドの中でレンダリングするときは、メソッドに渡されたグラフィックスオブジェクトの drawImage メソッドを呼び出します。
public void paint(Graphics g) { if (getSize().width <= 0 || getSize().height <= 0) return; Graphics2D g2 = (Graphics2D) g; if (offImg != null && isShowing()) { g2.drawImage(offImg, 0, 0, this); } }