DATE : 2006/09/15 (Fri)
(前回の記事)
メソッドの抽出 (3)
前回に続いてさらに、「4 : 2の WritableRaster のアルファ成分を設定」の部分
WritableRaster alphaRaster = destRaster.
	createWritableChild(0, 0, width, height, 0, 0,
		new int[]{destRaster.getNumBands() - 1});
// 可視領域を表すアルファ成分のみの Raster
WritableRaster visibleMaskRaster =
	createVisibleAlphaRaster(image);
alphaRaster.setRect(visibleMaskRaster);
を setAlphaSamplesメソッドに抽出します。
/**
 * 指定の WritableRaster にアルファ成分を設定します。
 * ただし、WritableRaster には、アルファ成分を格納するバンドが
 * 存在しなければなりません。
 * 
 * @param image アルファ成分を追加する元となる画像
 * @param dest アルファ成分を追加する WritableRaster
 */
private static void setAlphaSamples(
		RenderedImage image, WritableRaster dest) {
	WritableRaster alphaRaster = dest.
		createWritableChild(0, 0, width, height, 0, 0,
			new int[]{destRaster.getNumBands() - 1});
	// 可視領域を表すアルファ成分のみの Raster
	WritableRaster visibleMaskRaster =
		createVisibleAlphaRaster(image);
	alphaRaster.setRect(visibleMaskRaster);
}
しかし、メソッドを抽出していてふと思いました。上のメソッドでは、アルファ成分のみの Raster を生成して、WritableRaster のアルファ成分として設定しています。ところが、ここで設定するアルファ値は全画素で共通のはずです。すると、わざわざアルファ成分のみの Raster を生成するよりも、直接アルファ成分を設定した方がコードは簡単になります。
そこで、上のコードを、直接アルファ成分を設定するように変更します。
/**
 * 指定の WritableRaster にアルファ成分を設定します。
 * ただし、WritableRaster には、アルファ成分を格納するバンドが
 * 存在しなければなりません。
 * 
 * @param raster アルファ成分を設定する WritableRaster
 */
private static void setAlphaSamples(WritableRaster raster) {
	int alphaBand = raster.getNumBands() - 1;
	
	for (int y = 0; y < raster.getHeight(); y++) {
		for (int x = 0; x < raster.getWidth(); x++) {
			raster.setSample(x, y, alphaBand, 0xff);
		}
	}
}
ここでは、最大のアルファ値として 0xff を設定しています。ところが、1バンクの幅が1バイトを超えると、0xff は最大のアルファ値とはなりません。例えば、WritableRaster(Raster)の転送型が java.awt.image.DataBuffer#TYPE_INT の場合は、符号付き4バイト値(int型)でアルファ値が表されることになります。そのため、0xff を int 型の最大値に変更します。(バンク幅を超えた値は、バンク幅に合わせてビットが切り捨てられます)
raster.setSample(x, y, alphaBand, Integer.MAX_VALUE);
また、Integer.MAX_VALUE に「アルファ値」としての意味を持たせるため、定数として抽出します。
結果、setAlphaSamples メソッドは次のようになります。
private static final int ALPHA_VALUE = Integer.MAX_VALUE;
/**
 * 指定の WritableRaster にアルファ成分を設定します。
 * ただし、WritableRaster には、アルファ成分を格納するバンドが
 * 存在しなければなりません。
 * 
 * @param raster アルファ成分を設定する WritableRaster
 */
private static void setAlphaSamples(WritableRaster raster) {
	int alphaBand = raster.getNumBands() - 1;
	
	for (int y = 0; y < raster.getHeight(); y++) {
		for (int x = 0; x < raster.getWidth(); x++) {
			raster.setSample(
				x, y, alphaBand, ALPHA_VALUE);
		}
	}
}
初めに抽出したメソッドと比べて、引数が1つ減りました。
また、createVisibleAlphaRaster メソッドを使う必要がなくなりました。そのため、このメソッドは消去しておきます。
なお、「4 : 2の WritableRaster のアルファ成分を設定」の部分は次のように変わります。
setAlphaSamples(destRaster);
最後に、「5 : BufferedImage の生成」の部分です。
return new BufferedImage(destColorModel, destRaster, false, null);
しかし、この部分はコメントの通り BufferedImage を生成しているだけなので、メソッドには抽出しません。
ただ、アルファの乗算状態を false と決め打ちにしているところは気になります。そこでこの部分を、処理対象の画像のカラーモデルと同じ状態になるように変更します。
return new BufferedImage(destColorModel, destRaster, destColorModel.isAlphaPremultiplied(), null);
(つづきます)
 
