ImageFilterの基礎
アプレットやスタンドアロン型のアプリケーションで、GUIアプリを作ろうと思ったら Imageクラスを使って外部イメージを使う事が多いかと思います。特にゲームなんかでは イメージだらけと言ってもいいですよね。

Javaではこれらのイメージにフィルタを かけることが出来ます。フィルタをかけると、色が変わったり、特殊効果をもたらしたり 、画像が見やすくなったりと、いいこと尽くしです。しかも実装方法も簡単です。 ここではイメージを青くする方法を紹介します。

また、JavaでImageFilterを使う時は、RGBImageFilterクラスのサブクラスを使用します (というか、それしか知らない・・・)。このクラスは、イメージをピクセルごとに 変換するクラスです。このクラスのサブクラスで、protectedメソッドのfilterRGB()メソッドを オーバーライドします。では早速具体的な例を見てみましょう。
イメージを青くしてみる
では実際にフィルタをかけてみましょう。 今回のは色のフィルタをかけてみます。画像ソフトなんかには良くある機能です。 これをJavaで実装するには前述の通り、RGBImageFilterクラスのサブクラスを使用します。

	        
import java.awt.*;
import java.awt.image.*;
import javax.swing.*;

/*テスト用のメインクラス*/
public class Main extends JApplet {
    private Image defaultImage;  //元の画像
    private Image fileredImage;  //フィルタをかけた画像

    public void init() {
        resize(330, 120);
        defaultImage = getImage(getCodeBase(), "image.png");
		
        ImageProducer source = defaultImage.getSource();
		
        /*フィルタを作成*/
        ImageFilter filter = new BlueFilter();

        /*フィルタリング*/
        ImageProducer producer = new FilteredImageSource(source, filter);

        /*フィルタをかけたイメージを作成*/
        fileredImage = createImage(filterProducer);
    }

    public void paint(Graphics g){
        g.drawImage(defaultImage, 0, 0, this);
        g.drawImage(fileredImage, 170, 0, this);
    }
}

/*フィルタクラス*/
public class BlueFilter extends RGBImageFilter {
    public BlueFilter() {
        canFilterIndexColorModel = true;  //注目!!
    }
	
    /*フィルタ処理*/
    public int filterRGB(int x, int y, int rgb) {
        return (rgb | 0x000000FF);
    }
}

とりあえず、下のアプレットを見てください。

元のイメージ フィルタをかけたイメージ

左が元のイメージで、右が青いフィルタをかけたイメージです。確かに青くなっているのが 分かります。

このフィルタ処理をソースを追って理解しましょう。 まずはフィルタクラスに目をやってください。このクラスは青のフィルタを表すクラスです。 イメージをこのクラスにかけるとイメージは青くなります。

と、こんな説明じゃ怒られます(((;゚Д゚)ガクガクブルブル)。実はこのフィルタクラスは 実際のフィルタリング処理は行いません。「青のフィルタを表すクラス」と書きましたが、 その名の通り、フィルタを表すだけでイメージのフィルタリングは行いません。

ではfilterRGBメソッドは何のためにあるのでしょうか?ソースを見れば分かるように 一度もfilterRGBメソッドを呼び出してはいません。その答えを知るためには Javaのフィルタ処理とイメージ処理について少し知識が必要です。

で、説明したいんですが、オレも良く分かっていないのと、 この辺りの話は長くなるので、別の部分で説明したいと思います。 ここではあまり詳しくはやりません。

とりあえず、上記の疑問にだけ答えておきます。まず、filterRGBメソッドは、 フィルタリングを行うのではなく、引数で渡されたRGB値を加工するメソッドです。 RGB値とはRGBカラーモデル(以下、RGBとします)で使用される、色を表すintの値です。RはRed、GはGreen、 BはBlueです。テレビで使われてるのもこのRGBです。RGBでは、先に書いた赤と緑と 青を、16進数2桁の数値で表します。この辺は大体分かると思います。そして、 今回の例だと渡されたRGB値を「0x000000FF」というRGB値とor演算しています。 このor演算子は、一般的に使われる真偽の「||」とは違い、ビット演算を行う or演算です。「0x000000FF」というのはRGBで青を表しますから、任意のRGB値を この青を表すRGBとor演算することで、「青さ」が最高のRGBを生成します。 そしてfilterRGBメソッドはこの生成されたRGB値を返します。

ここまでを見てみると、フィルタリング処理がどのように行われているのか想像が出来ます。 fliterRGBメソッドにRGB値を与えてやれば、それを青くした(もちろん完全な青ではありません。 あくまで青フィルタを通した色です。)RGB値が返ってきます。これはイメージをフィルタリングしているとは 言えませんが、この処理をイメージのピクセル全てに適用すれば、結果として フィルタリングされたイメージが出来るはずです。つまり、何処かの誰かが このfilterRGBメソッド、もっと言えばそれを定義するBlueFilterクラスを 使用しているに違いありません。

ここでもう一度ソースを見てください。注目すべき箇所があります。 メインクラスでBlueFilterクラスのインスタンスを生成したあと、そのオブジェクトを あるクラスのコンストラクタ引数に渡しているのが分かるはずです。そのクラスは 「FilteredImageSource」というクラスです。このクラスにBlueFilterが渡されるという ことは(それもコンストラクタで!)、何らかの処理をしているに違いありません。

ぐはぁ!これ以上の説明は無理っす。長くなりすぎます。なので簡単に説明します。 詳細は別のとこで説明します。

このFilteredImageSourceのインスタンスは、コンストラクタの第1引数のイメージプロデューサと と第2引数のイメージフィルタを合わせて新たなイメージプロデューサを生成します。 イメージプロデューサというのはイメージを提供するオブジェクトだと思ってください。 ここから想像できるように、フィルタリングはこの部分で行われています。 生成された新しいプロデューサをcreateImageメソッドの引数に渡すことで、 そのプロデューサがイメージを提供してくれます。

下手な説明で申し訳ないですが、繰り返すように別の所でもっと詳しく説明したいと思います。 とりあえずここでは、フィルタを実装する方法を説明したので、RGBFilterメソッドの 内容を変えてやれば、色々なフィルタリングが可能です。