ピクセルを得る


ピクセルを操作する

以前覚えた MemoryImageSource クラスでピクセルを画像に変換しましたね
MemoryImageSourceクラスとcreateImage()を用いて、Imageオブジェクトを生成できますが
あの時はループによって手作業でピクセルを生成しました

もし画像からピクセルを抽出することができれば
そのピクセルを操作することで、高度な画像変換を行うことができます
JavaのImageFilterを用いたフィルターは、非常に高度で難しいですが
直接ピクセルを操作してイメージを生成する方法ならば、比較的簡易です

Imageオブジェクトからピクセルを抽出するにはjava.awt.image.PixelGrabberクラスを使用します
このクラスは、イメージからのピクセルの抽出をサポートします
コンストラクタは、イメージの状態を想定して次の中から適切なものを選択します

public PixelGrabber( Image img, int x, int y, int w, int h, int pix[], int off, int scansize )
public PixelGrabber( ImageProducer ip, int x, int y, int w, int h, int pix[], int off, int scansize )
public PixelGrabber( Image img, int x, int y, int w, int h, boolean forceRGB )

第一引数には、抽出するImageまたはImageProducerを指定します
x , y , w , h は、抽出するイメージの長方形を指定します
xにはx座標、yにはy座標を指定し、wには横幅、hには高さをピクセル単位で指定します

pix[]には、ピクセルを格納するint型の配列を、
offには配列のオフセット、scansizeにはピクセルの行間の距離(通常は画像の幅)を指定します

forceRGBは、ピクセルをRGB形式で送るかどうかを指定します
trueにするとRGB形式、そうでなければイメージプロデューサのカラーモデルを使用します

pix[]を渡す形式の場合は、あらかじめバッファを用意しなければなりませんが
3番目の構文を用いれば、後からピクセルを受け取る方法を用いることができます
通常pix[]を渡す形式の場合、イメージをあらかじめ読み込んでおく必要があります
その時には、MediaTrackerなどを用います

3番目の構文のwとhに、0以下の値(つまり負数)を指定した場合
幅はデフォルトの値になるので、ロードされていない画像に有効です

ピクセルを読み込むには、インスタンスを生成した後にgrabPixels()を使用します
このメソッドはイメージ(またはイメージプロデューサ)にピクセルの転送を要求します

public boolean grabPixels() throws InterruptedException

3番目のコンストラクタの構文を使用している場合は
grabPixels()を使用した後に、ピクセルの配列を得る必要があります
ピクセルバッファを得るにはgetPixels()メソッドを使用します

public synchronized Object getPixels()

このメソッドはbyteまたはintの配列を返します
このようにして得られたピクセルを操作し、イメージを再度生成すれば
元画像に何らかの操作を行うことができます

ピクセルの幅を得るにはgetWidth()メソッドを
ピクセルの高さを得るにはgetHeight()メソッドを用います

public synchronized int getHeight()
public synchronized int getWidth()

コンストラクタの3番目の構文で、負数を指定した時などによく使います
目的のサイズを返しますが、サイズがまだ不明の場合は-1を返します
import java.applet.Applet;
import java.awt.*;
import java.awt.image.*;

/*	<applet code="App60.class" width="300"height="300">
	<param name="img" value="img/test.jpg">
 	</applet>
*/

public class App60 extends Applet {
	Image img;
	public void init() {
		Image image = getImage(getDocumentBase() , getParameter("img"));
		PixelGrabber pg = new PixelGrabber(image , 0 , 0 , -1 , -1 , true);

		try { pg.grabPixels(); }
		catch (InterruptedException e) { }
		int px[] = (int[])pg.getPixels();

		for(int index = 0 ; index < px.length ; index++)
			if (px[index] == ((255 << 24) | (255 << 16) | (255 << 8) | 255))
				px[index] = (255 << 24);
				
		ImageProducer ip = new MemoryImageSource(
			pg.getWidth() , pg.getHeight() , px , 0 , pg.getWidth());
		this.img = createImage(ip);
	}
	public void paint(Graphics g) {
		g.drawImage(img , 0 , 0 , this);
	}
}
アプレット

ループで全てのピクセルを調べ、色が白のピクセルを黒に変換するアプレットです
画像のピクセルがRGB形式で 255 , 255 , 255 の色であれば、それを黒色に変換しています

これを用いれば、特定の色のアルファ値を0にすることで
画像ファイルを透過させるというようなことができます
背景とキャラクターの画像を分け、セル画のように表示させることができます



前のページへ戻る次のページへ