ゆるゆるプログラミング

・縁付き画像変換

ここでの縁付き画像変換とは、カラー画像の周りを一定幅の色で塗り潰すことです。

元の画像元の画像      縁付き画像縁付き画像

上の画像変換の例は、元の画像の周りを8ピクセル幅の赤色で塗り潰したものです。デジタルカメラ・スマートフォン・タブレットなどで撮影した写真画像の周りに色を付けたいときにこの方法を使います。ここで紹介する方法は、元の画像の大きさを変えないで縁の色を付けるものなので、上下左右の画像の縁の部分が指定色で塗り潰されます。

Edge.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 Edge {
007:    	public static void main( String[] args ) {
008:    		int    edgew;			// 描画する縁の幅(Pixel)
009:    		int    r, g, b, color;		// 縁の色
010:    		String inname, outname;		// ファイル名
011:    		BufferedImage img = null;	// 画像格納クラス
012:    
013:    		// 入力した引数が6つ以上かを調べる
014:    		if ( 6 > args.length ) {
015:    			// 入力した引数が6つ未満の場合、使用方法を表示する
016:    			System.out.println( "Edge [入力JPEG名]  [出力JPEG名]
017:    									 [幅] [R][G][B]" );
018:    			return;
019:    		}
020:    
021:    		// 入力JPEG名をinnameに代入(拡張子".jpg"省略なし)
022:    		inname  = args[ 0 ];
023:    		// 出力JPEG名をoutnameに代入(拡張子".jpg"省略なし)
024:    		outname = args[ 1 ];
025:    
026:    		try {
027:    			// 引数を変換し、縁の幅に代入
028:    			edgew = Integer.valueOf( args[ 2 ] );
029:    			// 引数を変換し、縁の色に代入
030:    			r = Integer.valueOf( args[ 3 ] );
031:    			g = Integer.valueOf( args[ 4 ] );
032:    			b = Integer.valueOf( args[ 5 ] );
033:    			color = ( r << 16 ) + ( g << 8 ) + b;
034:    		}
035:    		catch( NumberFormatException ne )
036:    		{
037:    			System.out.println( "引数が不正です" );
038:    			return;
039:    		}
040:    
041:    		// JPEG画像の読み込み
042:    		try {
043:    			// inname(入力JPEG)を読み込んでimgにセット
044:    			img = ImageIO.read( new File( inname ) );
045:    
046:    		} catch (Exception e) {
047:    			// inname(入力JPEG)の読み込みに失敗したときの処理
048:    			 e.printStackTrace();
049:    			return;
050:    		}
051:    
052:    		// 画像の色の持ち方をチェック
053:    		if ( BufferedImage.TYPE_3BYTE_BGR != img.getType() )
054:    		{
055:    			System.out.println( "対応していないカラーモデルです!("
056:    									 + inname +")" );
057:    			return;
058:    		}
059:    
060:    		// 縁の描画
061:    		int x, y;
062:    		int width, height;
063:    
064:    		// 画像サイズの取得
065:    		width = img.getWidth();
066:    		height= img.getHeight();
067:    
068:    		// 縦の縁を描画
069:    		for ( y = 0; y < height; ++ y ) {
070:    			for ( x = 0; x < edgew; ++ x ) {
071:    				img.setRGB( x, y, color );
072:    				img.setRGB( width - x - 1, y, color );
073:    			}
074:    		}
075:    
076:    		// 横の縁を描画
077:    		for ( x = 0; x < width; ++ x ) {
078:    			for ( y = 0; y < edgew; ++ y ) {
079:    				img.setRGB( x, y, color );
080:    				img.setRGB( x, height - y - 1, color );
081:    			}
082:    		}
083:    
084:    		// JPEG画像の保存
085:    		try {
086:    			// imgをoutname(出力JPEG)に保存
087:    			boolean result;
088:    			result = ImageIO.write( img, "jpeg", new File( outname ) );
089:    		} catch ( Exception e ) {
090:    			// outname(出力JPEG)の保存に失敗したときの処理
091:    			e.printStackTrace();
092:    			return;
093:    		}
094:    
095:    		// 正常に終了
096:    		System.out.println( "正常に終了しました" );
097:    	}
098:    }

Edgeを実行

C:\talavax\javasample>java Edge sampleimage001_400x320.jpg edge.jpg 16 200 200 100

1つ目の引数で渡したJPEGファイルに、3つ目の引数で指定した幅・4~6の引数で指定した色の縁を描画し、2つ目の引数で指定したJPEGファイル名で保存します。

実行結果

・元の画像(sampleimage001_400x320.jpg)

元画像

・変換後の縁付き画像(edge.jpg)

縁付き画像

画像が、白色と灰色(グレー)と黒色で表現されました。

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

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 Edge {

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

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

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

008:    		int    edgew;			// 描画する縁の幅(Pixel)
009:    		int    r, g, b, color;		// 縁の色
010:    		String inname, outname;		// ファイル名
011:    		BufferedImage img = null;	// 画像格納クラス

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

014:    		if ( 6 > args.length ) {
015:    			// 入力した引数が6つ未満の場合、使用方法を表示する
016:    			System.out.println( "Edge [入力JPEG名]  [出力JPEG名]
017:    									 [幅] [R][G][B]" );
018:    			return;
019:    		}

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

021:    		// 入力JPEG名をinnameに代入(拡張子".jpg"省略なし)
022:    		inname  = args[ 0 ];
023:    		// 出力JPEG名をoutnameに代入(拡張子".jpg"省略なし)
024:    		outname = args[ 1 ];

与えられた引数をそれぞれ、入力JPEG名の変数(inname)、出力JPEG名の変数(outname)代入しています。

026:    		try {
027:    			// 引数を変換し、縁の幅に代入
028:    			edgew = Integer.valueOf( args[ 2 ] );
029:    			// 引数を変換し、縁の色に代入
030:    			r = Integer.valueOf( args[ 3 ] );
031:    			g = Integer.valueOf( args[ 4 ] );
032:    			b = Integer.valueOf( args[ 5 ] );
033:    			color = ( r << 16 ) + ( g << 8 ) + b;
034:    		}
035:    		catch( NumberFormatException ne )
036:    		{
037:    			System.out.println( "引数が不正です" );
038:    			return;
039:    		}

与えられた引数をそれぞれ、ピクセル幅、縁の色を格納する変数に代入しています。

041:    		// JPEG画像の読み込み
042:    		try {
043:    			// inname(入力JPEG)を読み込んでimgにセット
044:    			img = ImageIO.read( new File( inname ) );
045:    
046:    		} catch (Exception e) {
047:    			// inname(入力JPEG)の読み込みに失敗したときの処理
048:    			 e.printStackTrace();
049:    			return;
050:    		}

入力JPEG名の変数(inname)を読み込んで、BufferedImageクラスのimgに格納しています。この処理には、ImageIOクラスreadメソッドを使います。

ImageIO.readメソッド

public static BufferedImage read( File input ) throws IOException
■Fileオブジェクトを復元した結果をBufferedImageに格納します。

  パラメータ input : Fileオブジェクト

  戻り値     inputを復元したBufferedImageaを返します。

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

052:    		// 画像の色の持ち方をチェック
053:    		if ( BufferedImage.TYPE_3BYTE_BGR != img.getType() )
054:    		{
055:    			System.out.println( "対応していないカラーモデルです!("
056:    									 + inname +")" );
057:    			return;
058:    		}

BufferedImageクラスgetTypeメソッドで画像のイメージ型を取得しています。

BufferedImage.getTypeメソッド

public static int getType()
■イメージ型を返します。
  パラメータ なし

  戻り値     BufferedImage のイメージ型を返します。

060:    		// 縁の描画
061:    		int x, y;
062:    		int width, height;

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

064:    		// 画像サイズの取得
065:    		width = img.getWidth();
066:    		height= img.getHeight();

widthに画像の幅(ピクセル)、heightに画像の高さ(ピクセル)を代入しています。

068:    		// 縦の縁を描画
069:    		for ( y = 0; y < height; ++ y ) {
070:    			for ( x = 0; x < edgew; ++ x ) {
071:    				img.setRGB( x, y, color );
072:    				img.setRGB( width - x - 1, y, color );
073:    			}
074:    		}
075:    
076:    		// 横の縁を描画
077:    		for ( x = 0; x < width; ++ x ) {
078:    			for ( y = 0; y < edgew; ++ y ) {
079:    				img.setRGB( x, y, color );
080:    				img.setRGB( x, height - y - 1, color );
081:    			}
082:    		}

縦横それぞれの縁のピクセル座標を求めるループをつくり、その座標に縁の色を描画しています。

BufferedImage.setRGBメソッド

public static void setRGB( int x, int y, int color )
■(x,y)で指定した画像座標の色情報を設定します。

  パラメータ x     : 画像のx座標(単位ピクセル)
        y     : 画像のy座標(単位ピクセル)
        color : 画像の色

  戻り値     無し

084:    		// JPEG画像の保存
085:    		try {
086:    			// imgをoutname(出力JPEG)に保存
087:    			boolean result;
088:    			result = ImageIO.write( img, "jpeg", new File( outname ) );
089:    		} catch ( Exception e ) {
090:    			// outname(出力JPEG)の保存に失敗したときの処理
091:    			e.printStackTrace();
092:    			return;
093:    		}

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

ImageIO.wrireメソッド

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

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

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

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

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

■関連コンテンツ

画像の色 画像の色について解説
画像ファイル形式 画像ファイル形式について解説
for文 繰り返し処理に使用するfor文について解説
光と色の3原色 光と色の3原色の考え方を解説

■新着情報

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

■広告

法人向けのETC専用カード

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

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

Topへ