目次|前|次 |
ImageReader
アプリケーションは、ImageIO
クラスを使用してイメージのデコード処理全体を実行するのではなく、ImageIO
クラスを使用してImageReader
オブジェクトを取得し(下のコード例を参照)、そのオブジェクトを使用して読込みを実行することができます。
Iterator readers = ImageIO.getImageReadersByFormatName("gif"); ImageReader reader = (ImageReader)readers.next();
読取りオブジェクトは、ファイルの内容、ファイルの拡張子またはMIMEタイプに基づいて取得することもできます。読取りオブジェクトを検索してインスタンス生成するメカニズムでは、javax.imageio.spi.ImageReaderSpi
クラスを利用します。このクラスを使用すると、プラグインを実際にインスタンス生成しなくても、読取りプラグインについての情報を取得できます。「サービス・プロバイダ・インタフェース」(service provider interface、SPI)の概念については、次の章で詳しく説明します。
読取りプラグインを取得した後は、そのオブジェクトに入力ソースを提供する必要があります。大部分の読取りオブジェクトは、ImageInputStream
からデータを読み取れます。これは、Image I/O APIによって定義されている特殊な入力ソースです。特殊な入力ソースを使用する目的は、読取りオブジェクトや書込みオブジェクトが、ファイル入出力とストリーム入出力の両方を簡単に処理できるようにすることです。
ImageInputStream
を取得するのは簡単です。入力ソースがFile
またはInputStream
の形式である場合、ImageInputStream
は、次のような呼出しによって生成できます。
Object source; // File or InputStream ImageInputStream iis = ImageIO.createImageInputStream(source);
ソースを取得した後は、次の呼出しによってそのソースを読取りオブジェクトに接続できます。
reader.setInput(iis, true);
この2番目のパラメータは、ソース・ファイルに複数のイメージが含まれていて、アプリケーションがそれらのイメージを順番に読み込めるという保証がない場合には、falseに設定する必要があります。1つのファイルに1つのイメージしか格納できないファイル形式の場合には、このパラメータに常にtrueを設定するようにします。
読込みオブジェクトに入力ソースを設定したあとは、必ずしもイメージ・データをメモリー内に読み込まないでも、そのオブジェクトを利用してイメージについての情報を入手できます。たとえば、reader.getImageWidth(0)
を呼び出せば、ファイルに格納されている最初のイメージの幅を入手できます。上手に作成されたプラグインであれば、イメージの幅を判別するのに必要なデータだけをデコードし、ピクセルは読み込まないようにするはずです。
イメージを読み込むには、アプリケーションからreader.read(imageIndex)
を呼び出します(imageIndex
は、ファイル内のイメージのインデックス)。この呼出しの結果は、上で説明したImageIO.read
を呼び出したときの結果と同じです。
ImageReadParam
読込み処理をさらに詳細に制御するには、read
メソッドにImageReadParam
型の追加パラメータを指定します。ImageReadParam
を使用すると、デコードされたイメージを格納するデスティネーション・イメージを指定できるので、メモリーの使用を効率よく制御できます。また、読み込みたい領域を指定することや、イメージの縮小版を取得するために利用できるサブサンプリング係数を指定することも可能です。
ソース領域が設定された場合は、ファイル形式が部分的なデコードを許しているかぎり、読込みプラグインは、設定された領域だけをデコードしようとします。どんな場合にも、設定された領域の外側にあるピクセルは出力されません。この機能により、非常に大きいイメージをかぎられた量のメモリーで処理することが可能になります。
たとえば、イメージの左上の4分の1区画だけをデコードするには、まず、読取りオブジェクトで使用するためのImageReadParam
を次のようにして取得します。
ImageReadParam param = reader.getDefaultReadParam();次に、読み込みたいソース領域を、次のようにして
ImageReadParam
に設定します。
import java.awt.Rectangle; int imageIndex = 0; int half_width = reader.getImageWidth(imageIndex)/2; int half_height = reader.getImageHeight(imageIndex)/2; Rectangle rect = new Rectangle(0, 0, half_width, half_height); param.setSourceRegion(rect);
そして最後に、このImageReadParam
を使用して、次のようにイメージを読み込みます。
BufferedImage bi = reader.read(imageIndex, param);
この結果として出力されるのは、幅と高さがそれぞれ元のイメージの半分になったBufferedImage
です(イメージの幅や高さが奇数の場合、端数は切り捨てられます)。
このあと、イメージの右下の4分の1区画を、左上の4分の1区画を保持するために作成した同じBufferedImage
に読み込むには、次のようにして以前のピクセル・データを上書きします。
param.setDestination(bi); rect = new Rectangle(half_width, half_height, half_width, half_height); param.setSourceRegion(rect); BufferedImage bi2 = reader.read(0, param); if (bi == bi2) { System.out.println("The same BufferedImage was used!"); } else { System.out.println("This can't happen!"); }
実際には、結果をどこに割り当てるかを指定せずに、単にreader.read(0, param)
を呼び出すこともできます。ピクセルは既存のBufferedImage
であるbi
に書き込まれるということがわかっているからです。
別の例としては、イメージのピクセルを3つに1つの割合で読み込み、元のサイズの9分の1のイメージを生成するため、次のようにして、ImageReadParam
にサブサンプリング係数を設定することもあります。
param = reader.getDefaultImageParam(); param.setSourceSubsampling(3, 3, 0, 0); BufferedImage bi3 = reader.read(0, param);
IIOParamController
プラグインは、オプションとして、IIOParamController
オブジェクトを提供できます。このオブジェクトは、IIOReadParam
(またはIIOWriteParam
)を、グラフィカル・ユーザー・インタフェース(GUI)やその他のインタフェースを利用してセット・アップするために使用されます。読取りプラグインでは、作成した任意のImageReadParam
オブジェクトに対して、次のようにしてIIOParamController
を付加できます。
ImageReadParam param = reader.getDefaultImageParam(); IIOParamController controller = param.getController(); if (controller != null) { controller.activate(param); }
コントローラのactivate
メソッドを呼び出すと、GUIが表示され、ユーザーがスライダを動かしたり、ボタンをクリックしたりするイベントが処理されます。通常、このインタフェースには「OK」または「適用」ボタンがあって、そのボタンがクリックされると、activateメソッドから戻ります。コントローラには、結び付けられたImageReadParam
の状態を更新するためのメソッドを呼び出す責任があります。メソッドの呼出しは、各GUIイベントが発生するたびに実行するか、activate
メソッドから戻る前にすべて一度に実行するかのどちらかです。
ImageReader
クラスのメソッドのうち、イメージを処理するメソッドはすべて、imageIndex
パラメータをとります。このパラメータを使用して、マルチイメージ・ファイル内の任意のイメージにアクセスできます。
ImageReader.getNumImages
メソッドは、入力ファイルに格納されているイメージの数を返します。このメソッドは、boolean型のパラメータallowSearch
をとります。一部のイメージ形式(特にGIF)では、ファイル全体を読み取らずにイメージの数を判別する手段が提供されていません。これでは負荷が掛かりすぎることがあるので、allowSearch
にfalse
を設定できます。その場合、読取りオブジェクトは戻り値として実際のイメージ数ではなく、-1
を返します。このパラメータがtrue
の場合、読取りオブジェクトは常に実際のイメージ数を返します。
アプリケーションがイメージの数を識別できない場合でも、read(imageIndex)
を呼び出すことは可能です。インデックスが大きすぎると、このメソッドは例外IndexOutOfBoundsException
をスローします。したがって、アプリケーションは、例外を受け取るまで、インデックスを増やしながらイメージを要求できます。
一部のイメージ形式では、1つの小さいプレビュー・イメージ(または複数のプレビュー・イメージ)を、メインのイメージと一緒に格納できます。この「サムネイル」イメージは、イメージ全体をデコードする必要なしに、イメージ・ファイルをすばやく識別できて便利です。
アプリケーションは、次の呼出しによって、特定のイメージに関連付けられているサムネイルの数を判別できます。
reader.getNumThumbnails(imageIndex);
サムネイル・イメージが存在する場合は、次のような呼出しによって取得できます。
int thumbailIndex = 0; BufferedImage bi; bi = reader.readThumbnail(imageIndex, thumbnailIndex);