ゆるゆるプログラミング

・グラデーション画像(放射状)

グラデーションとは色が段階的に変化する様子のことで、この色変化の様子を画像にしたものがグラデーション画像です。以下がグラデーション画像の例で、色が画像の中心から外側に向かって赤色から青色に変化しています。

グラデーション画像(放射状)グラデーション画像(放射状)

ここでは円の半径と2つの色を与えることで放射状に色が変化するグラデーション画像を作るソースコードを解説します。

Gradation2.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 Gradation2 {
007:    	public static void main( String[] args ) {
008:    		// 変数宣言
009:    		int rd;		// 半径
010:    		int w, h;	// 画像サイズ
011:    		int cx, cy;	// 円の中心座標
012:    		int r1, g1, b1;	// 開始色
013:    		int r2, g2, b2;	// 終了色
014:    		String outname;	// 出力ファイル名
015:    		BufferedImage img = null;	// 画像格納クラス
016:    
017:    		// 入力した引数が8以上かを調べる
018:    		if ( 8 > args.length ) {
019:    			// 入力した引数が8未満の場合、使用方法を表示する
020:    			System.out.println( 
021:    				"Gradation2 [PNG名][半径][R1][G1][B1][R2][G2][B2]" );
022:    			return;
023:    		}
024:    
025:    		try {
026:    			// 引数を変換し、半径に代入
027:    			rd =  Integer.valueOf( args[ 1 ] );
028:    			// 引数を変換し、開始色に代入
029:    			r1 =  Integer.valueOf( args[ 2 ] );
030:    			g1 =  Integer.valueOf( args[ 3 ] );
031:    			b1 =  Integer.valueOf( args[ 4 ] );
032:    			// 引数を変換し、終了色に代入
033:    			r2 =  Integer.valueOf( args[ 5 ] );
034:    			g2 =  Integer.valueOf( args[ 6 ] );
035:    			b2 =  Integer.valueOf( args[ 7 ] );
036:    		}
037:    		catch( NumberFormatException ne )
038:    		{
039:    			System.out.println( "引数が不正です" );
040:    			return;
041:    		}
042:    		// 出力PNG名をoutnameに代入(拡張子".png"省略なし)
043:    		outname = args[ 0 ];
044:    
045:    		// 画像サイズを半径から計算
046:    		w = rd * 2 + 1;
047:    		h = rd * 2 + 1;
048:    
049:    		// 円の中心座標を計算
050:    		cx = rd;
051:    		cy = rd;
052:    
053:    		// 新しい画像を作成
054:    		// 24ビットカラーの画像を作成
055:    		try {
056:    			img = new BufferedImage( w, h,
057:    						 BufferedImage.TYPE_INT_RGB );
058:    		} catch ( Exception e ) {
059:    			// 画像作成に失敗したときの処理
060:    			e.printStackTrace();
061:    			return;
062:    		}
063:    
064:    		// グラデーション作成
065:    		int    x, y;
066:    		int    color, r, g, b;	// 計算した色
067:    		double l;			// 距離		
068:    		double d;			// 距離		
069:    
070:    		for ( y = 0; y < h; ++ y ) {
071:    			for ( x = 0; x < w; ++ x ) {
072:    				// 円の中心(cx,cy)と(x,y)との距離lを計算
073:    				l = Math.sqrt( ( x - cx ) * ( x - cx ) + ( y - cy ) * ( y - cy ) );
074:    				// 距離dを計算
075:    				d = (double)l / (double)rd;
076:    
077:    				// 色を計算
078:    				r = (int)( (double)( r2 - r1 ) * d + (double)r1 );
079:    				g = (int)( (double)( g2 - g1 ) * d + (double)g1 );
080:    				b = (int)( (double)( b2 - b1 ) * d + (double)b1 );
081:    
082:    				// 色を0~255の範囲に収める
083:    				if ( 0 > r ) r = 0;
084:    				if ( 255 < r ) r = 255;
085:    				if ( 0 > g ) g = 0;
086:    				if ( 255 < g ) g = 255;
087:    				if ( 0 > b ) b = 0;
088:    				if ( 255 < b ) b = 255;
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:    }

Gradation2を実行

C:\talavax\javasample>java Gradation2 gradation2.png 128 0 255 0 255 255 0

引数2で円の半径128(pixel)を渡し、引数3と4と5で開始色R1=0・G1=255・B1=0、引数6と7と8で終了色R2=255・G2=255・B2=0を渡して、引数1のPNGファイル名でグラデーション画像を保存します。

実行結果

・作成したグラデーション画像(gradation2.png)

作成画像

色が緑色(R1=0・G1=255・B1=0)から黄色(R2=255・G2=255・B2=0)に滑らかに変化するグラデーション画像が作成されました。画像サイズは257x257pixelです。

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

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」というパッケージにあるクラスを、このプログラム内で使うために記述します。 この記述により、ImageIOクラスBufferedImageクラスが利用できるようになります。

006:    public class Gradation2 {

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

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

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

008:    		// 変数宣言
009:    		int rd;		// 半径
010:    		int w, h;	// 画像サイズ
011:    		int cx, cy;	// 円の中心座標
012:    		int r1, g1, b1;	// 開始色
013:    		int r2, g2, b2;	// 終了色
014:    		String outname;	// 出力ファイル名
015:    		BufferedImage img = null;	// 画像格納クラス

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

017:    		// 入力した引数が8以上かを調べる
018:    		if ( 8 > args.length ) {
019:    			// 入力した引数が8未満の場合、使用方法を表示する
020:    			System.out.println( 
021:    				"Gradation2 [PNG名][半径][R1][G1][B1][R2][G2][B2]" );
022:    			return;
023:    		}

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

025:    		try {
026:    			// 引数を変換し、半径に代入
027:    			rd =  Integer.valueOf( args[ 1 ] );
028:    			// 引数を変換し、開始色に代入
029:    			r1 =  Integer.valueOf( args[ 2 ] );
030:    			g1 =  Integer.valueOf( args[ 3 ] );
031:    			b1 =  Integer.valueOf( args[ 4 ] );
032:    			// 引数を変換し、終了色に代入
033:    			r2 =  Integer.valueOf( args[ 5 ] );
034:    			g2 =  Integer.valueOf( args[ 6 ] );
035:    			b2 =  Integer.valueOf( args[ 7 ] );
036:    		}
037:    		catch( NumberFormatException ne )
038:    		{
039:    			System.out.println( "引数が不正です" );
040:    			return;
041:    		}
042:    		// 出力PNG名をoutnameに代入(拡張子".png"省略なし)
043:    		outname = args[ 0 ];

与えられた引数をそれぞれ代入しています。

045:    		// 画像サイズを半径から計算
046:    		w = rd * 2 + 1;
047:    		h = rd * 2 + 1;

半径から画像サイズを計算してまます。このソースコードで画像の幅・高さは、半径の2倍に1を足した値にしています。

049:    		// 円の中心座標を計算
050:    		cx = rd;
051:    		cy = rd;

円の中心座標を変数cxと変数cyに代入しています。画像の中心が円の中心になるように(rd,rd)を中心座標としています。

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

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

BufferedImageコンストラクタ

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

imgTypeで指定しているTYPE_INT_RGBは、整数ピクセルにパックされた 8 ビット RGB 色成分によるイメージを表します。これを指定することで24ビットの画像を作成できます。

try { ~ } catchは、失敗する可能性がある処理を波括弧で囲み、その処理に失敗したときにcatch { ~ }の波括弧で囲まれた処理を実行するということです。この場合は、PNGファイル名が不正であったり、存在していなかったり、フォーマットが違っているなどが原因で処理が失敗する可能性があります。処理が失敗するとreturnによってmainメソッドを抜けるようにしています。

064:    		// グラデーション作成
065:    		int    x, y;
066:    		int    color, r, g, b;	// 計算した色
067:    		double l;			// 距離		
068:    		double d;			// 距離		

グラデーション画像作成で使う変数を宣言しています。

070:    		for ( y = 0; y < h; ++ y ) {
071:    			for ( x = 0; x < w; ++ x ) {

画像の中の全てのピクセルの座標を参照するループをつくっています。具体的には、変数yを0~h-1、変数xを0~w-1に変化させています。

072:    				// 円の中心(cx,cy)と(x,y)との距離lを計算
073:    				l = Math.sqrt( ( x - cx ) * ( x - cx ) + ( y - cy ) * ( y - cy ) );

(x,y)と(cx,cy)の距離を計算して変数lに代入しています。

074:    				// 距離dを計算
075:    				d = (double)l / (double)rd;
076:    
077:    				// 色を計算
078:    				r = (int)( (double)( r2 - r1 ) * d + (double)r1 );
079:    				g = (int)( (double)( g2 - g1 ) * d + (double)g1 );
080:    				b = (int)( (double)( b2 - b1 ) * d + (double)b1 );
081:    
082:    				// 色を0~255の範囲に収める
083:    				if ( 0 > r ) r = 0;
084:    				if ( 255 < r ) r = 255;
085:    				if ( 0 > g ) g = 0;
086:    				if ( 255 < g ) g = 255;
087:    				if ( 0 > b ) b = 0;
088:    				if ( 255 < b ) b = 255;

変数lの値から距離を計算しています。l=0.0のとき距離dが0.0、l=rdのとき距離dが1.0になるようし、その距離での色を計算しています。(x,y)と(cx,cy)の距離がrdを超えると距離dが1.0を超えます。その結果rとgとbの値が0~255の範囲外になることがあるので、それぞれの値が範囲に収まるようにif文で制御しています。

■関連コンテンツ

グラデーション(3) グラデーションを作成する方法を解説

090:    				// r,g,bの色を合成
091:    				color = ( r << 16 ) + ( g << 8 ) + b;

計算したRGB合成して、色(変数color)を作成しています。

093:    				// 合成した色を(x,y)に設定
094:    				img.setRGB( x, y, color );

色(変数color)を(x,y)に代入しています。

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などが存在していなかったり、空き容量が少ないなどが原因で処理が失敗する可能性があります。

ImageIO.writeメソッド

public static boolean write( RenderedImage im, String formatName, File output ) throws IOException
■BufferedImageを画像ファイルに保存します。

  パラメータ RenderedImage : 保存するRenderedImage
                  formatName     : 画像ファイルのフォーマット(png/jpeg/bmp/gifなど)
                  output             : Fileオブジェクト

  戻り値     保存に成功するとtrue、失敗するとfalseを返します。

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

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

■関連コンテンツ

グラデーション グラデーションを作成する方法を解説
光と色の3原色 光と色の3原色の考え方を解説
画像の色 画像の色について解説
画像ファイル形式 画像ファイル形式について解説
for文 繰り返し処理に使用するfor文について解説
コマンドライン引数 外部からの値を受け取る方法について解説

■新着情報

2017.11.17 N値化 カラー画像をN値化する方法について解説
2017.11.16 最も近い値の取得 指定値に最も近い配列の値を取得する方法を解説
2017.10.02 アルファ値(透過) アルファ値(透過)について

■広告

法人向けのETC専用カード

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

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

Topへ