ゆるゆるプログラミング

・画像の一部切り出し

画像ファイルの一部の範囲を切り出して、別の画像ファイルを作る方法を解説します。

元の画像元の画像      切り出し画像切り出し画像

上の画像変換の例は、指定した矩形長方形)の範囲の画像を切り出したものです。矩形範囲は、切り出す左上隅のピクセル座標ピクセル幅・ピクセルの高さで指定します。ここで紹介する方法では、矩形の範囲が元の画像から外に出ないように指定し、外に出る場合は処理を実行しないようにしています。

Subimage.java
001:    import java.awt.image.BufferedImage;
002:    import java.io.File;
003:    import javax.imageio.ImageIO;
004:    import java.io.IOException;
005:    import java.awt.image.RasterFormatException;
006:    
007:    public class Subimage {
008:    	public static void main( String[] args ) {
009:    		String inname, outname;		// ファイル名
010:    		BufferedImage img = null;	// 画像格納クラス
011:    
012:    		// 入力した引数が6つ以上かを調べる
013:    		if ( 6 > args.length ) {
014:    			// 入力した引数が6つ未満の場合、使用方法を表示する
015:    			System.out.println(
016:    				"Subimage [入力JPEG名] [出力JPEG名] [X] [Y] [幅] [高さ]" );
017:    			return;
018:    		}
019:    
020:    		// 入力JPEG名をinnameに代入(拡張子".jpg"省略なし)
021:    		inname  = args[ 0 ];
022:    		// 出力JPEG名をoutnameに代入(拡張子".jpg"省略なし)
023:    		outname = args[ 1 ];
024:    
025:    		// 変数の宣言
026:    		int x, y;	// 切り出す左上のピクセル座標
027:    		int w, h;	// 切り出す画像サイズ
028:    
029:    		try {
030:    			// 引数を変換し、縁の幅に代入
031:    			x = Integer.valueOf( args[ 2 ] );
032:    			y = Integer.valueOf( args[ 3 ] );
033:    			w = Integer.valueOf( args[ 4 ] );
034:    			h = Integer.valueOf( args[ 5 ] );
035:    		}
036:    		catch( NumberFormatException ne ) {
037:    			System.out.println( "引数が不正です" );
038:    			return;
039:    		}
040:    
041:    		if ( ( 1 > w ) || ( 1 > h ) ) {
042:    			System.out.println( "画像サイズが不正です" );
043:    			return;
044:    		}
045:    
046:    
047:    		// JPEG画像の読み込み
048:    		try {
049:    			// inname(入力JPEG)を読み込んでimgにセット
050:    			img = ImageIO.read( new File( inname ) );
051:    
052:    		} catch (Exception e) {
053:    			// inname(入力JPEG)の読み込みに失敗したときの処理
054:    			 e.printStackTrace();
055:    			return;
056:    		}
057:    
058:    		// 切り出し処理
059:    		BufferedImage subimg = null;	// 切り出し画像格納クラス
060:    		try {
061:    			subimg = img.getSubimage( x, y, w, h );
062:    		}
063:    		catch ( RasterFormatException re ) {
064:    			System.out.println( "指定した範囲が画像の範囲外です" );
065:    			return;
066:    		}
067:    
068:    		// JPEG画像の保存
069:    		try {
070:    			// subimgをoutname(出力JPEG)に保存
071:    			boolean result;
072:    			result = ImageIO.write( subimg, "jpeg", new File( outname ) );
073:    		} catch ( Exception e ) {
074:    			// outname(出力JPEG)の保存に失敗したときの処理
075:    			e.printStackTrace();
076:    			return;
077:    		}
078:    
079:    		// 正常に終了
080:    		System.out.println( "正常に終了しました" );
081:    	}
082:    }

Subimageを実行

C:\talavax\javasample>java Subimage sampleimage001_400x320.jpg subimage.jpg
                                                                                                         160 200 200 100

1つ目の引数で渡したJPEGファイル名、3つ目と4つ目の引数でピクセル座標、5つ目と6つ目の引数で幅と高さを指定し、切り出した画像を2つ目の引数で指定したJPEGファイル名で保存します。

実行結果

・元の画像(sampleimage001_400x320.jpg)

元画像

・切り出し後の画像(subimage.jpg)

切り出し後の画像

画像が、左上隅のピクセル座標(160,200)、幅200ピクセル、高さ100ピクセル矩形範囲で切り出されました。

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

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

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

007:    public class Subimage {

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

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

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

009:    		String inname, outname;		// ファイル名
010:    		BufferedImage img = null;	// 画像格納クラス

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

012:    		// 入力した引数が6つ以上かを調べる
013:    		if ( 6 > args.length ) {
014:    			// 入力した引数が6つ未満の場合、使用方法を表示する
015:    			System.out.println(
016:    				"Subimage [入力JPEG名] [出力JPEG名] [X] [Y] [幅] [高さ]" );
017:    			return;
018:    		}

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

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

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

025:    		// 変数の宣言
026:    		int x, y;	// 切り出す左上のピクセル座標
027:    		int w, h;	// 切り出す画像サイズ
028:    
029:    		try {
030:    			// 引数を変換し、縁の幅に代入
031:    			x = Integer.valueOf( args[ 2 ] );
032:    			y = Integer.valueOf( args[ 3 ] );
033:    			w = Integer.valueOf( args[ 4 ] );
034:    			h = Integer.valueOf( args[ 5 ] );
035:    		}
036:    		catch( NumberFormatException ne ) {
037:    			System.out.println( "引数が不正です" );
038:    			return;
039:    		}
040:    
041:    		if ( ( 1 > w ) || ( 1 > h ) ) {
042:    			System.out.println( "画像サイズが不正です" );
043:    			return;
044:    		}

与えられた引数をそれぞれ、左隅のピクセル座標ピクセル幅、、ピクセルの高さを格納する変数に代入しています。

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

入力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メソッドを抜けるようにしています。

058:    		// 切り出し処理
059:    		BufferedImage subimg = null;	// 切り出し画像格納クラス
060:    		try {
061:    			subimg = img.getSubimage( x, y, w, h );
062:    		}
063:    		catch ( RasterFormatException re ) {
064:    			System.out.println( "指定した範囲が画像の範囲外です" );
065:    			return;
066:    		}

BufferedImageクラスsubimageメソッドでサブイメージを作っています。このときサブイメージのデータ配列は、imgと共有しています。

BufferedImage.subimageメソッド

public static void subimage( int x, int y, int w, int h )
■指定された矩形領域のサブイメージを返します。(元のBufferedImageのデータ配列を共有)

  パラメータ x     : 指定矩形の左上隅のx座標(単位ピクセル)
        y     : 指定矩形の左上隅のy座標(単位ピクセル)
        w     : 指定矩形の幅
        h     : 指定矩形の高さ

  戻り値     BufferedImageのサブイメージ

068:    		// JPEG画像の保存
069:    		try {
070:    			// subimgをoutname(出力JPEG)に保存
071:    			boolean result;
072:    			result = ImageIO.write( subimg, "jpeg", new File( outname ) );
073:    		} catch ( Exception e ) {
074:    			// outname(出力JPEG)の保存に失敗したときの処理
075:    			e.printStackTrace();
076:    			return;
077:    		}

BufferedImageクラスのsubimgのメモリ内のデータを、出力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を返します。

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

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

■関連コンテンツ

画像の座標系 画像の座標系について解説
画像ファイル形式 画像ファイル形式について解説

■新着情報

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

■広告

法人向けのETC専用カード

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

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

Topへ