java.awt.image.RGBImageFilter

目的
RGB値を操作するフィルタリングをかける。

関連クラス

今回のソース
//////////////////// filter.java ////////////////////

import java.awt.event.*;
import java.awt.*;
import java.awt.image.FilteredImageSource;
import java.awt.image.RGBImageFilter;

class filter
{
	public static void main(String args[])
	{
		new MainWindow(args[0],Double.parseDouble(args[1]));
	}
}

class MainWindow extends Frame
{
	public MainWindow(String image_name,double rate)
	{
		// Windowリスナの登録
		WindowListener listener = new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);
			}
		};
		addWindowListener(listener);

		setLayout(new BorderLayout());

		// イメージの取得
		Toolkit toolkit = getToolkit();
		Image src = toolkit.getImage(image_name);

		// イメージのフィルタリング処理
		RGBImageFilter filter;
		if(rate >= 0)
			filter = new BrighterFilter(Math.abs(rate));
		else
			filter = new DarkerFilter(Math.abs(rate));
		Image image = createImage(new FilteredImageSource(src.getSource(),filter));

		// コンポーネントの追加
		PaintCanvas canvas = new PaintCanvas(image);
		add(canvas,BorderLayout.CENTER);

		Label lbl = new Label(image_name,Label.CENTER);
		add(lbl,BorderLayout.SOUTH);

		// フレームの初期設定
		setSize(150,150);
		setTitle("Image Filter");
		setVisible(true);
	}
}

// イメージ表示用キャンバス
class PaintCanvas extends Canvas
{
	Image image;

	public PaintCanvas(Image image)
	{
		this.image = image;
	}

	public void paint(Graphics g)
	{
		g.drawImage(image,0,0,this);
	}
}

////////////////////////////////////////////////////////////

//////////////////// BrighterFilter.java ////////////////////

import java.awt.image.RGBImageFilter;

// 明化処理フィルタ
class BrighterFilter extends RGBImageFilter
{
	final int RGB_MAX = 255;
	// 明化の度合(大きいほど明るくなる)
	double rate;
	int hosei;

	public BrighterFilter(double rate)
	{
		// rateのノーマライズ
		if(rate > 1.0)
			rate = 1.0;
		if(rate < 0.0)
			rate = 0.0;
		this.rate = rate;

		hosei = (int)(RGB_MAX * rate);
		canFilterIndexColorModel = true;
	}

	public int filterRGB(int x,int y,int rgb)
	{
		// 各RGB値の取得
		int alpha_value = (rgb & 0xff000000);
		int red_value   = (rgb & 0x00ff0000) >> 16;
		int green_value = (rgb & 0x0000ff00) >> 8;
		int blue_value  = (rgb & 0x000000ff);

		// 明化処理
		red_value   = (int)(red_value   * (1 - rate)) + hosei;
		green_value = (int)(green_value * (1 - rate)) + hosei;
		blue_value  = (int)(blue_value  * (1 - rate)) + hosei;

		return(alpha_value | (red_value << 16) | (green_value  << 8) | blue_value);
	}
}

////////////////////////////////////////////////////////////

//////////////////// DarkerFilter.java ////////////////////

import java.awt.image.RGBImageFilter;

// 暗化処理フィルタ
class DarkerFilter extends RGBImageFilter
{
	// 暗化の度合(大きいほど暗くなる)
	double rate;

	public DarkerFilter(double rate)
	{
		// rateのノーマライズ
		if(rate > 1.0)
			rate = 1.0;
		if(rate < 0.0)
			rate = 0.0;
		this.rate = rate;

		canFilterIndexColorModel = true;
	}

	public int filterRGB(int x,int y,int rgb)
	{
		// 各RGB値の取得
		int alpha_value = (rgb & 0xff000000);
		int red_value   = (rgb & 0x00ff0000) >> 16;
		int green_value = (rgb & 0x0000ff00) >> 8;
		int blue_value  = (rgb & 0x000000ff);

		// 暗化処理
		red_value   = (int)(red_value   * (1 - rate));
		green_value = (int)(green_value * (1 - rate));
		blue_value  = (int)(blue_value  * (1 - rate));

		return(alpha_value | (red_value << 16) | (green_value  << 8) | blue_value);
	}
}

////////////////////////////////////////////////////////////
Source is here. (ZIP Format,21762Byte,Shift-JIS)

コンパイル&実行
javac filter.java
java filter <image_name> <rate>
rate : -1.0(暗)〜1.0(明)

説明
(概略)

各RGB値にフィルタリングをかけて、画像を明るくしたり、暗くしたりします。

明るめ 普通 暗め
明るめ 普通 暗め

RGBの各値は、0(暗い)〜255(明るい)となっているので、
暗くする時には、値*rateで、rateが低い程値は小さくなります。
実際には、rateが高い程暗くしたいので、値*(1-rate)となっています。

逆に、明るくする時には、値*rate+補正値というフィルタをかけています。
これは、0〜255という値の範囲が、例えば、127〜255という値の範囲にすることで、
全体的に明るい方の値へ補正することによって、イメージを明るくしています。

具体的には、rate=0.5だった場合、補正値hoseiは、hosei=255*0.5=127で計算され、
値100→100*(1-0.5)+127=177
値150→150*(1-0.5)+127=202
値200→200*(1-0.5)+127=227
値255→255*(1-0.5)+127=254(この辺はちょっとおかしいけど...)
のように、rateによって、値を増やしています。

(サンプルプログラムの説明)

Double.parseDouble
JDK1.2から追加されたメソッドです。
文字列から、浮動小数点表現にします。
これで、いちいち小数点の前後を判断するような
プログラミングをしなくても済みますね。
Toolkit toolkit = getToolkit();
Image src = toolkit.getImage(image_name);
イメージの取得は、各プラットフォーム固有の方法で
得なければならないので、AWTとネイティブを結び付ける、
Toolkitクラスを使います。
FilteredImageSource(src.getSource(),filter)
フィルタをかけたイメージを作るのに使います。
名前もそのまんまって感じですね。
filterには、java.awt.image.ImageFilter又はそのサブクラスを使います。
イメージ表示用キャンバス
フレームに直接イメージを描画することも、多分出来ますけど、
今回は、フレームの上にキャンバスを貼って、
その上に、イメージを描画しています。
canFilterIndexColorModel = true;
この boolean 型は、IndexColorModel オブジェクトのカラーテーブルエントリに
filterRGB メソッドのカラーフィルタリングを
フィルタリングによるピクセルの代わりに使用するどうかを示す。
という、JDKマニュアルの説明ですけど(^^;

まず、IndexColorModelというクラスは、ピクセル値<->カラーの
変換テーブルだと思って下さい。
つまり、あるピクセル値を与えると、そのピクセルに対応する、
カラーが得られるという仕掛けです。

ところで、このIndexColorModelというカラーモデルを用いていると、
ピクセルによって、与えられるカラーは固定的なため、
いくらフィルタをかけても、与えられるカラーは一定になってしまい、
フィルタリング処理が出来ません。

そこで、canFilterIndexColorModelというフラグをセットすることによって、
IndexColorModelが与えるカラーの替わりに、フィルタリング処理の結果を
使うということを示しています。
public int filterRGB(int x,int y,int rgb)
フィルタリング処理を決める、重要なメソッドです。
rgb値を操作することで、各ピクセルの色を変化させることが出来ます。
rgbはint型で、32bit(Alpha,Red,Green,Blue)の色情報を含んでいます。
また、x,yを使うことで、ピクセルによるフィルタリングを
かけることが出来るでしょう。
各RGB値の取得
まず最初の、論理和演算は、
rgbが、0xaarrggbbというフォーマットなので、
例えば、rgb & 0x00ff0000なら、rrにあたる赤色値を取り出しています。
ただ、このままでは、rr0000という値になってしまうので、
16bit右へシフト演算を施して、0xrr(0〜255)という値を取り出しています。