トップページ -> 実践知識 -> Java プログラミング入門 -> Java での画像フィルタの例
[サイトマップへ]  

Java での画像フィルタの例

サイト構成 連絡先,業績 実践知識 コンピュータ 教材 サポートページ

この Web ページでは,画像ファイルの読み出しと書き込みや,画像処理を行う Java プログラムの見本を示す. ImageMagick と JMagick を使って簡単に作ることができます.

参考 Web ページ
http://kyle-in-jp.blogspot.com/search/label/JMagick : JMagick を使った画像処理プログラムの見本が載ったすばらしい Web ページ


必要となるソフトウエア


サンプルプログラム

要点

実行手順は, 「Java から ImageMagick の機能を使う(JMagick を使用)」 のWebページを見てください.

package hoge.hoge.com;

import magick.ImageInfo;
import magick.MagickException;
import magick.MagickImage;

public class HelloWorld {

	final private static String FILENAME = "C:\\R\\hoge.jpg";
	
	// 縦横 2M だけ大きいサイズの真っ黒の画像の中心に,画像 bytes を貼り付け
	// 各画素は4バイト(1バイトが4つ分)であること.
	private static double[] imagepaste( final int width, final int height, byte bytes[], final int M ) {

		double data[] = new double[ (width + (2 * M)) * (height * (2 * M)) * 4 ]; // red, green, blue, alpha
		
		for( int i=0; i<height; i++ ) {
			for( int j=0; j<width; j++ ) {
				final int from = (i* width * 4) + (j*4);
				final int to   = ((width+(2*M))*M*4) + (i*(width+(2*M))*4) + (M*4) + (j*4);
				data[ to ]     = bytes[ from ]; // red
				data[ to + 1 ] = bytes[ from + 1 ]; // green
				data[ to + 2 ] = bytes[ from + 2 ]; // blue
				data[ to + 3 ] = bytes[ from + 3 ]; // alpha
			}
			// 左右の余白を黒でうめる
			for( int j=0; j<M; j++) {
				final int to = ((width+(2*M))*M*4) + (i*(width+(2*M))*4) + (j*4);
				data[ to ]     = 0;  // red
				data[ to + 1 ] = 0;  // green
				data[ to + 2 ] = 0;  // blue
				data[ to + 3 ] = 0;  // alpha
			}
			for( int j=0; j<M; j++) {
				final int to = ((width+(2*M))*M*4) + (i*(width+(2*M))*4) + (M*4) + (width*4) + (j*4);
				data[ to ]     = 0;  // red
				data[ to + 1 ] = 0;  // green
				data[ to + 2 ] = 0;  // blue
				data[ to + 3 ] = 0;  // alpha
			}
		}
		// 上を黒で埋める
		for( int i=0; i<M; i++ ) {
			for( int j=0; j<(width+(2*M)); j++ ) {
				final int to   = (i*(width+(2*M))*4) + (j*4);
				data[ to ]     = 0; // red
				data[ to + 1 ] = 0; // green
				data[ to + 2 ] = 0; // blue
				data[ to + 3 ] = 0; // alpha
			}
		}
		// 下を黒で埋める
		for( int i=0; i<M; i++ ) {
			for( int j=0; j<(width+(2*M)); j++ ) {
				final int to   = ((width+(2*M))*(M+height)*4) + (i*(width+(2*M))*4) + (j*4);
				data[ to ]     = 0; // red
				data[ to + 1 ] = 0; // green
				data[ to + 2 ] = 0; // blue
				data[ to + 3 ] = 0; // alpha
			}
		}
		
		return data;
	}
	
	// 画像の隅、縦横 2M 画素を切り抜く
	// 各画素は4バイト(1バイトが4つ分)であること.imagepaste の逆操作
	private static byte[] imageclip( final int width, final int height, double data[], final int M ) {

		byte bytes[] = new byte[ width * height * 4 ]; // red, green, blue, alpha
		
		for( int i=0; i<height; i++ ) {
			for( int j=0; j<width; j++ ) {
				final int from = ((width+(2*M))*M*4) + (i*(width+(2*M))*4) + (M*4) + (j*4);
				final int to   = (i * width * 4) + (j*4);
				bytes[ to ]     = (byte) data[ from ]; // red
				bytes[ to + 1 ] = (byte) data[ from + 1 ]; // green
				bytes[ to + 2 ] = (byte) data[ from + 2 ]; // blue
				bytes[ to + 3 ] = (byte) data[ from + 3 ]; // alpha
			}
		}
		
		return bytes;
	}
	
	private static byte[] filter( int width, int height, byte bytes[] ) {

		// 余白つきの画像を生成
		final int M = 1;
		double data[] = imagepaste( width, height, bytes, /* margin */ M );

		// フィルタ本体
		byte data2[] = new byte[ (width + 2) * (height * 2) * 4 ]; // red, green, blue, alpha
		for( int i=0; i<height; i++ ) {
			for( int j=0; j<width; j++ ) {
				final int at  = ((width+(2*M))*M*4) + (i*(width+(2*M))*4) + (M*4) + (j*4); // 余白の分だけずれる
				final int atP  = at - ((width+(2*M))*4);
				final int atN  = at + ((width+(2*M))*4);

				final double red = (double) (
					data[ atP - 4 ] + data[ atP     ] + data[ atP + 4 ] +
					data[ at  - 4 ] + data[ at      ] + data[ at  + 4 ] +
                    data[ atN - 4 ] + data[ atN     ] + data[ atN + 4 ] ) / 9;
				final double green = (double) (
					data[ atP - 3 ] + data[ atP + 1 ] + data[ atP + 5 ] +
					data[ at  - 3 ] + data[ at  + 1 ] + data[ at  + 5 ] +
                    data[ atN - 3 ] + data[ atN + 1 ] + data[ atN + 5 ] ) / 9;
				final double blue = (double) (
					data[ atP - 2 ] + data[ atP + 2 ] + data[ atP + 6 ] +
					data[ at  - 2 ] + data[ at  + 2 ] + data[ at  + 6 ] +
	                data[ atN - 2 ] + data[ atN + 2 ] + data[ atN + 6 ] ) / 9;
				final double alpha = (double) (
					data[ atP - 1 ] + data[ atP + 3 ] + data[ atP + 7 ] +
					data[ at  - 1 ] + data[ at  + 3 ] + data[ at  + 7 ] +
                    data[ atN - 1 ] + data[ atN + 3 ] + data[ atN + 7 ] ) / 9;
				
				final int to  = (i* width *4) + (j*4);
				data2[ to ]     = (byte) red;
				data2[ to + 1 ] = (byte) green;
				data2[ to + 2 ] = (byte) blue;
				data2[ to + 3 ] = (byte) alpha;
			}
		}

		return data2;	
	}
	
	public static void main(String[] args) {
		MagickImage image;
		try {
			// 画像ファイル読み込み
		    image = new MagickImage( new ImageInfo( FILENAME ) );
   		    int width  = (int)image.getDimension().getWidth();
		    int height = (int)image.getDimension().getHeight();
		   
		    // 画像データを,配列にコピー
		    byte bytes[] = new byte[ width * height * 4 ]; // red, green, blue, alpha
		    image.dispatchImage(0, 0, width, height, "RGBA", bytes);
		    // フィルタ(filter)の実行結果を書き戻す
		    image.constituteImage(width, height, "RGBA", filter( width, height, bytes ) );
		   
	        image.setFileName("c:\\R\\sample.png");
	        image.writeImage(new ImageInfo());
		} catch (MagickException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		}

	}

}