ゆるゆるプログラミング

・同心円模様

画像サイズと黒の線幅と白の線幅を指定することで、黒と白の同心縁模様画像を作成します。ここで紹介するプログラムで出力する画像の形式はPNGファイルです。

同心円模様画像同心円模様

上の画像の例は、画像サイズ:256x256、黒のピクセル幅:10、白のピクセル幅:20で作成したものです。この例では、中心付近の色は白色になるようにしています。

Pattern_Circles01.java ← クリックしてダウンロードページに移動
001:    import java.awt.image.BufferedImage;
002:    import java.io.File;
003:    import javax.imageio.ImageIO;
004:    import java.io.IOException;
005:    
006:    public class Pattern_Circles01 {
007:    	public static void main( String[] args ) {
008:    		// 変数宣言
009:    		int w, h;	// 画像サイズ
010:    		int w_b;	// 黒の幅
011:    		int w_w;	// 白の幅
012:    		String outname;	// 出力ファイル名
013:    		BufferedImage img = null;	// 画像格納クラス
014:    
015:    		// 入力した引数が5以上かを調べる
016:    		if ( 5 > args.length ) {
017:    			// 入力した引数が5未満の場合、使用方法を表示する
018:    			System.out.println( 
019:    				"Pattern_Circles01 [PNG名] [画像幅] [画像高] [黒幅] [白幅]" );
020:    			return;
021:    		}
022:    
023:    		try {
024:    			// 引数を変換し、画像の幅と高さをwとhに代入
025:    			w =  Integer.valueOf( args[ 1 ] );
026:    			h =  Integer.valueOf( args[ 2 ] );
027:    
028:    			// 引数を変換し、黒の幅w_bに代入
029:    			w_b = Integer.valueOf( args[ 3 ] );
030:    			if ( 1 > w_b ) {
031:    				System.out.println( "黒幅に1以上を指定!" );
032:    				return;
033:    			}
034:    
035:    			// 引数を変換し、白の幅w_wに代入
036:    			w_w = Integer.valueOf( args[ 4 ] );
037:    			if ( 1 > w_w ) {
038:    				System.out.println( "白幅に1以上を指定!" );
039:    				return;
040:    			}
041:    		}
042:    		catch( NumberFormatException ne )
043:    		{
044:    			System.out.println( "引数が不正です" );
045:    			return;
046:    		}
047:    		// 出力PNG名をoutnameに代入(拡張子".png"省略なし)
048:    		outname = args[ 0 ];
049:    
050:    		// 新しい画像を作成
051:    		// 24ビットカラーの画像を作成
052:    		try {
053:    			img = new BufferedImage( w, h,
054:    						 BufferedImage.TYPE_INT_RGB );
055:    		} catch ( Exception e ) {
056:    			// 画像作成に失敗したときの処理
057:    			e.printStackTrace();
058:    			return;
059:    		}
060:    
061:    		// 同心円画像作成
062:    		int    x, y;
063:    		int    color, r, g, b;	// 計算した色
064:    		double ox, oy;		// 画像の中心座標
065:    		double l;		// 画像の中心座標からの距離
066:    		double dx, dy;		// 画像の中心座標からの距離(x,y毎)
067:    	
068:    		// 画像の中心座標を計算
069:    		ox = (double)w / 2.0;
070:    		oy = (double)h / 2.0;
071:    	
072:    		// 画像の作成メインループ
073:    		for ( y = 0; y < h; ++ y ) {
074:    			// 中心座標oyからのyまでの距離
075:    			dy = (double)y - oy;
076:    
077:    			for ( x = 0; x < w; ++ x ) {
078:    				// 中心座標oxからのxまでの距離
079:    				dx = (double)x - ox;
080:    
081:    				// 中心座標からの距離計算
082:    				l = Math.sqrt( dx * dx + dy * dy );
083:    
084:    				// 黒か白かの判定
085:    				if ( ( l % (double)( w_b + w_w ) ) <= (double)w_w )
086:    					r = g = b = 255;
087:    				else
088:    					r = g = b = 0;
089:    
090:    				// r,g,bの色を合成
091:    				color = ( r << 16 ) + ( g << 8 ) + b;
092:    
093:    				// 合成した色を(x,y)に設定
094:    				img.setRGB( x, y, color );
095:    			}
096:    		}
097:    
098:    		try {
099:    			// imgをoutname(出力PNG)に保存
100:    			boolean result;
101:    			result = ImageIO.write( img, "PNG", new File( outname ) );
102:    		} catch ( Exception e ) {
103:    			// outname(出力PNG)の保存に失敗したときの処理
104:    			e.printStackTrace();
105:    			return;
106:    		}
107:    
108:    		// 正常に終了
109:    		System.out.println( "正常に終了しました" );
110:    	}
111:    }

Pattern_Circles01の実行例

java Pattern_Circles01 pattern_circles01.png 256 256 20 10

ここからは、このJavaソースコードを上から順番に解説していきます。

001:    import java.awt.image.BufferedImage;
002:    import java.io.File;
003:    import javax.imageio.ImageIO;
004:    import java.io.IOException;

Javaのクラスライブラリの中から「java.awt.image.BufferedImage」と「java.io.File」と「javax.imageio.ImageIO」と「java.io.IOException」というパッケージにあるクラスを、このプログラム内で使うために記述します。この記述により、BufferedImageクラスImageIOクラスが利用できるようになります。

006:    public class Pattern_Circles01 {

クラス名を、Pattern_Circles01としています。

007:    	public static void main( String[] args ) {

このmainメソッドからプログラムを実行します。

008:    		// 変数宣言
009:    		int w, h;	// 画像サイズ
010:    		int w_b;	// 黒の幅
011:    		int w_w;	// 白の幅
012:    		String outname;	// 出力ファイル名
013:    		BufferedImage img = null;	// 画像格納クラス

このプログラムで使う変数を宣言しています。

015:    		// 入力した引数が5以上かを調べる
016:    		if ( 5 > args.length ) {
017:    			// 入力した引数が5未満の場合、使用方法を表示する
018:    			System.out.println( 
019:    				"Pattern_Circles01 [PNG名] [画像幅] [画像高] [黒幅] [白幅]" );
020:    			return;
021:    		}

5つ以上の引数が与えられたかをチェックし、5つ未満の場合に、使い方のメッセージを表示し、returnによってmainメソッドを抜けています。

023:    		try {
024:    			// 引数を変換し、画像の幅と高さをwとhに代入
025:    			w =  Integer.valueOf( args[ 1 ] );
026:    			h =  Integer.valueOf( args[ 2 ] );
027:    
028:    			// 引数を変換し、黒の幅w_bに代入
029:    			w_b = Integer.valueOf( args[ 3 ] );
030:    			if ( 1 > w_b ) {
031:    				System.out.println( "黒幅に1以上を指定!" );
032:    				return;
033:    			}
034:    
035:    			// 引数を変換し、白の幅w_wに代入
036:    			w_w = Integer.valueOf( args[ 4 ] );
037:    			if ( 1 > w_w ) {
038:    				System.out.println( "白幅に1以上を指定!" );
039:    				return;
040:    			}
041:    		}
042:    		catch( NumberFormatException ne )
043:    		{
044:    			System.out.println( "引数が不正です" );
045:    			return;
046:    		}
047:    		// 出力PNG名をoutnameに代入(拡張子".png"省略なし)
048:    		outname = args[ 0 ];

与えられた引数をそれぞれ、作成する画像の幅/高さ、黒ピクセルの幅、白ピクセルの幅、出力PNG名を格納する変数に代入しています。画像の幅/高さ、黒ピクセルの幅、白ピクセルの幅の引数はString型なので、Integerクラスを使ってint型に変換しています。

050:    		// 新しい画像を作成
051:    		// 24ビットカラーの画像を作成
052:    		try {
053:    			img = new BufferedImage( w, h,
054:    						 BufferedImage.TYPE_INT_RGB );
055:    		} catch ( Exception e ) {
056:    			// 画像作成に失敗したときの処理
057:    			e.printStackTrace();
058:    			return;
059:    		}

BufferedImageクラスコンストラクタで、新しいBufferedImageを構築しています。

BufferedImageコンストラクタ

BufferedImage( int width, int height, int imageType )
■新しい BufferedImage を構築します。
  パラメータ width     : 構築する画像の横ピクセル
        height    : 構築する画像の縦ピクセル
        imageType : 構築する画像のイメージ形式

061:    		// 同心円画像作成
062:    		int    x, y;
063:    		int    color, r, g, b;	// 計算した色
064:    		double ox, oy;		// 画像の中心座標
065:    		double l;		// 画像の中心座標からの距離
066:    		double dx, dy;		// 画像の中心座標からの距離(x,y毎)

画像作成で使う変数を宣言しています。

068:    		// 画像の中心座標を計算
069:    		ox = (double)w / 2.0;
070:    		oy = (double)h / 2.0;

画像の中心座標を計算しています。画像の座標の範囲は、左上(0,0)~右下(w-1,h-1)なので、(w-1)と(h-1)を2で割った値が画像の中心座標になります。

072:    		// 画像の作成メインループ
073:    		for ( y = 0; y < h; ++ y ) {
074:    			// 中心座標oyからのyまでの距離
075:    			dy = (double)y - oy;
076:    
077:    			for ( x = 0; x < w; ++ x ) {
078:    				// 中心座標oxからのxまでの距離
079:    				dx = (double)x - ox;
080:    
081:    				// 中心座標からの距離計算
082:    				l = Math.sqrt( dx * dx + dy * dy );
083:    
084:    				// 黒か白かの判定
085:    				if ( ( l % (double)( w_b + w_w ) ) <= (double)w_w )
086:    					r = g = b = 255;
087:    				else
088:    					r = g = b = 0;
089:    
090:    				// r,g,bの色を合成
091:    				color = ( r << 16 ) + ( g << 8 ) + b;
092:    
093:    				// 合成した色を(x,y)に設定
094:    				img.setRGB( x, y, color );
095:    			}
096:    		}

画像の中の全てのピクセルの座標(x,y)を参照するループをつくり、その座標の色が黒か白かを判定していきます。判定した色を(x,y)に代入していきます。

判定には、画像の中心座標(ox,oy)と(x,y)を結んだ線の距離lを使います。

ピタゴラスの定理

求めた距離lを(黒ピクセル幅+白ピクセル幅)で割った余りを求め、その値が白ピクセル幅以下であれば白色とし、超えていれば黒色としています。

同心円の白黒判定
098:    		try {
099:    			// imgをoutname(出力PNG)に保存
100:    			boolean result;
101:    			result = ImageIO.write( img, "PNG", new File( outname ) );
102:    		} catch ( Exception e ) {
103:    			// outname(出力PNG)の保存に失敗したときの処理
104:    			e.printStackTrace();
105:    			return;
106:    		}

BufferedImageクラスのimgのメモリ内のデータを、出力PNG名の変数(outname)に格納されているファイル名で保存します。この場合は、PNGファイル名が不正であったり、保存先のHDDなどが存在していなかったり、空き容量が少ないなどが原因で処理が失敗する可能性があります。

108:    		// 正常に終了
109:    		System.out.println( "正常に終了しました" );

全ての処理が正常終了すると、ここまで処理が実行されます。

■関連コンテンツ

模様の描画 いろいろな模様の描画方法を紹介

■新着情報

2019.09.13 長さの単位変換 1マイル、1フィートは何m?
2019.09.06 クイックソート 高速に配列に並び替える方法
2019.09.05 中央値(メディアン) 配列に格納されている値の中央値を求める
2019.09.05 最頻値 配列から出現回数が最も多い値の取得
2019.09.03 配列値の反転 配列の反転処理
2019.08.05 トランプの操作 トランプを操作するクラス

■広告

法人向けのETC専用カード

~約8,000名の受講生と80社以上の導入実績~ 企業向けプログラミング研修ならCodeCamp

日本最大級ショッピングサイト!お買い物なら楽天市場

Topへ