目次 | 前の項目 | 次の項目 JavaTM 2D API プログラマーズガイド

第 5 章

イメージング

Java 2D™ API では、3 種類のイメージングモデルがサポートされています。

次の表は、3 種類のイメージングモデルの機能を比較したものです。

 
プッシュモデル
中間方式イメージバッファモデル
プルモデル
主要なインタフェースとクラス
  • Image
  • ImageProducer
  • ImageConsumer
  • ImageObserver
    (JDK 1.0.x, 1.1.x)
  • BufferedImage
  • Raster
  • BufferedImageOp
  • RasterOp
    (JavaTM 2D API)
  • RenderableImage
  • RenderableImageOp
    (Java 2D API)
  • RenderedOp
  • RenderableOp
  • TiledImage
    (Java 拡張イメージング API)
長所
  • ネットワーク経由などでイメージの可用性によって引き出される処理
  • インクレメンタルに処理されるイメージ
  • もっとも単純なプログラミングインタフェース
  • 共通使用モデル
  • 必要なデータのみを格納/処理
  • 消極的評価の許容
短所
  • 処理せずに転送を要求
  • より複雑なプログラミングインタフェース
  • イメージ全体のメモリ割り当てが必要
  • イメージ全体の処理が必要
  • より複雑なプログラミングインタフェース
  • より複雑な実装

この章では、直接方式イメージングモデルのオブジェクトと技法について説明します。Java 2D API の直接方式イメージング用のクラスとインタフェースでは、メモリにデータが格納されているピクセルにマッピングされたイメージを扱うための技法が提供されています。この API は、さまざまな形式で記憶されているイメージデータへのアクセスと、何種類かのフィルタリング操作を使ったイメージデータの処理をサポートしています。

5.1 インタフェースとクラス

Java 2D™ API の直接方式イメージング API は、インタフェース、イメージデータクラス、イメージ操作クラス、サンプルモデルクラス、カラーモデルクラス、および例外の 6 種類に分類できます。

5.1.1 イメージングインタフェース

インタフェース
説明
BufferedImageOp
BufferedImage オブジェクトで実行される単一入力/単一出力の操作を記述します。AffineTransformOpColorConvertOpConvolveOpLookupOp、および RescaleOp で実装されます。
RasterOp
Raster オブジェクトで実行される単一入力/単一出力の操作を定義します。AffineTransformOpBandCombineOpColorConvertOpConvolveOpLookupOp、および RescaleOp で実装されます。
RenderedImage
Raster の形式のイメージデータを含む、または生成できるオブジェクトに対する共通プロトコルを定義します。
WritableRenderedImage
スーパークラス: RenderedImage
変更が可能な Raster の形式のイメージデータを含む、または生成できるオブジェクトに対する共通プロトコルを定義します。
TileObserver
WritableRenderedImage の変更状態が変化したときに通知する必要があるオブジェクトのためのプロトコルを定義します。

5.1.2 イメージデータクラス

クラス
説明
BufferedImage
スーパークラス: Image
インタフェース: WriteableRenderedImage
アクセス可能なデータバッファのあるイメージです。BufferedImage には、イメージデータの ColorModelRaster が含まれます。
ByteLookupTable
スーパークラス: LookupTable
バイトデータを含む LookupTable です。
DataBuffer
ピクセルデータを保持する 1 つ以上のデータ配列をラップします。各データ配列を「バンク」と呼びます。
DataBufferByte
スーパークラス: DataBuffer (Final)
バイト型のデータを格納するデータバッファです。(Java Advanced Imaging API で使われます)。
DataBufferInt
スーパークラス: DataBuffer (Final)
int 型のデータを格納するデータバッファです (Java Advanced Imaging API で使われます)。
DataBufferShort
スーパークラス: DataBuffer (Final)
short 型のデータを格納するデータバッファです (Java Advanced Imaging API で使われます)。
DataBufferUShort
スーパークラス: DataBuffer (Final)
符号なし short 型のデータを格納するデータバッファです。
Kernel
入力ピクセルとその周囲のピクセルが ConvolveOp フィルタリング操作の出力ピクセルの値に与える影響を記述するマトリックスです。
LookupTable
スーパークラス: オブジェクト
単一バンド化されたピクセルデータの値をカラー値にマッピングするテーブルです。
Raster
イメージデータを取り出すことのできるピクセルの矩形配列です。Raster には、DataBufferSampleModel が含まれています。
ShortLookupTable
スーパークラス: LookupTable
short 型のデータを含むルックアップテーブルです。
WritableRaster
スーパークラス: Raster
変更できる Raster です。

5.1.3 イメージ操作クラス

クラス
説明
AffineTransformOp
インタフェース: BufferedImageOp, RasterOp
変換元の Image または Raster の 2 次元座標から、変換先の Image または Raster の 2 次元座標への線形変換を行うアフィン変換を定義するクラスです。このクラスでは、双一次または最近傍のアフィン変換操作を実行できます。
BandCombineOp
インタフェース: RasterOp
指定されたマトリックスを使って、Raster のバンドの任意の線形結合を実行します。
BufferedImageFilter
スーパークラス: ImageFilter
BufferedImageOp (単一ソース/単一デスティネーションのイメージ演算子) を使って BufferedImage または Raster のフィルタリングを行うための簡単な手段を提供する ImageFilter です。
ColorConvertOp
インタフェース: BufferedImageOpRasterOp
ソースイメージのデータに対しピクセル単位のカラー変換を行います。
ConvolveOp
インタフェース: BufferedImageOpRasterOp
Kernel を使って、ソースイメージの畳み込みを行います。畳み込みは、入力ピクセルの周囲のピクセルにカーネル値を掛けて出力ピクセルの値を生成する空間演算です。Kernel は、入力ピクセルに隣接するピクセルと出力ピクセルの間の関係を数学的に定義しています。
LookupOp
インタフェース: BufferedImageOpRasterOp
ソースからデスティネーションへのルックアップ操作を行います。Raster の場合、ルックアップはサンプル値に対して行われます。BufferedImage の場合は、カラー成分とアルファ成分に対して行われます。
RescaleOp
インタフェース: BufferedImageOpRasterOp
ソースイメージのデータについて、ピクセル単位の再スケーリングを行います。 そのためには、各ピクセルの値にスケーリング係数を掛けてから、オフセットを加えます。

5.1.4 サンプルモデルクラス

クラス
説明
BandedSampleModel
スーパークラス: ComponentSampleModel (Final)
格納されているイメージデータへのアクセスを提供します。 サンプルは、DataBuffer の個別のバンクのバンドとして格納されています。1 つのピクセルは、各バンドから得られる 1 つのサンプルで構成されます。
ComponentSampleModel
スーパークラス: SampleModel
格納されているイメージデータへのアクセスを提供します。 ピクセルの各サンプルは、DataBuffer の独立した要素の中にあります。ピクセルの異なる種類のインタリーブがサポートされています。
MultiPixelPackedSampleModel
スーパークラス: SampleModel
格納されているイメージデータへのアクセスを提供します。 1 つのサンプルの複数のピクセルが、DataBuffer の 1 つの要素に収められています。
PixelInterleavedSampleModel
スーパークラス: ComponentSampleModel
格納されているイメージデータへのアクセスを提供します。 各ピクセルのサンプルデータはデータ配列の隣接する要素に収められており、すべての要素は DataBuffer の単一のバンクに収められています。
SampleModel
基になっているデータが DataBuffer にどのように格納されているか知らない状態で、イメージからサンプルデータを抽出する方式を定義している abstract クラスです。
SinglePixelPackedSampleModel
スーパークラス: SampleModel
イメージデータへのアクセスを提供します。 個別のピクセルに属するすべてのサンプルが、DataBuffer の 1 つの要素に格納されています。

5.1.5 カラーモデルクラス

クラス
説明
ColorModel
インタフェース: Transparency
JDK 1.1 のクラスです。イメージのピクセル値を赤、緑、青などの色成分に変換するメソッドを定義している抽象クラスです。
ComponentColorModel
スーパークラス: ColorModel
任意の ColorSpace と色成分の配列を処理して ColorSpace に適合させることのできる ColorModel です。このクラスを使うと、大部分の GraphicsDevice のほとんどのカラーモデルを表現できます。
DirectColorModel
スーパークラス: PackedColorModel
JDK 1.1 のクラスです。この ColorModel は、ピクセルのビットに RGB の色成分が直接埋め込まれているピクセル値を表します。X11 の TrueColor と類似したカラーモデルです。ColorModel.getRGBdefault から返されるデフォルトの RGB の ColorModel は、DirectColorModel です。
IndexColorModel
スーパークラス: ColorModel
JDK 1.1 のクラスです。この ColorModel は、sRGB の ColorSpace にある固定カラーマップへのインデックスであるピクセル値を表します。
PackedColorModel
スーパークラス: ColorModel
この抽象 ColorModel クラスは、ピクセルのビットに色成分が直接埋め込まれているピクセル値を表します。RGB の色成分を含むピクセルをサポートするため、DirectColorModelPackedColorModel を継承しています。

5.1.6 例外クラス

クラス
説明
ImagingOpException
スーパークラス: RuntimeException
BufferedImageOp または RasterOp のフィルタメソッドがイメージを処理できない場合にスローされます。
RasterFormatException
スーパークラス: RuntimeException
Raster に無効なレイアウト情報がある場合にスローされます。

5.2 即時モードイメージングのコンセプト

直接方式イメージングモデルは、メモリに格納されている固定解像度のイメージに対応しています。また、イメージデータに対するフィルタリング操作もサポートしています。このモデルでは、多くのクラスとインタフェースが使われています。

次の文で、このグラフィックスを説明しています。

図 5-1 BufferedImage とサポートクラス

図 5-1 に示すように、BufferedImage はイメージの全体的な管理機能を提供します。BufferedImage はメモリ内に直接作成でき、それを使って、ファイルまたは URL から取得したイメージデータを保持および操作できます。BufferedImage は、任意の Graphics2D オブジェクトを使って画面装置に表示したり、適当な Graphics2D コンテキストを使ってほかの出力先にレンダリングしたりできます。BufferedImage オブジェクトには、Raster オブジェクトと ColorModel オブジェクトが含まれています。

Raster クラスは、イメージデータの管理機能を提供します。Raster クラスは、イメージの矩形座標を表し、メモリにイメージデータを保持し、単一のイメージデータバッファから複数のサブイメージを作成する仕組みを提供します。また、イメージ内の特定のピクセルにアクセスするためのメソッドも提供しています。Raster オブジェクトには、DataBuffer オブジェクトと SampleModel オブジェクトが含まれています。

DataBuffer クラスは、メモリ内にピクセルデータを保持します。

SampleModel クラスは、バッファのデータを解釈し、それを個別のピクセルまたはピクセルの矩形範囲として提供します。

ColorModel クラスは、イメージのサンプルモデルで提供されるピクセルデータの色を解釈する機能を提供します。

image パッケージでは、ほかに、BufferedImage オブジェクトと Raster オブジェクトに対するフィルタリング操作を定義するクラスが提供されています。イメージ処理のそれぞれの操作は、BufferedImageOp インタフェースと RasterOp インタフェースのどちらかまたはその両方を実装するクラスに埋め込まれています。操作クラスでは、実際のイメージ操作を行う filter メソッド群が定義されています。

図 5-2 は、Java 2D™ API のイメージ処理の基本的なモデルです。

流れ図に、ソースイメージがデスティネーションイメージになる前にイメージ処理過程を流れる様子を示します。

図 5-2 イメージ処理モデル

イメージ操作では、次の機能がサポートされています。

イメージの表示と操作だけが必要な場合は、BufferedImage クラスとフィルタリング操作クラスを理解するだけで十分です。一方、フィルタを記述したりイメージデータに直接アクセスしたりする場合は、BufferedImage クラスと関連のあるクラスを理解する必要があります。

5.2.1 用語

次の用語は、このあとの説明で使われているものです。

データ要素: イメージデータを記憶する単位として使われているプリミティブ型です。DataBuffer 配列の個々のメンバです。データバッファ内の要素のレイアウトは、イメージの SampleModel によって行われるピクセルとしてのデータの解釈には依存しません。

サンプル: イメージのピクセルを構成する個別のメンバです。SampleModel は、DataBuffer の要素をピクセルとそのサンプルに変換する仕組みを提供します。ピクセルのサンプルは、特定のカラーモデルの基本的な値を表す場合があります。たとえば、RGB カラーモデルのピクセルは、赤、緑、青という 3 つのサンプルで構成されています。

成分: 色の解釈に依存しないピクセルの値です。成分とサンプルの違いは、IndexColorModel で役に立ちます。IndexColorModel の場合、ピクセルの成分は LookupTable のインデックスになります。

バンド: イメージに含まれる同じ種類の全サンプルの集合です。 たとえば、赤の全サンプルや緑の全サンプルなどです。ピクセルデータはさまざまな方法で格納できますが、Java 2D API では、バンド化方式とピクセルインタリーブ化方式の 2 種類がサポートされています。バンド化記憶方式の場合、イメージデータはバンドの単位で編成されて、ピクセルは各バンドの同じ位置にあるサンプルデータで構成されます。ピクセルインタリーブ化記憶方式の場合は、イメージデータはピクセル単位に編成されます。 すべてのピクセルが 1 つの配列に含まれていて、バンドは各ピクセルの同じインデックス位置にあるサンプルの集合で構成されます。

原色: 特定のカラーモデルにおけるカラー値の個別のメンバです。 たとえば、RGB モデルでは、原色の赤と緑と青からカラー値を生成します。

5.3 BufferedImage クラスの使用方法

BufferedImage クラスは、直接イメージングモードのサポートで中心となるクラスです。メモリ内のイメージを管理し、ピクセルデータを格納および解釈したり、Graphics コンテキストまたは Graphics2D コンテキストにピクセルデータをレンダリングしたりする手段を提供しています。

5.3.1 BufferedImage の作成

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 をメモリ内に作成することもできます。

5.3.2 オフスクリーンバッファでの描画

BufferedImage クラスを使うと、グラフィック要素をオフスクリーンの状態で用意し、それを画面にコピーすることができます。この方法は、グラフィックが複雑な場合、または 1 つのグラフィックを繰り返し使う場合に、特に有効です。たとえば、複雑な図形を何度も表示する必要がある場合は、オフスクリーンバッファにその図形を一度描画してから、ウィンドウの別の場所にそれをコピーします。一度描画した図形をコピーすることで、グラフィックの表示を高速化できます。

java.awt パッケージでは、ウィンドウに描画する場合と同じ方法で Image オブジェクトに描画できるので、簡単にオフスクリーンバッファを使うことができます。オフスクリーンイメージに描画するときも、Java 2D™ API のすべてのレンダリング機能を使用できます。

オフスクリーンバッファは、アニメーションでよく使われます。たとえば、オフスクリーンバッファを使ってオブジェクトを 1 回描画し、ウィンドウの中でそれを動き回らせるような使い方をします。同様に、ユーザがマウスを使ってグラフィックを移動させるときのフィードバックにも、オフスクリーンバッファを利用します。すべてのマウス位置でグラフィックを描画するのではなく、一度オフスクリーンバッファに描画したグラフィックを、ユーザがマウスをドラッグするのに合わせて、マウスの位置にコピーします。1

次のコンテキストでこのグラフィックスを説明します。

図 5-3 オフスクリーンバッファの使用方法

図 5-3 は、オフスクリーンイメージに描画してからそのイメージをウィンドウに何回もコピーしているプログラムの例です。最後にイメージをコピーするときは、イメージを変換しています。変換を指定してイメージを再描画する代わりに描画されているイメージを変換すると、不十分な結果になる場合があることに注意してください。

5.3.2.1 オフスクリーンバッファの作成

オフスクリーンバッファとして使用できるイメージを作る場合は、Component.createImage メソッドを使うのがもっとも簡単な方法です。

色空間、発色数、およびピクセルレイアウトが描画先のウィンドウと正確に一致するイメージを作ることで、イメージをグラフィックス装置に効率よく移すことができます。これにより、drawImage は処理をすばやく実行できます。

BufferedImage オブジェクトを直接作成し、オフスクリーンバッファとして使うこともできます。この方法は、オフスクリーンイメージの種類または透明度を制御する必要がある場合に便利です。

次は、BufferedImage でサポートされている定義済みのイメージです。

BufferedImage オブジェクトは、アルファチャネルを含むことができます。図 5-3 では、アルファチャネルを使って、描画される領域と描画されない領域を区別し、すでに描画されているグラフィック (この場合はシェーディングされた矩形) の上に不規則な図形を表示できます。また、アルファチャネルを使うと、既存のイメージの色と新しいイメージの色を混合することもできます。

注:透明度の指定のためにアルファイメージデータが必要な場合以外は、つまり図 5-2 に示す不規則な形状のイメージを描画するような場合は、アルファ情報を持つオフスクリーンバッファの作成を避ける必要があります。必要がない場合にアルファ値を使うと、レンダリングのパフォーマンスが低下します。

GraphicsConfiguration では、使っている構成と互換性のある形式で、バッファリングされたイメージを自動的に作成する便利なメソッドが提供されています。また、ウィンドウが存在するグラフィックス装置に関するグラフィックス構成を問い合わせて、互換性のある BufferedImage オブジェクトの作成に必要な情報を取得することもできます。

5.3.2.2 オフスクリーンバッファでの描画

バッファのイメージに描画するには、その 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); 
             
    } 
 

5.3.3 BufferedImage データの直接的な操作

BufferedImage に直接描画する以外に、2 種類の方法で、イメージのピクセルデータに直接アクセスして操作することができます。「イメージの処理と拡張」で説明されているように、この技法は、BufferedImageOp のフィルタリングインタフェースを実装する場合に役に立ちます。

BufferedImage.setRGB メソッドを使うと、ピクセルまたはピクセル配列の値に特定の RGB 値を直接設定できます。ただし、ピクセルを直接変更すると、ディザリングは行われません。また、BufferedImage に関連する WritableRaster オブジェクトを操作することによってピクセルデータを操作することもできます。 詳細については、「Raster の管理と操作」を参照してください。

5.3.4 BufferedImage のフィルタリング

BufferedImageOp インタフェースを実装するオブジェクトを使って、BufferedImage にフィルタリング操作を適用できます。フィルタリングおよびこのフィルタリングインタフェースを提供するクラスについては、「イメージの処理と拡張」を参照してください。

5.3.5 BufferedImage のレンダリング

バッファリングされたイメージを特定のコンテキストにレンダリングするには、コンテキストの 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); 
        } 
    } 

5.4 Raster の管理と操作

BufferedImage オブジェクトは、Raster を使ってピクセルデータの矩形配列を管理します。Raster クラスでは、イメージの座標系のためのフィールドとして、幅、高さ、および原点が定義されています。Raster オブジェクト自体は、DataBufferSampleModel という 2 つのオブジェクトを使って、ピクセルデータを管理します。DataBuffer はラスタのピクセルデータを格納するオブジェクトで (「イメージデータと DataBuffer」を参照)、SampleModelDataBuffer からのピクセルデータの解釈を提供します (「SampleModel からのピクセルデータの抽出」を参照)。

5.4.1 Raster の作成

ほとんどの場合、Raster を直接作る必要はありません。 メモリに BufferedImage を作ると、Raster が必ず提供されます。ただし、BufferedImage コンストラクタメソッドを使うと、WritableRaster を渡して Raster を作成できます。

Raster クラスでは、DataBufferSampleModel を指定して Raster を作成するための static ファクトリメソッドがいくつか提供されています。RasterOp フィルタリングクラスを実装するときは、これらのファクトリを使うことができます。

5.4.2 親と子のラスタ

Raster クラスには、親ラスタと子ラスタのコンセプトが組み込まれています。これにより、同じ親からいくつでもバッファリングされたイメージを作成できるので、記憶効率を向上させることができます。親とその子はすべて同じデータバッファを参照し、それぞれの子は、バッファ内で自分のイメージの場所を識別するために固有のオフセットと境界を持っています。子は、getParent メソッドを使って所有権を識別します。

サブラスタを作成するには、Raster.createSubRaster メソッドを使います。サブラスタを作成する際には、サブラスタがカバーする親の領域と親の原点からのオフセットを指定します。

5.4.3 Raster に対する操作

Raster クラスでは、ピクセルとピクセルデータにアクセスするためのさまざまな方法が定義されています。これらの方法は、RasterOp インタフェースを実装するとき、または低レベルのピクセル操作を行う必要のあるメソッドを実装するときに、役に立ちます。 RasterOp インタフェースは、イメージデータに対するラスタレベルのフィルタリングおよび操作を提供します。

Raster.getPixel メソッドを使うと、ピクセルを個別に取得できます。 ピクセルは、配列の中の個別のサンプルとして返されます。Raster.getDataElements メソッドからは、指定した一連の解釈されていないイメージデータが DataBuffer から取り出されて返されます。Raster.getSample メソッドからは、個別のピクセルのサンプルが返されます。getSamples メソッドからは、イメージの特定の範囲に対するバンドが返されます。

これらのメソッドのほかに、Raster クラスのインスタンス変数を通して、データバッファとサンプルモデルにアクセスすることもできます。これらのオブジェクトでは、Raster のピクセルデータにアクセスして解釈するための別の手段が提供されています。

5.4.4 WritableRaster サブクラス

WritableRaster サブクラスでは、ピクセルデータとサンプルを設定するメソッドが提供されます。BufferedImage に関連する Raster は実際には WritableRaster なので、ピクセルデータの操作に必要なすべてのアクセスが提供されます。

5.5 イメージデータと DataBuffer

Raster に属している DataBuffer は、イメージデータの配列を表します。直接または BufferedImage のコンストラクタを使って Raster を作るときは、ピクセルで幅と高さを指定するとともに、イメージデータの SampleModel を指定します。この情報を使って、適切なデータ種類とサイズの DataBuffer が作成されます。

DataBuffer には 3 つのサブクラスがあり、それぞれが異なる種類のデータ要素を表しています。

前で定義したように、要素はデータバッファの配列の連続していないメンバで、成分またはサンプルは、まとめられてピクセルを形成する不連続の値です。DataBuffer に格納されている特定の種類の要素と、SampleModel で表される特定の種類のピクセルの間には、さまざまなマッピングが考えられます。このようなマッピングを実装し、特定の DataBuffer から特定のピクセルを取得する手段を提供するのは、SampleModel のさまざまなサブクラスの役割です。

DataBuffer のコンストラクタは、特定のサイズで特定の数のバンクを持つバッファを作成するための手段を提供します。

DataBuffer のイメージデータには直接アクセスできますが、一般に、Raster クラスと WritableRaster クラスのメソッドを使ってアクセスする方が簡単で便利です。

5.6 SampleModel からのピクセルデータの抽出

抽象クラスの SampleModel では、基になっているデータの格納方法を知らなくてもイメージのサンプルを抽出できるメソッドが定義されています。このクラスは、関連する DataBuffer のイメージデータの高さと幅を追跡するためのフィールドと、そのバッファのバンド数とデータ種類を記述するためのフィールドを提供しています。SampleModel のメソッド群はピクセルの集合としてイメージデータを提供し、各ピクセルは多くのサンプルまたは成分で構成されています。

java.awt.image パッケージでは、5 種類のサンプルモデルが提供されています。

データソースの種類により、SampleModel で表されるピクセルデータと特定のカラーモデルのカラーデータ表現との間には、直接的な相互関係がある場合とない場合があります。たとえば、写真イメージデータの場合、サンプルは RGB データを表す場合があります。医療用画像装置のイメージデータの場合は、温度や骨密度など、異なる種類のデータをサンプルが表している可能性があります。

イメージデータにアクセスするためのメソッドには、3 つの種類があります。getPixel 系メソッドは、サンプルごとに 1 つのエントリがある配列としてピクセル全体を返します。getDataElement メソッドを使うと、DataBuffer に格納されている解釈されていない未処理のデータにアクセスできます。getSample メソッドは、特定のバンドのピクセル成分に対するアクセスを提供します。

5.7 ColorModel とカラーデータ

Raster オブジェクトはイメージデータを管理するためのものですが、BufferedImage クラスには、これ以外に、カラーピクセル値としてデータを解釈する ColorModel が含まれています。abstract クラスの ColorModel では、イメージのピクセルデータを対応する ColorSpace のカラー値に変換するメソッドが定義されています。

java.awt.image パッケージでは、4 種類のカラーモデルが提供されています。

ComponentColorModelPackedColorModel は、Java™ 2 SDK で新しく導入されたものです。

DataBuffer のデータに基づいて、SampleModelColorModel にピクセルを提供し、ColorModel はそのピクセルを色として解釈します。

5.7.1 ルックアップテーブル

ルックアップテーブルには、チャネルまたはイメージの成分のデータが含まれています。たとえば、赤と緑と青の独立した配列などです。java.awt.image パッケージでは、バイト型のデータを含むもの (ByteLookupTable) と short 型のデータを含むもの (ShortLookupData) の 2 種類のルックアップテーブルが定義されていて、どれも abstract LookupTable クラスを継承しています。

5.8 イメージの処理と拡張

image パッケージでは、2 つのインタフェース BufferedImageRaster が提供されています。これらのインタフェースは、それぞれが、BufferedImageOpRasterOp に対する操作を定義しています。

これらのインタフェースを実装するクラスとしては、AffineTransformOpBandCombineOpColorConvertOpConvolveOpLookupOpRescaleOp があります。これらのクラスを使って、イメージに対する幾何学的変換、ぼかし、シャープ化、コントラスト強調、しきい値、色調補正などの処理を行うことができます。

図 5-4 は、輪郭の検出と強調の結果を示したものです。 この操作は、イメージ内の輝度の鋭い変化を強調するものです。輪郭の検出は、普通、医療用画像処理や地図アプリケーションで使われます。輪郭の検出を使うと、イメージ内の隣接する構造の間のコントラストが強くなり、より細部まで識別できるようになります。

前の文で、このグラフィックスを説明しています。

図 5-4 輪郭の検出と強調

次のコードは、輪郭の検出について記述したものです。

float[] elements = { 0.0f, -1.0f, 0.0f, 
                    -1.0f, 4.f, -1.0f, 
                    0.0f, -1.0f, 0.0f}; 
... 
 
BufferedImage bimg = new BufferedImage(bw,bh,BufferedImage.TYPE_INT_RGB); 
Kernel kernel = new Kernel(3, 3, elements); 
ConvolveOp cop = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, 		                                   null); 
cop.filter(bi,bimg); 

図 5-5 は、ルックアップテーブル操作の例です。ルックアップ操作は、ピクセルの個別のコンポーネントを変更する場合に使用できます。

前の文で、このグラフィックスを説明しています。

図 5-5 ルックアップテーブルの操作

次のコードは、ルックアップテーブル操作について記述したものです。

	byte reverse[] = new byte[256]; 
   for (int j=0; j<200; j++){  
       		reverse[j]=(byte)(256-j);  
	}	 
   	ByteLookupTable blut=new ByteLookupTable(0, reverse);  
   	LookupOp lop = new LookupOp(blut, null);  
   lop.filter(bi,bimg);   

図 5-6 は、再スケーリングの例です。再スケーリングでは、すべての点の輝度を強くしたり弱くしたりできます。再スケーリングを使うと、メリハリのないイメージのダイナミックレンジを拡大して、平板に見える領域の細部を際立たせることができます。

前の文で、このグラフィックスを説明しています。

図 5-6 再スケーリング

次のコードは、再スケーリングについて記述したものです。

	RescaleOp rop = new RescaleOp(1.5f, 1.0f, null); 
	rop.filter(bi,bimg); 

5.8.1 イメージ処理操作の使用方法

畳み込みは、ほとんどの空間フィルタリングアルゴリズムの基になっている処理です。畳み込みでは、イメージの各ピクセルの値と周囲のピクセルの値の間で重み付けを行なったり、平均化したりする処理が行われます。これにより、カーネルで数学的に指定できる方法に従って、出力される各ピクセルに周囲の隣接するピクセルからの影響を反映させることができます。図 5-7 は、畳み込みの例です。

前の文で、このグラフィックスを説明しています。

図 5-7 畳み込みを使ったぼかし

次に示すコードは、イメージ処理クラスの 1 つである ConvolveOp の使用方法の例です。次の例では、ソースイメージの各ピクセルは、隣接する 8 つのピクセルと均等に平均化されます。

float weight = 1.0f/9.0f;float[] elements = new float[9]; // create 2D array// fill the array with nine equal elements 
for (i = 0; i < 9; i++) {   elements[i] = weight;}// use the array of elements as argument to create a Kernelprivate Kernel myKernel = new Kernel(3, 3, elements);public ConvolveOp simpleBlur = new ConvolveOp(myKernel); 
 
// sourceImage and destImage are instances of BufferedImagesimpleBlur.filter(sourceImage, destImage) // blur the image 

変数 simpleBlur には、BufferedImage または Raster のぼかし操作を実装する ConvolveOp の新しいインスタンスが格納されます。sourceImage と destImage は、BufferedImage の 2 つのインスタンスとします。ConvolveOp クラスの核となるメソッドの filter を呼び出すと、ソースイメージのピクセルとそれを囲む 8 つのピクセルの値が平均化されて、デスティネーションイメージの対応するピクセルの値に設定されます。

この例の畳み込みカーネルは、4 桁の有効数字で指定される要素を持つ次の行列で表されます。

すべての値が 0.1111 の 3 × 3 のマトリックス。

イメージの畳み込みでは、デスティネーションイメージの各ピクセルの値は、そのピクセルの値と周囲のピクセルの値を平均化するときの荷重値の組としてカーネルを使って算出されます。この操作は、イメージのチャネルごとに行われます。

次の式は、畳み込みを行うときにカーネルの荷重値をソースイメージのピクセルと関連付ける方法を示しています。カーネルの各値は、イメージの空間位置に結び付けられます。

3 × 3 のマトリックス。最初の行の値は、i − 1、j − 1、i、j − 1、および i + 1、j − 1 です。2 番目の行の値は、i − 1、j、i、j、および i + 1、j です。3 番目の行の値は、i − 1、j + 1、i、j + 1、および i + 1、j + 1 です。

デスティネーションピクセルの値は、カーネルの荷重値と周囲のソースピクセルの値を掛けた積を合計したものです。多くの単純な操作では、カーネルは平行で対称の行列であり、荷重値を合計すると 1 になります。 2

この例の畳み込みカーネルは、比較的単純なものです。このカーネルでは、ソースイメージの各ピクセルが均等に荷重されます。ほかのカーネルを選択し、ソースイメージに対する荷重レベルを高くしたり低くしたりすることで、デスティネーションイメージの輝度を強くしたり弱くしたりできます。ConvolveOp コンストラクタで設定される Kernel オブジェクトで、実行されるフィルタリングの種類が決まります。ほかの値を設定すれば、ぼかし (ガウス、円形、移動など)、シャープ化、平滑化操作など、ほかの種類の積和演算を実行できます。図 5-8 は、畳み込みを使ったシャープ化の例です。

前の文で、このグラフィックスを説明しています。

図 5-8 畳み込みを使ったシャープ化

次に示すコードは、畳み込みを使ったシャープ化の例です。

float[] elements = { 0.0f, -1.0f, 0.0f, 
                    -1.0f,  5.f, -1.0f, 
                     0.0f, -1.0f,  0.0f}; 
... 
 
Kernel kernel = new Kernel(3,3,elements); 
ConvolveOp cop = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, 														null); 
	cop.filter(bi,bimg); 

1プログラマは、新たな位置にコピーを新規作成する前に、以前のバージョンのイメージを消去する必要があります。これは、バックグラウンドを再描画するか、別のオフスクリーンバッファからバックグラウンドをコピーすることによって行うことができます。
2行列内の荷重値の合計が 1 である場合、デスティネーションイメージの輝度はソースと同一です。

 


目次 | 前の項目 | 次の項目 JavaTM 2D API プログラマーズガイド
JavaTM 2 SDK, Standard Edition, 1.4 Version