ゆるゆるプログラミング

・テーブルによる色変換

色変換テーブルは、RGBそれぞれの色成分(0~255の整数)を入力したときの出力値を設定したテーブルのことです。下の図は、入力値RGBを出力値R'G'B'に変換するイメージです。

テーブルによる色変換テーブルによる色変換

具体的には、テーブルとしてRGB各成分ごとに定義したint型配列をテーブルを使います。

    int[] colorconv_r = new int[ 256 ];
    int[] colorconv_g = new int[ 256 ];
    int[] colorconv_b = new int[ 256 ];

配列添え字が入力値で、配列の値が出力値です。配列の値は、0~255の範囲に収まるように設定しておきます。以下のソースは、入力値rとgとbのそれぞれの色成分を出力値に変換している例です。

    r = colorconv_r[ r ];
    g = colorconv_g[ g ];
    b = colorconv_b[ b ];

配列に設定するだけで、簡単に色変換できることが分かります。ただし、RGBを組み合わせて色を計算するグレースケール変換や2値化、セピア色への変換等にはこの方法は使用できません。

これから紹介するJavaソースコードには、テーブルを利用した色変換の例をいくつか含んでいます。それらの色変換は、引数で渡すモードによって変えられるようにしています。参考にしてください。

ColorConversion.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 ColorConversion {
007:    	// modeによるカラーテーブルの設定
008:    	static void setTable( int[] colorconv_r, int[] colorconv_g, int[] colorconv_b,
009:    									 int mode )
010:    	{
011:    		int    i, col;
012:    		double rad;
013:    
014:    		switch ( mode ) {
015:    			case 0:
016:    				// 色反転
017:    				for ( i = 0; i < 256; ++ i ) {
018:    					colorconv_r[ i ] = 255 - i;
019:    					colorconv_g[ i ] = 255 - i;
020:    					colorconv_b[ i ] = 255 - i;
021:    				}
022:    				break;
023:    
024:    			case 1:
025:    				// 輝度を半分
026:    				for ( i = 0; i < 256; ++ i ) {
027:    					colorconv_r[ i ] = i / 2;
028:    					colorconv_g[ i ] = i / 2;
029:    					colorconv_b[ i ] = i / 2;
030:    				}
031:    				break;
032:    
033:    			case 2:
034:    				// 量子化
035:    				for ( i = 0; i < 256; ++ i ) {
036:    					colorconv_r[ i ] = ( i / 64 ) * 64;
037:    					colorconv_g[ i ] = ( i / 64 ) * 64;
038:    					colorconv_b[ i ] = ( i / 64 ) * 64;
039:    				}
040:    				break;
041:    
042:    			case 3:
043:    				// サインカーブ
044:    				for ( i = 0; i < 256; ++ i ) {
045:    					rad = Math.toRadians( (double)i / 256.0 * 720.0 );
046:    					col = (int)( Math.sin( rad ) * 127.0 + 127.0 );
047:    					colorconv_r[ i ] = col;
048:    					colorconv_g[ i ] = col;
049:    					colorconv_b[ i ] = col;
050:    				}
051:    				break;
052:    
053:    			case 4:
054:    				// 白っぽくする
055:    				for ( i = 0; i < 256; ++ i ) {
056:    					colorconv_r[ i ] = i + 100;
057:    					if ( 255 < colorconv_r[ i ] ) colorconv_r[ i ] = 255;
058:    					colorconv_g[ i ] = i + 100;
059:    					if ( 255 < colorconv_g[ i ] ) colorconv_g[ i ] = 255;
060:    					colorconv_b[ i ] = i + 100;
061:    					if ( 255 < colorconv_b[ i ] ) colorconv_b[ i ] = 255;
062:    				}
063:    				break;
064:    
065:    
066:    			case 5:
067:    				// 赤成分だけの残す
068:    				for ( i = 0; i < 256; ++ i ) {
069:    					colorconv_r[ i ] = i;
070:    					colorconv_g[ i ] = 0;
071:    					colorconv_b[ i ] = 0;
072:    				}
073:    				break;
074:    
075:    
076:    			case 6:
077:    				// 緑成分だけの残す
078:    				for ( i = 0; i < 256; ++ i ) {
079:    					colorconv_r[ i ] = 0;
080:    					colorconv_g[ i ] = i;
081:    					colorconv_b[ i ] = 0;
082:    				}
083:    				break;
084:    
085:    
086:    			case 7:
087:    				// 青成分だけの残す
088:    				for ( i = 0; i < 256; ++ i ) {
089:    					colorconv_r[ i ] = 0;
090:    					colorconv_g[ i ] = 0;
091:    					colorconv_b[ i ] = i;
092:    				}
093:    				break;
094:    
095:    			default:
096:    				// 入力値と出力値を同じにする
097:    				for ( i = 0; i < 256; ++ i ) {
098:    					colorconv_r[ i ] = i;
099:    					colorconv_g[ i ] = i;
100:    					colorconv_b[ i ] = i;
101:    				}
102:    				break;
103:    		} 
104:    	}
105:    
106:    
107:    	public static void main( String[] args ) {
108:    		// 結果格納フラグ
109:    		boolean result;
110:    		// 色変換モード
111:    		int mode;
112:    		// ファイル名
113:    		String inname, outname;
114:    		// 画像格納クラス
115:    		BufferedImage img = null;
116:    
117:    		// 入力した引数が3つ以上かを調べる
118:    		if ( 3 > args.length ) {
119:    			// 入力した引数が3つ未満の場合、使用方法を表示する
120:    			System.out.println( "ColorConversion [入力JPG][出力JPG][モード]" );
121:    			return;
122:    		}
123:    
124:    		// 入力JPEG名をinnameに代入(拡張子".jpg"省略なし)
125:    		inname  = args[ 0 ];
126:    		// 出力JPEG名をoutnameに代入(拡張子".jpg"省略なし)
127:    		outname = args[ 1 ];
128:    
129:    		// モードをmodeに代入
130:    		try {
131:    			// 引数を変換し、モードに代入
132:    			mode = Integer.valueOf( args[ 2 ] );
133:    		}
134:    		catch( NumberFormatException ne )
135:    		{
136:    			System.out.println( "引数が不正です" );
137:    			return;
138:    		}
139:    
140:    		// JPEGの読み込み
141:    		try {
142:    			// inname(入力JPEG)を読み込んでimgにセット
143:    			img = ImageIO.read( new File( inname ) );
144:    		} catch (Exception e) {
145:    			// inname(入力JPEG)の読み込みに失敗したときの処理
146:    			 e.printStackTrace();
147:    			return;
148:    		}
149:    
150:    
151:    		// 画像の色の持ち方をチェック
152:    		if ( BufferedImage.TYPE_3BYTE_BGR != img.getType() )
153:    		{
154:    			System.out.println( "対応していないカラーモデルです!("
155:    									 + inname +")" );
156:    			return;
157:    		}
158:    
159:    		// 色変換
160:    		int x, y;
161:    		int width, height;
162:    		int color, r, g, b;
163:    		int p;
164:    		int newcolor;
165:    
166:    		// 色変換テーブル
167:    		int[] colorconv_r = new int[ 256 ];
168:    		int[] colorconv_g = new int[ 256 ];
169:    		int[] colorconv_b = new int[ 256 ];
170:    
171:    
172:    		// 色変換テーブル設定
173:    		setTable( colorconv_r, colorconv_g, colorconv_b, mode );
174:    
175:    		// 画像サイズの取得
176:    		width = img.getWidth();
177:    		height= img.getHeight();
178:    
179:    		for ( y = 0; y < height; ++ y ) {
180:    			for ( x = 0; x < width; ++ x ) {
181:    				// (x,y)の色を取得
182:    				color = img.getRGB( x, y );
183:    
184:    				// 色をr,g,bに分解
185:    				r = ( color >> 16 ) & 0xff;
186:    				g = ( color >> 8 ) & 0xff;
187:    				b = color & 0xff;
188:    
189:    				// r,g,bの色をテーブルで変換
190:    				r = colorconv_r[ r ];
191:    				g = colorconv_g[ g ];
192:    				b = colorconv_b[ b ];
193:    
194:    				// r,g,bの色を合成
195:    				newcolor = ( r << 16 ) + ( g << 8 ) + b;
196:    
197:    				// 合成した色を(x,y)に設定
198:    				img.setRGB( x, y, newcolor );
199:    			}
200:    		}
201:    
202:    		try {
203:    			// imgをoutname(出力JPEG)に保存
204:    			result = ImageIO.write( img, "jpeg", new File( outname ) );
205:    		} catch ( Exception e ) {
206:    			// outname(出力JPEG)の保存に失敗したときの処理
207:    			e.printStackTrace();
208:    			return;
209:    		}
210:    
211:    		// 正常に終了
212:    		System.out.println( "正常に終了しました" );
213:    	}
214:    }

ColorConversionを実行

>java ColorConversion sampleimage005_300x200.jpg colorconversion_0001.jpg 1

1つ目の引数で元のJPEGファイル名、2つ目の引数に作成するJPEG画像ファイル名、3つ目に色変換モードを指定します。

実行結果

・元の画像(sampleimage005_300x200.jpg)

元画像

・モード=0で作成した画像(colorconversion_0000.jpg)

色を反転(ネガ)

・モード=1で作成した画像(colorconversion_0001.jpg)

少し暗くする(輝度を半分)

・モード=2で作成した画像(colorconversion_0002.jpg)

減色(64で量子化)

・モード=3で作成した画像(colorconversion_0003.jpg)

サインカーブ

・モード=4で作成した画像(colorconversion_0004.jpg)

白っぽくする(RGBに100を足す)

・モード=5で作成した画像(colorconversion_0005.jpg)

赤成分だけ残す

・モード=6で作成した画像(colorconversion_0006.jpg)

緑成分だけ残す

・モード=7で作成した画像(colorconversion_0007.jpg)

青成分だけ残す

モードによっていろいろな処理の画像が作成されることが分かります。

■関連コンテンツ

テーブルによる色変換 その2 テーブルによる色の変換方法を解説(その2)
テーブルによる色変換 その3 テーブルによる色の変換方法を解説(その3)
光と色の3原色 光と色の3原色の考え方を解説

■新着情報

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

■広告

法人向けのETC専用カード

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

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

Topへ