2019/04/30 公開
・放射状模様
画像サイズと線の本数と線の角度を指定することで、黒と白の放射状模様画像を作成します。ここで紹介するプログラムで出力する画像の形式はPNGファイルです。

上の画像の例は、画像サイズ:256x256、線の本数:20、線の角度:10°で作成したものです。
Pattern_Radiation01.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_Radiation01 { 007: // Math.atan2メソッドを利用し、角度の戻り値を0~2πにしたもの 008: private static double atan3( double y, double x ) 009: { 010: // yが0以上の場合 011: if ( 0.0 <= y ) 012: return Math.atan2( y, x ); 013: 014: // yが0未満の場合 015: return Math.atan2( y, x ) + 2.0 * Math.PI; 016: } 017: 018: 019: // メイン 020: public static void main( String[] args ) { 021: // 変数宣言 022: int w, h; // 画像サイズ 023: int l_num; // 本数 024: double l_deg; // 線の角度 025: double w_deg; // 白部分の角度 026: String outname; // 出力ファイル名 027: BufferedImage img = null; // 画像格納クラス 028: 029: // 入力した引数が5以上かを調べる 030: if ( 5 > args.length ) { 031: // 入力した引数が5未満の場合、使用方法を表示する 032: System.out.println( 033: "Pattern_Radiation01 [PNG名] [幅] [高] [線の本数] [線の角度]" ); 034: return; 035: } 036: 037: try { 038: // 引数を変換し、画像の幅と高さをwとhに代入 039: w = Integer.valueOf( args[ 1 ] ); 040: h = Integer.valueOf( args[ 2 ] ); 041: 042: // 引数を変換し、線の本数l_numに代入 043: l_num = Integer.valueOf( args[ 3 ] ); 044: if ( 1 > l_num ) { 045: System.out.println( "線の本数に1以上を指定!" ); 046: return; 047: } 048: 049: // 引数を変換し、線の角度l_degに代入 050: l_deg = Double.valueOf( args[ 4 ] ); 051: if ( 0.0 >= l_deg ) { 052: System.out.println( "線の角度に0.0より大きい値を指定!" ); 053: return; 054: } 055: } 056: catch( NumberFormatException ne ) 057: { 058: System.out.println( "引数が不正です" ); 059: return; 060: } 061: // 出力PNG名をoutnameに代入(拡張子".png"省略なし) 062: outname = args[ 0 ]; 063: 064: // 新しい画像を作成 065: // 24ビットカラーの画像を作成 066: try { 067: img = new BufferedImage( w, h, 068: BufferedImage.TYPE_INT_RGB ); 069: } catch ( Exception e ) { 070: // 画像作成に失敗したときの処理 071: e.printStackTrace(); 072: return; 073: } 074: 075: // 放射状模様 画像作成 076: int x, y; 077: int color, r, g, b; // 計算した色 078: double mx, my; // 画像の中心の座標 079: double deg, rad; // (mx,my)を原点とした(x,y)の角度 080: 081: // 画像の中心座標を計算 082: mx = (double)( w - 1 ) / 2.0; 083: my = (double)( h - 1 ) / 2.0; 084: 085: // 白部分の角度 086: w_deg = ( 360.0 - (double)l_num * l_deg ) / (double)l_num; 087: 088: // 画像作成 089: for ( y = 0; y < h; ++ y ) { 090: for ( x = 0; x < w; ++ x ) { 091: // 角度(ラジアン)を計算 092: rad = atan3( (double)y - my, (double)x - my ); 093: 094: // ラジアンを度に変換 095: deg = rad * 180.0 / Math.PI; 096: 097: // 判定式 098: if ( l_deg >= ( deg % ( l_deg + w_deg ) ) ) 099: r = g = b = 0; 100: else 101: r = g = b = 255; 102: 103: // rgbを合成 104: color = ( r << 16 ) + ( g << 8 ) + b; 105: // 色を設定 106: img.setRGB( x, y, color ); 107: } 108: } 109: 110: try { 111: // imgをoutname(出力PNG)に保存 112: boolean result; 113: result = ImageIO.write( img, "PNG", new File( outname ) ); 114: } catch ( Exception e ) { 115: // outname(出力PNG)の保存に失敗したときの処理 116: e.printStackTrace(); 117: return; 118: } 119: 120: // 正常に終了 121: System.out.println( "正常に終了しました" ); 122: } 123: }
Pattern_Radiation01の実行例
java Pattern_Radiation01 pattern_radiation01.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_Radiation01 {
クラス名を、Pattern_Radiation01としています。
007: // Math.atan2メソッドを利用し、角度の戻り値を0~2πにしたもの 008: private static double atan3( double y, double x ) 009: { 010: // yが0以上の場合 011: if ( 0.0 <= y ) 012: return Math.atan2( y, x ); 013: 014: // yが0未満の場合 015: return Math.atan2( y, x ) + 2.0 * Math.PI; 016: }
引数xとyから角度(ラジアン)を0~2πの範囲で求めるメソッドです。
詳しくはこちらを参照してください。「逆三角関数 atan3」
019: // メイン 020: public static void main( String[] args ) {
このmainメソッドからプログラムを実行します。
021: // 変数宣言 022: int w, h; // 画像サイズ 023: int l_num; // 本数 024: double l_deg; // 線の角度 025: double w_deg; // 白部分の角度 026: String outname; // 出力ファイル名 027: BufferedImage img = null; // 画像格納クラス
このプログラムで使う変数を宣言しています。
029: // 入力した引数が5以上かを調べる 030: if ( 5 > args.length ) { 031: // 入力した引数が5未満の場合、使用方法を表示する 032: System.out.println( 033: "Pattern_Radiation01 [PNG名] [幅] [高] [線の本数] [線の角度]" ); 034: return; 035: }
5つ以上の引数が与えられたかをチェックし、5つ未満の場合に、使い方のメッセージを表示し、returnによってmainメソッドを抜けています。
037: try { 038: // 引数を変換し、画像の幅と高さをwとhに代入 039: w = Integer.valueOf( args[ 1 ] ); 040: h = Integer.valueOf( args[ 2 ] ); 041: 042: // 引数を変換し、線の本数l_numに代入 043: l_num = Integer.valueOf( args[ 3 ] ); 044: if ( 1 > l_num ) { 045: System.out.println( "線の本数に1以上を指定!" ); 046: return; 047: } 048: 049: // 引数を変換し、線の角度l_degに代入 050: l_deg = Double.valueOf( args[ 4 ] ); 051: if ( 0.0 >= l_deg ) { 052: System.out.println( "線の角度に0.0より大きい値を指定!" ); 053: return; 054: } 055: } 056: catch( NumberFormatException ne ) 057: { 058: System.out.println( "引数が不正です" ); 059: return; 060: } 061: // 出力PNG名をoutnameに代入(拡張子".png"省略なし) 062: outname = args[ 0 ];
与えられた引数をそれぞれ、作成する画像の幅/高さ、線の本数/角度、出力PNG名を格納する変数に代入しています。画像の幅/高さ/線の本数は、Integerクラスを使ってint型に変換しています。線の角度は、Doubleクラスを使ってdouble型に変換しています。
064: // 新しい画像を作成 065: // 24ビットカラーの画像を作成 066: try { 067: img = new BufferedImage( w, h, 068: BufferedImage.TYPE_INT_RGB ); 069: } catch ( Exception e ) { 070: // 画像作成に失敗したときの処理 071: e.printStackTrace(); 072: return; 073: }
BufferedImageクラスのコンストラクタで、新しいBufferedImageを構築しています。
BufferedImageコンストラクタ
■新しい BufferedImage を構築します。 パラメータ width : 構築する画像の横ピクセル height : 構築する画像の縦ピクセル imageType : 構築する画像のイメージ形式
075: // 放射状模様 画像作成 076: int x, y; 077: int color, r, g, b; // 計算した色 078: double mx, my; // 画像の中心の座標 079: double deg, rad; // (mx,my)を原点とした(x,y)の角度
081: // 画像の中心座標を計算 082: mx = (double)( w - 1 ) / 2.0; 083: my = (double)( h - 1 ) / 2.0;
画像の中心座標を計算しています。画像の座標の範囲は、左上(0,0)~右下(w-1,h-1)なので、(w-1)と(h-1)を2で割った値が画像の中心座標になります。
画像の中心座標の計算方法はこちらを参照してください。「画像の中心座標」
085: // 白部分の角度 086: w_deg = ( 360.0 - (double)l_num * l_deg ) / (double)l_num;
白の部分(線でない部分)の角度を計算しています。(線の本数×線の角度)を360から引いた値が白部分の合計の角度です。その角度を線の本数で割った値が白い部分の1つの角度として計算できます。
088: // 画像作成 089: for ( y = 0; y < h; ++ y ) { 090: for ( x = 0; x < w; ++ x ) { 091: // 角度(ラジアン)を計算 092: rad = atan3( (double)y - my, (double)x - my ); 093: 094: // ラジアンを度に変換 095: deg = rad * 180.0 / Math.PI; 096: 097: // 判定式 098: if ( l_deg >= ( deg % ( l_deg + w_deg ) ) ) 099: r = g = b = 0; 100: else 101: r = g = b = 255; 102: 103: // rgbを合成 104: color = ( r << 16 ) + ( g << 8 ) + b; 105: // 色を設定 106: img.setRGB( x, y, color ); 107: } 108: }
画像の中の全てのピクセルの座標(x,y)を参照するループをつくり、その座標の色が黒か白かを判定していきます。判定した色を(x,y)に代入していきます。
判定には、画像の中心座標(mx,my)と(x,y)を結んだ線とx軸との角度rad(ラジアン)をatan3メソッドで求め、その角度radを°単位に変換した角度deg(°)を使います。
求めた角度deg(°)を(線の角度+白部分の角度)で割った余りを求め、その値が線の角度以下であれば黒色とし、線の角度を超えていれば白色としています。
110: try { 111: // imgをoutname(出力PNG)に保存 112: boolean result; 113: result = ImageIO.write( img, "PNG", new File( outname ) ); 114: } catch ( Exception e ) { 115: // outname(出力PNG)の保存に失敗したときの処理 116: e.printStackTrace(); 117: return; 118: }
BufferedImageクラスのimgのメモリ内のデータを、出力PNG名の変数(outname)に格納されているファイル名で保存します。この場合は、PNGファイル名が不正であったり、保存先のHDDなどが存在していなかったり、空き容量が少ないなどが原因で処理が失敗する可能性があります。
120: // 正常に終了 121: System.out.println( "正常に終了しました" );
全ての処理が正常終了すると、ここまで処理が実行されます。
以上です。
■関連コンテンツ
模様の描画 | いろいろな模様の描画方法を紹介 |
画像の座標系 | 画像の座標系について解説 |
画像の中心座標 | 画像の中心座標は? |
タイル画像の素材 | フリーの素材を提供 |
■新着情報
2022.07.07 | 外部プログラムの実行 | exeファイル実行 |
2022.07.06 | 完全数 | 6=1+2+3 |
■広告
