目次 | 前へ | 次へ

第 5 章

イメージング

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

  • 旧バージョンの JDK で提供されているプロデューサ/コンシューマ (プッシュ) モデル。
  • Java™ 2 SDK で導入された直接方式モデル。
  • 直接方式モデルと互換性のあるパイプライン (プル) モデル。将来の Java Advanced Imaging API で完全に実装される。

次の表は、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 Advanced Imaging API)
長所
  • ネットワーク経由などでイメージの可用性によって引き出される処理
  • インクリメンタルに処理されるイメージ
  • もっとも単純なプログラミングインタフェース
  • 共通使用モデル
  • 必要なデータのみを格納/処理
  • 消極的評価の許容
短所
  • 処理せずに転送を要求
  • より複雑なプログラミングインタフェース
  • イメージ全体のメモリー割り当てが必要
  • イメージ全体の処理が必要
  • より複雑なプログラミングインタフェース
  • より複雑な実装

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

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

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

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

インタフェース
説明
BufferedImageOp
BufferedImage オブジェクトで実行される単一入力/単一出力の操作を記述します。AffineTransformOpColorConvertOpConvolveOpLookupOp、および RescaleOp によって実装されます。
RasterOp
Raster オブジェクトで実行される単一入力/単一出力の操作を定義します。AffineTransformOpBandCombineOpColorConvertOpConvolveOpLookupOp、および RescaleOp によって実装されます。
RenderedImage
Rasters の形式のイメージデータを含む、または生成できるオブジェクトに対する共通プロトコルを定義します。
WritableRenderedImage
スーパークラス: RenderedImage
変更が可能な Rasters の形式のイメージデータを含む、または生成できるオブジェクトに対する共通プロトコルを定義します。
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))
整数型のデータを格納するデータバッファーです (Java Advanced Imaging API で使われます)。
DataBufferShort
スーパークラス:DataBuffer (final)
short 型のデータを格納するデータバッファーです (Java Advanced Imaging API で使われます)。
DataBufferUShort
スーパークラス:DataBuffer (final)
符号なし short 型のデータを格納するデータバッファーです。
Kernel
入力ピクセルとその周囲のピクセルが ConvolveOp フィルタリング操作の出力ピクセルの値に与える影響を記述する行列です。
LookupTable
スーパークラス: Object
単一バンド化されたピクセルデータの値をカラー値にマッピングするテーブルです。
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
インタフェース: BufferedImageOp, RasterOp
ソースイメージのデータに対しピクセル単位のカラー変換を行います。
ConvolveOp
インタフェース: BufferedImageOp, RasterOp
Kernel を使って、ソースイメージの畳み込みを行います。畳み込みは、入力ピクセルの周囲のピクセルにカーネル値を掛けて出力ピクセルの値を生成する空間演算です。Kernel は、入力ピクセルに隣接するピクセルと出力ピクセルの間の関係を数学的に定義しています。
LookupOp
インタフェース: BufferedImageOp, RasterOp
ソースからデスティネーションへのルックアップ操作を行います。Rasters の場合、ルックアップはサンプル値に対して行われます。BufferedImages の場合、ルックアップはカラー成分とアルファ成分に対して行われます。
RescaleOp
インタフェース: BufferedImageOp, RasterOp
ソースイメージのデータについて、ピクセル単位の再スケーリングを行います。そのためには、各ピクセルの値にスケーリング係数を掛けてから、オフセットを加えます。

5.1.4 サンプルモデルクラス

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

5.1.5 カラーモデルクラス

クラス
説明
ColorModel
インタフェース: Transparency
JDK 1.1 のクラスです。イメージのピクセル値を赤、緑、青などの色成分に変換するメソッドを定義している抽象クラスです。
ComponentColorModel
スーパークラス: ColorModel
任意の ColorSpace と色成分の配列を処理し、その ColorSpace に適合させることのできる ColorModel です。このクラスを使うと、ほとんどの種類の GraphicsDevices 上で大半のカラーモデルを表すことができます。
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 オブジェクトには、ほかの 2 つのオブジェクト (Raster オブジェクトと ColorModel オブジェクト) が含まれています。

Raster クラスは、イメージデータの管理機能を提供します。Raster クラスは、イメージの矩形座標を表し、メモリーにイメージデータを保持し、単一のイメージデータバッファーから複数のサブイメージを作成するメカニズムを提供します。また、イメージ内の特定のピクセルにアクセスするためのメソッドも提供しています。Raster オブジェクトには、2 つのオブジェクト (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 でサポートされている定義済みのイメージ型を次に示します。

  • TYPE_3BYTE_BGR
  • TYPE_4BYTE_ABGR
  • TYPE_4BYTE_ABGR_PRE
  • TYPE_BYTE_BINARY
  • TYPE_BYTE_GRAY
  • TYPE_BYTE_INDEXED
  • TYPE_CUSTOM
  • TYPE_INT_ARGB_PRE
  • TYPE_INT_ARGB
  • TYPE_INT_BGR
  • TYPE_INT_RGB
  • TYPE_USHORT_555_RGB
  • TYPE_USHORT_565_RGB
  • TYPE_INT_GRAY

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 クラスでは、DataBuffersSampleModels を指定して Rasters を作成するための 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 クラスのインスタンス変数を使用して DataBuffer およびサンプルモデルにアクセスすることもできます。これらのオブジェクトでは、Raster のピクセルデータにアクセスして解釈するための別の手段が提供されています。

5.4.4 WritableRaster サブクラス

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

5.5 イメージデータと DataBuffer

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

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

  • DataBufferByte (8 ビット値を表す)
  • DataBufferInt (32 ビット値を表す)
  • DataBufferShort (16 ビット値を表す)
  • DataBufferUShort (符号なし short 値を表す)

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

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

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

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

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

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

  • ComponentSampleModel - DataBuffer の 1 つのバンクの独立したデータ配列要素群にサンプルデータが格納されているイメージからピクセルを抽出する。
  • BandedSampleModel - 個別のデータ要素に各サンプルが格納されているイメージからピクセルを抽出する。バンドは、連続したデータ要素に格納されている。
  • PixelInterleavedSampleModel - 個別のデータ要素に各サンプルが格納されているイメージからピクセルを抽出する。ピクセルは、連続したデータ要素に格納されている。
  • MultiPixelPackedSampleModel - 1 つのデータ要素に 1 つのサンプルの複数のピクセルが格納されている単一バンド化されたイメージからピクセルを抽出する。
  • SinglePixelPackedSampleModel - DataBuffer の最初のバンクにある 1 つのデータ配列要素に単一ピクセルのサンプルデータが格納されているイメージからサンプルを抽出する。

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

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

5.7 ColorModel とカラーデータ

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

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

  • PackedColorModel - 整数型ピクセルのビットに色成分が直接埋め込まれているピクセル値を表す抽象 ColorModel クラス。DirectColorModel は、PackedColorModel のサブクラスです。
  • DirectColorModel - ピクセル自体のビットに RGB の色成分が直接埋め込まれているピクセル値を表す ColorModelDirectColorModel モデルの表示は X11 の TrueColor と類似しています。
  • ComponentColorModel - 任意の ColorSpace と色成分の配列を処理し、その ColorSpace に適合させることのできる ColorModel
  • IndexColorModel - sRGB の色空間にある固定カラーマップへのインデックスであるピクセル値を表す ColorModel

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

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

5.7.1 ルックアップテーブル

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

5.8 イメージの処理と拡張

image パッケージでは、BufferedImage オブジェクトと Raster オブジェクトに対する操作を定義する次の 2 つのインタフェースが提供されています。BufferedImageOp および RasterOp

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

図 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 である場合、デスティネーションイメージの輝度はソースと同一です。

 


目次 | 前へ | 次へ

Copyright © 1993, 2013, Oracle and/or its affiliates. All rights reserved.