Previous | Next | Trail Map | Creating a User Interface | グラフィックスを扱う


イメージフィルタの使用方法

次のアプレットはフィルタを使用してイメージを回転させる。 この RotateFilter という名前の特製フィルタについては次のページで説明する。 フィルタについて知っておくべきことは、そのコンストラクタが 1 個の倍精度引数をとるということだけである。この引数にはラジアン単位のローテー ション角度が指定される。 このアプレットはユーザが入力した数値を度からラジアンに変換し、アプレットが RotateFilter を作成できるようにしている。

以下に、ソースコードのフィルタを使用する部分を示す。 (プログラム全体も参照できる。)

public class ImageRotator extends Applet {
    . . .
    RotatorCanvas rotator;
    double radiansPerDegree = Math.PI / 180;

    public void init() {
        //イメージをロードする。
        Image image = getImage(getCodeBase(), "../images/rocketship.gif");

        ...//イメージフィルタを使用するコンポーネントを作成する。
        rotator = new RotatorCanvas(image);
        . . .
        add(rotator);
        . . .
    }

    public boolean action(Event evt, Object arg) {
        int degrees;

        ...//イメージの回転角度を取り込む。

        //ラジアンに変換する。
        rotator.rotateImage((double)degrees * radiansPerDegree);

        return true;
    }
}

class RotatorCanvas extends Canvas {
    Image sourceImage;
    Image resultImage;

    public RotatorCanvas(Image image) {
        sourceImage = image;
        resultImage = sourceImage;
    }

    public void rotateImage(double angle) {
        ImageFilter filter = new RotateFilter(angle);
        ImageProducer producer = new FilteredImageSource(
                                        sourceImage.getSource(),
                                        filter);
        resultImage = createImage(producer);
        repaint();
    }

    public void paint(Graphics g) {
        Dimension d = size();
        int x = (d.width - resultImage.getWidth(this)) / 2;
        int y = (d.height - resultImage.getHeight(this)) / 2;

        g.drawImage(resultImage, x, y, this);
    }
}

コードが動作する仕組み

イメージフィルタを使用する場合、プログラムは以下のステップをたどる。

  1. Image オブジェクトを取り込む (通常は getImage() メソッドで 行う)。
  2. getSource() メソッドを使用し、Image オブジェクトのデータソ ース (ImageProducer) を取り込む。
  3. 必要に応じてイメージフィルタを初期化し 、フィルタのインスタンスを作成する。
  4. コンストラクタにイメージソースオブジェクトとフィルタオブジェクトを渡し 、FilteredImageSource オブジェクトを作成する。
  5. Component の createImage() メソッドで、イメージプロデュー サとして FilteeredImageSource をもつ新しい Image オブジェクトを作成する。

複雑そうに見えるかもしれないが、実際には簡単に実装できる。 本当に複雑なのは少し後で説明するとおり、内部の動きである。 まず、イメージフィルタを使用するアプレット例のコードについて解説する。

アプレット例では、RotatorCanvas の rotateImage() メソッドが、イ メージフィルタの使用に関連するタスクのほとんどを実行する。 これに当てはまらないのは、元の Image オブジェクトを取り込む第 1 ステップであ り、これはアプレットの init() メソッドによって実行される。この Image オブジェクトは RotatorCanvas に渡され、そこで sourceImage として参照される。

rotateImage() メソッドは、フィルタのコンストラクタを呼び出して イメージフィルタをインスタンス化する。 コンストラクタへの 1 個の引数は、ラジアン単位のイメージの回転角度である。

ImageFilter filter = new RotateFilter(angle);

次に、rotateImage() メソッドが FilteredImageSource インスタンス を作成する。 FilteredImageSource コンストラクタへの最初の引数は getSource() メソッドを使って得られたイメージソースである。 2 番目の引数はフィルタオブジェクトである。

ImageProducer producer = new FilteredImageSource(
                                sourceImage.getSource(),
                                filter);

最後にコードは、Component の createImage() メソッドを起動して、 resultImage という名前の別の Image を作成する。 createImage() へのただ 1 つの引数は上のステップで作成された FilteredImageSource である。

resultImage = createImage(producer);

内部で起きること

このセクションでは、イメージフィルタリングが内部でどのように動作しているかに ついて解説する。 このような実装上の詳細を気にしたくない場合は、イメージフィル タの保管場所へスキップしてよい。

最初に理解しなければならないことは、AWT が drawImage() 要求に答 えて内部で ImageConsumer を使用していることである。 したがって、イメージコンシューマに該当するのはイメージを表示する Component ではなく、AWT の奥深くにある何らかのオブジェクトである。

上記の createImage() 呼び出しは、プロデューサである FilteredImageSource インスタンスからイメージデータを得ようとする Image (resultImage) を設定する。 ここで、resultImageの観点から見たイメージデータのパスを示す。

点線は、イメージコンシューマが実際には FilteredImageSource からデータを取り込まないことを表している。 その代わりに FilteredImageSource は、 イメージコンシューマが (g.drawImage(resultImage,...) に応えて) イメージデータを要求したとき、何らかの技を実行し、別の道筋をつける。以下に、 FilteredImageSource が実行する技を示す。

この結果、次のようになる。

イメージフィルタの保管場所

ここでは、既存のイメージフィルタが納めてある場所について述べる。 java.AWT.image パッケージにはいつでも使える CropImageFilter フィルタが組み込ま れている。このフィルタは、元のイメージの矩形範囲から成る イメージを作り出すものである。 ほかにも、当社の Web サイトでアプレットが使用しているイメージフィルタがいく つかある。 以下に示すページにはすべて、それぞれのアプレットとイメージフィルタのソースコ ードへのリンクが組み込まれている。


Previous | Next | Trail Map | Creating a User Interface | グラフィックスを扱う