18-1:BufferedImage と Raster

JDK1.2 から java.awt.imageパッケージに追加された新しいクラスの中で、 中心となるのが BufferedImage 及び Raster という名前のものです。 これらの意味と取り扱いについて解説します。


・ BufferedImage は java.awt.Imageのサブクラスです。 なぜ新しいイメージのクラスが登場してきたのでしょうか?  元々 Imageクラスは非常に抽象化された存在でした。 これはアプリケーションが、 ハードウェアやウィンドウシステムの違いに依存しないようにするためです。 Imageクラス自体が抽象クラスで、 コンストラクタによるオブジェクトの生成は勝手に行えません。 通常、Imageのオブジェクトの生成は java.awt.Toolkitクラスによって行われます。 また Imageのデータの元は、 ImageProducer というインターフェイスによって抽象化されます。 このような「ブラックボックス化」は手軽な反面、 きめ細かな処理を行いたい時に自由がききません。 たとえば Imageクラスそのものには、 内部のピクセル情報を取り出すメソッドすら用意されていません。
JDK1.1 からイメージのフィルタリングや個々のピクセル情報を取り出すための クラスが追加されました。 イメージの情報を取り出して加工するクラス(ImageFilter や PixelGrabber)は、 ImageConsumer というインターフェイスによって抽象化されます。
しかし Graphics2Dの導入によって、 イメージの線形変換や重ね合わせの処理などを効率良く行う必要が生じてきました。 そのためには、 やはりメモリ上にあるイメージの元のデータに直接アクセスする手段が必要でしょう。 ただし、そのためには解決すべき問題があります。 一般にイメージの元データがどのような形式で格納されているかは、 さまざまなケースがあります。 ディスプレイのハードウェアやウィンドウシステムの設定によっても 大きく左右されます。 ある場合にはモノクロ画像かもしれません。 逆に24ビットのフルカラーのデータがメモリ上に存在するかもしれません。 あるいはウィンドウシステムが管理するカラーマップのインデックスによって ピクセル情報が表されるかもしれません。
こうした違いを吸収するために導入されたクラスが Raster です。 Raster(およびそのサブクラス)は、 マシンやシステムに依存しない形式でメモリ上のデータへのアクセスを可能にします。 Rasterのサブクラスに WritableRasterがあります。 Rasterは読み出し専用の機能を提供するのに対して、 ピクセル情報を変更したいような場合には WritableRasterを利用します。


BufferedImage と Raster

・ サイズとデータ形式を指定して BufferedImageのオブジェクトを生成すると、 それに対応する Rasterのオブジェクトも自動的に生成されます。 この場合には BufferedImage の getRaster()メソッドによって、 WritableRasterのオブジェクトを取り出すことができます。 またデータ形式の指定には BufferedImageクラスに定義された static定数を利用します。


BufferedImage image
    = new BufferedImage( 64, 64, BufferedImage.TYPE_INT_RGB );
WritableRaster raster = image.getRaster();

先に WritableRasterのオブジェクトを生成し、 BufferedImageのオブジェクトを生成することもできます。 ただしその場合には、あらかじめ ColorModelの選択が必要で、 手順は少しややこしくなります。 ColorModelはピクセル値がどのような形式で与えられるのかを表します。 カラーマップのインデックスを使用する IndexColorModel、 直接にカラーのデータをピクセル値とする DirectColorModelなどの場合があります。


int[] cmap = new int[8];
cmap[0] = 0x00000000; cmap[1] = 0x00ff0000;
cmap[2] = 0x0000ff00; cmap[3] = 0x00ffff00;
cmap[4] = 0x000000ff; cmap[5] = 0x00ff00ff;
cmap[6] = 0x0000ffff; cmap[7] = 0x00ffffff;
IndexColorModel model
    = new IndexColorModel( 8, 8, cmap, 0, false, -1, true );
WritableRaster raster
    = model.createCompatibleWritableRaster( 64, 64 );
BufferedImage image
    = new BufferedImage( model, raster, false );