Javaコラム Javaエンジニアのためのお役立ちコラム

Javaの画像処理を基礎から解説!

2020年10月26日
SE
Javaの画像処理とはどのような処理のことでしょうか。
PM
Javaでグラフィックを描画すること全てが該当します。

Javaの画像処理とは?


Javaの画像処理と言えば、Javaでグラフィックを描画すること全てが該当します。今回は画像ファイルを読み込んで何かの処理を行って保存する、という一連の動作を画像処理として扱いましょう。

Javaの画像処理はImageIOクラスを利用します。そして読み込んだ画像はBufferedImageクラスのデータとして扱います。まずはとても簡単な、画像ファイルを読み込んで保存するだけの処理を行ってみましょう。

画像ファイルを読み込んで保存するサンプル

以下はpng形式の画像ファイルを開いて、jpg形式で保存するJavaサンプルです。実行して試してみてください。

import java.io.*;
import java.awt.image.*;
import javax.imageio.*;

public class MainClass {
public static void main(String[] args) {
try {
BufferedImage bi = ImageIO.read(new File(“”c:\\test\\test.png””));
ImageIO.write(bi, “”jpg””, new File(“”c:\\test\\test.jpg””));
}
catch (Exception e) {
e.printStackTrace();
}
}
}

画像処理のサンプル

次はもう少し凝った画像処理をしてみましょう。以下のJavaサンプルをご覧ください。

import java.io.*;
import java.awt.image.*;
import javax.imageio.*;

public class MainClass {
public static void main(String[] args) {
try {
BufferedImage readBuf=ImageIO.read(new File(“”c:\\test\\test.jpg””));
int w = readBuf.getWidth();
int h = readBuf.getHeight();
BufferedImage writeBuf =
new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);

for(int y=0;y < h;y++){
for(int x=0;x < w;x++){
int c = readBuf.getRGB(x, y);
c &= 0xff0000ff;
writeBuf.setRGB(x,y,c);
}
}

ImageIO.write(writeBuf, “”jpg””, new File(“”c:\\test\\test2.jpg””));
}
catch (Exception e) {
e.printStackTrace();
}
}
}

画像処理の基礎

このサンプルを実行すると、test.jpgを画像処理してtest2.jpgに保存します。test2.jpgはtest.jpgを真っ青にしたような画像になっているはずです。これはtest.jpgから青の要素だけ取り出してtest2.jpgに保存したからです。

Javaサンプルのプログラムについて解説する前に、まず画像処理の基礎を簡単に説明します。画像ファイルはピクセル(ドット)の集まりで出来ています。画像ファイルを画像ビューワで拡大すると、画像が縦横のマス目で構成されていることがわかります。そのマス目がピクセルです。

ピクセルにはRGBの値が入っている

色というものは赤・緑・青の三原色から成り立ちます。コンピューターではそれをRGB(Red・Green・Blue)とセットで表します。そして画像ファイルの各ピクセルにはRGBの値が入っているのです。例えばRGBのRが最高値でGとBが0なら、ピクセルは真っ赤になるということです。

つまり画像ファイルはRGB値のピクセルの集合体ということです。それを踏まえた上で、Javaの画像処理サンプルの解説に入ります。

TYPE_INT_RGBで書き込み用バッファを生成する

今回のJavaの画像処理サンプルではまずBufferedImageに画像を読み込んだ後、getWidth()とgetHeight()でサイズを取得しています。これが横と縦のピクセル数ということです。そしてその縦横サイズで書き込み用のwriteBufを作成しています。

その時にTYPE_INT_RGBを指定していますが、これはRGBそれぞれが8ビットの値を持つピクセルのBufferedImageを作成するという意味です。8ビットとは、10進数で0から255、16進数で0x00~0xffの値を持つサイズの単位です。

1つのピクセルは3つの8ビットの値から構成されている

サンプルソースの、「int c = readBuf.getRGB(x, y);」の次に以下を追加して実行してみてください。

if (y==h/2 && x==w/2) System.out.println(Integer.toHexString(c));

これは画像の中心辺りの場所のピクセルの値を表示します。画像ファイルの内容にもよりますが、以下のように表示されるはずです。

ff927f3d

これは16進数で、

未使用 = 0xff
R = 0x92
G = 0x7f
B = 0x3d

と言う意味です。このように1つのピクセルは8ビットサイズの3つのRGB値から構成されているのです。なお未使用の部分にはARGBの場合はAlpha値という透明度が入ります。

ピクセルの値にビット演算を行う

Javaの画像処理サンプルの解説に戻りましょう。writeBufを生成した後は、画像ファイルのサイズの分だけ、2重のforループ処理を行って各ピクセルの読み込みと書き込み処理を行います。readBuf.getRGB(x, y)で変数cにピクセルのRGB値を読み込んで、

c &= 0xff0000ff;

と言う処理を行っています。これはビット演算です。先ほどのケースで1つのピクセルは8桁の16進数で表せると分かりましたが、このビット演算で未使用値とBlueだけを残して、RedとGreenは00にしてしまいます。

ビット演算でBだけを残す

ビット演算の箇所は、以下のようにJavaの2進数表記で置き換えることもできます。

c &= 0b1111_1111_0000_0000_0000_0000_1111_1111;

0と1だけの2進数の場合は32桁になりますが、&=の場合その各桁で乗算を行います。その結果、0の桁が消えて1の桁が残ります。ビット演算についてはここではこれ以上詳しくは説明しないので、他を調べてみてください。

画像を明るくするサンプル

変数cにビット演算を行った後は、setRGB(x,y,c)でwriteBufに書き込みます。これを全ピクセル行います。最後にImageIO.writeでwriteBufをファイルに書き込んで終了です。このようにビット演算さえ理解すればJavaの画像処理はそれほど難しくはありません。

では次に青だけを残しているc &= 0xff0000ff;の箇所を、以下のように変えてみましょう。

int r = (c & 0x00ff0000) >> 16;
int g = (c & 0x0000ff00) >> 8;
int b = c & 0x000000ff;
final int add = 0x40;
r += add;
if (r > 0xff) r = 0xff;
g += add;
if (g > 0xff) g = 0xff;
b += add;
if (b > 0xff) b = 0xff;
c = 0xff000000 | (r << 16) | (g << 8) | b;

画像処理のプログラムにはビット演算の知識は必須

これを実行するとtest2.jpgはtest.jpgより明るくなります。RGBそれぞれに0x40を加算して色を底上げしているというわけです。RGBは全てが0xffになると白になるので、白っぽくなったとも言えます。

行っていることは、まずRを&で取得して右に16ビットシフト、Gを&で取得して右に8ビットシフト、Bを&で取得します。それぞれに0x40を加算、ただし0xffは越えないようにします。そして未使用の0xff000000・Rを左16ビットシフト・Gを左8シフト・Bを、それぞれ|(OR)で加算して新しいピクセルの値とする、です。

ビット演算が分からない人は、ビット演算のやり方を調べてからもう一度見直してください。理解できるようになるでしょう。

SE
Javaの画像処理は難しいイメージでしたが、やり方さえ分かれば簡単にできるのですね。
PM
ビット演算さえ理解できれば、初心者でも難しくない作業です。

Javaの画像処理は難しくない!

Javaの画像処理について解説しましたが、ご理解頂けましたでしょうか。ビット演算の知識が必要になりますが、それをマスターすれば後は自在に画像処理ができるようになるでしょう。


Javaでのキャリアアップをお考えの方は、現在募集中の求人情報をご覧ください。

また、直接のエントリーも受け付けております。

エントリー(応募フォーム)