2023.07.16

画像処理

画像をセピア色にする

このサイトで紹介している画像操作クラスMyBufferedImage0」を利用して、フルカラー画像をセピア調の色に変換する方法を説明します。

元の画像
元の画像
右矢印
セピア色変換画像
セピア色画像

MyBufferedImage0」には画像の読込、画像の保存、色の取得、色の設定など画像処理に必要なメソッドが用意されているので、比較的簡単に画像処理プログラムを作成することができます。

セピア色に変換する方法

以下の方法で変換します。

①元の画像をMyBufferedImage0.readメソッドで読み込む

②読み込んだ画像色を以下に式で変換する
   新しいr = r * 0.393 + g * 0.769 + b * 0.189
   新しいg = r * 0.349 + g * 0.686 + b * 0.168
   新しいb = r * 0.272 + g * 0.534 + b * 0.131

③画像をMyBufferedImage0.writeJPGメソッドで保存

以上です。

Javaソースコード

画像PNG形式ファイルに変換するJavaソースコードです。MyBufferedImage0クラスを利用しています。

MySepia.java

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
public class MySepia {
	public static void main(String[] args) {
		// ファイル名
		String inname, outname;

		// 入力した引数が2つ以上かを調べる
		if ( 2 > args.length ) {
			// 入力した引数が2つ未満の場合、使用方法を表示する
			System.out.println( "MySubImage [入力画像名]  [出力JPG名]" );
			return;
		}

		// 入力画像名をinnameに代入(拡張子省略なし)
		inname  = args[ 0 ];
		// 出力JPG名をoutnameに代入(拡張子".jpg"省略なし)
		outname = args[ 1 ];

		// 画像操作クラス
		MyBufferedImage0 img = new MyBufferedImage0();	// 入力用

		// 画像の読み込み
		if ( !img.read( inname ) ) {
			System.out.println( "読み込みに失敗しました!(" + inname +")" );
			return;
		}

		// 読み込んだ画像のサイズ
		int w = img.getWidth();
		int h = img.getHeight();

		// セピア色に変換
		int defcolor = 0xffffffff;
		for ( int y = 0; y < h; y++ ) {
			for ( int x = 0; x < w; x++ ) {
				// 色を取得
				int color = img.getRGB( x, y, defcolor );
				int r = MyBufferedImage0.getR( color );
				int g = MyBufferedImage0.getG( color );
				int b = MyBufferedImage0.getB( color );

				// セピア色に変換
				int new_r =  (int)(  (double)r * 0.393 +  (double)g * 0.769 +  (double)b * 0.189 );
				int new_g =  (int)(  (double)r * 0.349 +  (double)g * 0.686 +  (double)b * 0.168 );
				int new_b =  (int)(  (double)r * 0.272 +  (double)g * 0.534 +  (double)b * 0.131 );

				// 変換した色を設定
				img.setRGB( x, y, new_r, new_g, new_b );
			}
		}

		// JPG画像の保存
		if ( !img.writeJPG( outname ) ) {
			System.out.println( "保存に失敗しました!(" + outname +")" );
			return;
		}

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

このソースのコンパイルには、JavaソースファイルMyBufferedImage0.Java」が必要です。以下から取得してください。

BufferedImageクラスを利用して、利便性の高い画像操作クラスを作成しました。興味のある方は、是非ご覧ください。

2022.11.16

実行方法

コンパイル ソースコードが「ANSI」の場合

C:\talavax\javasample>javac -encoding sjis MySepia.java

コンパイル ソースコードが「UTF-8」の場合

C:\talavax\javasample>javac MySepia.java

MyBufferedImage0.Javaは、指定しなくてもコンパイルされます。

sampleimage001_400x320.jpgの一部を切り出してsepia.jpgに保存

java MySepia sampleimage001_400x320.jpg sepia.jpg

sampleimage001_400x320.jpgの色を変更して、sepia.jpgに保存します。

変換結果

元の画像 セピア調の画像

Javaソースコードの解説

ここから、ソースコードを詳しく解説していきます。

001
public class MySepia {

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

002
	public static void main(String[] args) {

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

003
004
		// ファイル名
		String inname, outname;

このプログラムで使うファイル名を格納する変数を宣言しています。

006
007
008
009
010
011
		// 入力した引数が2つ以上かを調べる
		if ( 2 > args.length ) {
			// 入力した引数が2つ未満の場合、使用方法を表示する
			System.out.println( "MySubImage [入力画像名]  [出力JPG名]" );
			return;
		}

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

013
014
015
016
		// 入力画像名をinnameに代入(拡張子省略なし)
		inname  = args[ 0 ];
		// 出力JPG名をoutnameに代入(拡張子".jpg"省略なし)
		outname = args[ 1 ];

与えられた先頭の2つの引数をそれぞれ、入力画像名の変数(inname)と出力PNG名の変数(outname)に代入しています。

018
019
		// 画像操作クラス
		MyBufferedImage0 img = new MyBufferedImage0();	// 入力用

画像を操作するMyBufferedImage0クラスの実体imgを作成しています。

imgは色変換する画像を格納するオブジェクトです。

021
022
023
024
025
		// 画像の読み込み
		if ( !img.read( inname ) ) {
			System.out.println( "読み込みに失敗しました!(" + inname +")" );
			return;
		}

MyBufferedImage0.readメソッドで、画像ファイルinnameをimgに読み込んでいます。

MyBufferedImage0.readメソッド

boolean create( String imgname )
・指定した画像ファイルを読み込みます。

  パラメータ imgname  : フルパスの画像ファイル名(拡張子は省略不可)

  戻り値    true   : 画像の読み込みに成功
         false  : 画像の読み込みに失敗
027
028
029
		// 読み込んだ画像のサイズ
		int w = img.getWidth();
		int h = img.getHeight();

imgに読み込んだ画像の幅を変数w、高さを変数hに代入しています。

MyBufferedImage0.getWidthメソッド

public int getWidth()
・画像の横のピクセルサイズを返します。

  パラメータ なし

  戻り値     画像の横ピクセル数

MyBufferedImage0.getHeightメソッド

public int getHeight()
・画像の縦のピクセルサイズを返します。

  パラメータ なし

  戻り値     画像の縦ピクセル数
031
032
		// セピア色に変換
		int defcolor = 0xffffffff;

ここから、セピア色の変換処理です。

int型変数defcolorは、元の画像の外側の色を取得しようとしたときに戻す色を指定しています。任意の色に変更可能です。

セピア色に変換する処理では、色を取得するときに元画像の外側のピクセル座標を指定することはないので実際には使用しません。

033
034
		for ( int y = 0; y < h; y++ ) {
			for ( int x = 0; x < w; x++ ) {

for文2重ループでを作成しています。

切り出し後の画像ピクセル座標(xは0~w-1、yは0~h-1)を処理するループにしています。

035
036
				// 色を取得
				int color = img.getRGB( x, y, defcolor );

変数colorに、ピクセル座標( x, y )の色を代入しています。

MyBufferedImage0.getRGBメソッド

int getRGB( int x, int y, int defcolor )
・指定した座標の色を取得します。

  パラメータ x  : ピクセルのx座標
        y  : ピクセルのy座標
        defcolor   : (x,y)が画像の範囲外の場合に戻す値

  戻り値    RGBを合成した色
037
038
039
				int r = MyBufferedImage0.getR( color );
				int g = MyBufferedImage0.getG( color );
				int b = MyBufferedImage0.getB( color );

変数colorの赤成分r、緑成分g、青成分bに分解しています。

MyBufferedImage0.getRメソッド

static int getR( int color )
・RGBを合成した色からR成分(赤の輝度)だけを抽出します。

  パラメータ color  : RGBを合成した色

  戻り値    赤の輝度

MyBufferedImage0.getGメソッド

static int getG( int color )
・RGBを合成した色からG成分(緑の輝度)だけを抽出します。

  パラメータ color  : RGBを合成した色

  戻り値    緑の輝度

MyBufferedImage0.getBメソッド

static int getB( int color )
・RGBを合成した色からB成分(青の輝度)だけを抽出します。

  パラメータ color  : RGBを合成した色

  戻り値    青の輝度
041
042
043
044
				// セピア色に変換
				int new_r =  (int)(  (double)r * 0.393 +  (double)g * 0.769 +  (double)b * 0.189 );
				int new_g =  (int)(  (double)r * 0.349 +  (double)g * 0.686 +  (double)b * 0.168 );
				int new_b =  (int)(  (double)r * 0.272 +  (double)g * 0.534 +  (double)b * 0.131 );

以下の計算式で、( r, g, b )を( new_r, new_g, new_b )に変換しています。

new_r = r * 0.393 + g * 0.769 + b * 0.189

new_g = r * 0.349 + g * 0.686 + b * 0.168

new_b = r * 0.272 + g * 0.534 + b * 0.131

046
047
				// 変換した色を設定
				img.setRGB( x, y, new_r, new_g, new_b );

ピクセル座標( x, y )に、計算した色new_r、new_g、new_bを設定しています。

MyBufferedImage0.setRGBメソッド

boolean setRGB( int x, int y, int color )
・指定した座標の色を設定します。

  パラメータ x  : ピクセルのx座標
        y  : ピクセルのy座標
        color   : 設定するRGBを合成した色

  戻り値    (x,y)が画像の範囲内の場合、true
         (x,y)が画像の範囲外の場合、false
boolean setRGB( int x, int y, int r, int g, int b )
・指定した座標の色を設定します。

  パラメータ x  : ピクセルのx座標
        y  : ピクセルのy座標
        r  : 赤の輝度
        g  : 緑の輝度
        b  : 青の輝度

  戻り値    (x,y)が画像の範囲内の場合、true
         (x,y)が画像の範囲外の場合、false

  詳細         r、g、bは自動で0~255の範囲に変換されます。
051
052
053
054
055
		// JPG画像の保存
		if ( !img.writeJPG( outname ) ) {
			System.out.println( "保存に失敗しました!(" + outname +")" );
			return;
		}

MyBufferedImage0.writeJPGメソッドで、ファイル名outnameでJPEG画像を保存しています。

MyBufferedImage0.writeJPGメソッド

boolean writeJPG( String imgname )
・画像をJPEG形式のファイルで保存します。

  パラメータ imgname  : フルパスのJPEG画像ファイル名

  戻り値    true   : 画像の読み込みに成功
         false  : 画像の読み込みに失敗
057
058
		// 正常に終了
		System.out.println( "正常に終了しました" );

保存に成功したメッセージをprintlnコンソール出力しています。全ての処理が正常終了すると、ここまで処理が実行されます。

関連コンテンツ

画像フォーマット形式・色・大きさ・傾きなどの変更、特定の図形(文字・記号など)を見つけたり、取り出したりする画像処理について詳しく解説。

2015.11.29

一般に使われている画像フォーマットには、いろいろな種類があります。画像フォーマットBMP、JPEG、PNG、GIF、TIFFの特徴を知ってますか?

2015.11.29

このサイトのオリジナルクラスのMyBufferedImage0クラスを利用して、JPEG、BMP、TIFFなどの各種画像ファイルをPNG形式のファイルに保存するプログラムを紹介しています。

2022.11.18

このサイトのオリジナルクラスのMyBufferedImage0クラスを利用して、JPEG、PNG、BMP、TIFFなどの各種画像の横と縦のピクセル数を求めるプログラムを紹介しています。

2022.11.19

画像の一部を切り出して、新しい画像に保存する方法を解説しています。ソースコード付きです。

2023.02.23

条件式を判断して処理を分岐する方法を詳しく説明しています。

2023.03.20

変数やクラスに格納されている値をコンソール出力する方法は?

2020.03.23

メソッドを抜けるときに使用するreturn文について説明しています。

2020.03.20

プログラムの最初に実行されるメソッドは?

2022.12.13

プログラミングで使う変数って何?

2020.03.23

Javaのプログラムを書いてみませんか?プログラムの書き方をくわしく説明しています。

2020.03.23

「Javaソースコード」から実行可能な「オブジェクトコード」に変換する方法をくわしく説明しています。

2020.03.23

BufferedImageクラスを利用して、利便性の高い画像操作クラスを作成しました。興味のある方は、是非ご覧ください。

2022.11.16

PCやスマートフォンのディスプレイに表示されている色、プリンターで印刷される色の仕組みについて解説しています。

2020.03.23

画像って何?

2022.07.25

メソッドの定義方法を詳しく解説しています。Javaのサンプルソースコードを使った説明もあります。

2020.03.23

プログラミング言語とは?種類や特徴について説明しています。

2022.08.03

ファイルは、データを取り扱うとき管理単位の一つで、ハードディスク、SSD,USBメモリ、CD/DVD/ブルーレイなどの記憶媒体に保存するときに使われます。詳しくは、記事をご覧ください。

2022.08.12

Javaプログラムの構成について解説しています。詳しくは、こちらをご覧ください。

2020.03.23

コンピュータに保存されたファイルを特定するための名前がファイル名です。その付け方は?

2016.11.23

オブジェクト指向の考え方を、Javaのソースコードを使って詳しく解説しています。興味のある方は、是非ご覧ください。

2022.09.02

画像の座標系はどのように定義されていますか?

2020.03.23

処理を繰り返すために使用するfor文について解説しています。

2020.03.23

for文などのループ中に、さらにループがある多重ループについて解説しています。

2021.02.09

繰り返し処理の作り方を解説しています。

2016.03.02

広告