Javaで画像を扱う際の方法について、ここでは画像の表示から画像への文字入れなどの方法を紹介する。
目次
Javaの画像の扱い方
Javaの画像を扱うためにImageIOクラスを使う。このクラスには画像をファイルから読み込んだり、指定したファイルに書き込んだりするクラスメソッドが用意されている。この時、画像データは画像ファイルとして保存するために標準画像フォーマットに従ってエンコードやデコードされる。
例えば、デジタルカメラで撮影された画像は、JPEGと呼ばれるフォーマットで保存される。ここでいうフォーマットとは画像をどのように圧縮するかを決める仕様のことである。また、デコードとは、あるフォーマットに変換されたデータを元の画像データに戻すことである。ImageIOクラスのreadメソッドを使えば、画像ファイルから読み込んだデータをデコードしてBufferedImageクラスのオブジェクトとして読み込むことができる。
基本的な書き方はこうだ。
1 |
BufferedImage bufferedImage = ImageIO.read(new File(ファイル名)); |
読み込まれた画像を画面に表示するために、JavaのSwingが使われる。Swingはグラフィカルなユーザ・インタフェースを開発するためのツールである。そのSwingを使えば読み込んだ画像は画面にそのまま表示することができる。
1 2 3 |
public void paint(Graphics graphics) { graphics.drawImage(bufferedImage, 0, 0, null); } |
また、読み込んだ画像データ(BufferedImageクラスのオブジェクト)に線を引いたり、文字を書き込んだりするにはBufferedImageクラスのオブジェクトからGraphics2Dクラスのオブジェクトを作って、Graphics2Dクラスのオブジェクトに線を引いたり文字を書き込んだりする。このようにすると、画像に書き込んだ線や文字が上書きされる仕組みになっている。
1 2 3 4 5 6 |
public void paint(Graphics graphics) { Graphics2D graphics2D = bufferedImage.createGraphics(); graphics2D.drawRect(310, 310, 100, 20); graphics2D.drawString("RED ROSE", 320, 325); graphics.drawImage(bufferedImage, 0, 0, null); } |
エンコードとは、元の画像データを圧縮するために、目的のフォーマットのデータに変換することである。ImageIOクラスのwriteメソッドを使えばBufferedImageクラスのオブジェクトとして作られた画像データをエンコードして書き込むことができる。
基本的な書き方はこうだ。
1 |
ImageIO.write(bufferedImage, フォーマット名, new File(ファイル名)); |
ImageIOクラスのwriteメソッドは、画像を保存するために使用可能な標準画像フォーマットをいくつか選択できる機能を提供している。それぞれ特徴があるので目的にあったフォーマットを選ぶことが出来る。
フォーマット名 |
読み込み |
書き込み |
JPEG |
○ |
○ |
PNG |
○ |
○ |
BMP |
○ |
○ |
WBMP |
○ |
○ |
GIF |
○ |
○ |
では、実際にサンプルプログラムで見てみよう。
画像をファイルから読み込むサンプルプログラム
このサンプルは、画像ファイルを読み込んでそのまま画面に表示している。画面に「Save」ボタンが表示されるが、画像は保存されない。ただ表示するだけである。
このプログラムは、二つのクラスから構成されている。ReadImageUserInterfaceクラスはSwingを使ったユーザ・インタフェースである。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
import java.awt.*; import java.awt.event.*; import javax.swing.*; class ReadImageUserInterface extends JFrame implements ActionListener{//[1] ReadImageComponent component = null;//[2] ReadImageUserInterface () {//[3] setTitle("Java 画像サンプル");//[4] setSize(320,160);//[5] setLayout(new BorderLayout());//[6] Container contentPane = getContentPane();//[7] component = new ReadImageComponent();//[8] contentPane.add(component, BorderLayout.CENTER);//[9] JButton button = new JButton("Save");//[10] button.addActionListener(this);//[11] contentPane.add(button, BorderLayout.SOUTH);//[12] } public void actionPerformed(ActionEvent e){//[20] component.writeImage();//[21] } public static void main(String[] args) {//[30] ReadImageUserInterface readImageUserInterface = new ReadImageUserInterface();//[31] WindowAdapter windowAdapter = new WindowAdapter(){ public void windowClosing(WindowEvent e) { System.exit(0); } };//[32] readImageUserInterface.addWindowListener(windowAdapter);//[33] readImageUserInterface.pack();//[34] readImageUserInterface.setVisible(true);//[35] } } |
もうひとつは、画像を読み込んで表示するReadImageComponentクラスである。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; class ReadImageComponent extends Component {//[100] BufferedImage bufferedImage = null;//[101] ReadImageComponent() {//[102] String imageFilename = "C:\\temp\\pic.jpg";//[103] try {//[104] bufferedImage = ImageIO.read(new File(imageFilename));//[105] } catch (IOException e) {//[106] System.out.println("image file not found. [" + imageFilename + "]");//[107] } } public void paint(Graphics graphics) {//[110] graphics.drawImage(bufferedImage, 0, 0, null);//[111] } public Dimension getPreferredSize() {//[120] int width = 100;//[123] int height = 100;//[134] if (bufferedImage != null) {//[125] width = bufferedImage.getWidth(null);//[126] height = bufferedImage.getHeight(null);//[127] } return new Dimension(width, height);//[128] } void writeImage() {//[130] } } |
実行結果
サンプルプログラムの説明
それでは簡単にプログラムの解説をしていこう。
- [1] ReadImageUserInterfaceクラスを定義する。
- [2] ReadImageComponentクラスの参照変数componentを宣言する。
- [3] コンストラクタを定義する。
- [4]-[6] 表示する画面のタイトル、大きさ、レイアウトの設定を行う。
- [7]-[9] 画像を表示するコンポーネントを追加する。
- [10]-[11] 「Save」ボタンを追加する。
- [20] actionPerformedメソッドを定義する。
- [21] 「Save」ボタンが押された時に、画像を保存するwriteメソッドを呼び出す。
- [30] mainメソッドを定義する。
- [31] ReadImageUserInterfaceクラスのreadImageUserInterfaceオブジェクトを作る。
- [32] クローズボタンが押された時にウインドウを閉じるための処理をwindowAdapterとして定義する。
- [32] readImageUserInterfaceオブジェクトにwindowAdapterを追加する。
- [33]-[34] 画面を表示する。
- [100] Componentクラスを継承してReadImageComponentクラスを定義する。
- [101] BufferedImageクラスの参照変数bufferedImageを宣言し、nullで初期化する。
- [102] コンストラクタを定義する。
- [103]-[107] JPEG画像を読み込んで、その画像を持つbufferedImageオブジェクトを作る。
- [110] paintメソッドを定義する。
- [111] 画像を表示する。
- [120] getPreferredSizeメソッドを定義する。
- [121]-[128] 画像が読み込めれば、画像に合わせたサイズに画面の大きさを設定する。もし画像が読み込めなければ、幅:100、高さ:100のサイズに画面を設定する。
- [130]-[131] 空のwriteImageメソッドを定義する。
画像に線や文字を書き込むサンプルプログラム
このサンプルは、画像ファイルを読み込んだ後、画像に四角で囲んだ「RED ROSE」の文字を表示している。
このプログラムは、二つのクラスから構成されている。ReadImageUserInterfaceクラスはSwingを使ったユーザ・インタフェースである。この部分は、前のセクションとほぼ同じであるが、ReadImageUserInterfaceクラスの中で、componentオブジェクトを作るところをReadImageComponent クラスからPaintImageComponentクラスに書き換えている。
1 2 3 4 5 6 7 8 9 |
…. class ReadImageUserInterface extends JFrame implements ActionListener{//[1] ReadImageComponent component = null;//[2] ReadImageUserInterface () {//[3] …. component = new PaintImageComponent();//[8] ….. } } |
もうひとつのクラスは、画像を読み込んで表示するPaintImageComponentクラスである。このクラスは、ReadImageComponent クラスを継承していている。
このため画像を表示するpaintメソッド以外の処理はReadImageComponent クラスと同じである。ただし、paintメソッドをオーバーライドして書き換えているので、画像に四角で囲んだ「RED ROSE」の文字が表示される。
1 2 3 4 5 6 7 8 9 10 11 12 |
import java.awt.*; class PaintImageComponent extends ReadImageComponent {//[200] public void paint(Graphics graphics) {//[201] Graphics2D graphics2D = bufferedImage.createGraphics();//[202] graphics2D.setColor(Color.YELLOW);//[203] BasicStroke wideStroke = new BasicStroke(4.0f);//[204] graphics2D.setStroke(wideStroke);//[205] graphics2D.drawRect(310, 310, 100, 20);//[206] graphics2D.drawString("RED ROSE", 320, 325);//[207] graphics.drawImage(bufferedImage, 0, 0, null);//[208] } } |
実行結果
サンプルプログラムの説明
それでは簡単にプログラムの解説をしていこう。
- [7]-[9] 四角と文字を表示するコンポーネントを追加する。
- [200] ReadImageComponentクラスを継承してPaintImageComponentクラスを定義する。
- [201] paintメソッドを定義する。
- [202] bufferedImageからGraphics2D クラスのオブジェクトgraphics2Dを作る。
- [203]-[206] 四角を表示する。
- [207] 「RED ROSE」を四角の中に表する。
- [208] 画像を表示する。
画像をファイルに書き込むサンプルプログラム
このサンプルは、四角で囲んだ「RED ROSE」の文字を画像に書き込んだ後「Save」ボタンが押されると画像を保存する。実際には「Save」ボタンが押されるとReadImageUserInterfaceクラスのactionPerformedメソッドが呼び出され、このメソッドの中から、さらにWriteImageComponentクラスのwriteImageメソッドが呼び出される流れになっている。
このプログラムは、二つのクラスから構成されている。ReadImageUserInterfaceクラスはSwingを使ったユーザ・インタフェースである。この部分は、前のセクションとほぼ同じであるが、ReadImageUserInterfaceクラスの中で、componentオブジェクトを作るところをPaintImageComponentクラスからWriteImageComponentクラスに書き換える。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
…. class ReadImageUserInterface extends JFrame implements ActionListener{//[1] ReadImageComponent component = null;//[2] ReadImageUserInterface () {//[3] …. component = new WriteImageComponent ();//[8] ….. } ….. public void actionPerformed(ActionEvent e){//[20] component.writeImage();//[21] } ….. } |
もうひとつは、画像を書き込むWriteImageComponentクラスである。このクラスは、PaintImageComponentクラスを継承していている。
このため画像を保存するwriteImageメソッド以外の処理はPaintImageComponentクラスと同じである。ただし、writeImageメソッドは空のメソッドがオーバーライドされて画像を保存できるように書き換えられている。
1 2 3 4 5 6 7 8 9 10 11 12 |
import javax.imageio.ImageIO; import java.io.File; class WriteImageComponent extends PaintImageComponent {//[300] void writeImage() {//[301] String imageFilename = "C:\\temp\\flower.png";//[302] try {//[303] ImageIO.write(bufferedImage, "png", new File(imageFilename));//[304] } catch (Exception e) {//[305] System.out.println("image file write error. [" + imageFilename + "]");//[306] } } } |
実行結果
サンプルプログラムの説明
それでは簡単にプログラムの解説をしていこう。
- [7]-[9] 画像を保存するコンポーネントを追加する。
- [20] actionPerformedメソッドを定義する。
- [21] 「Save」ボタンが押された時に、画像を保存するwriteメソッドを呼び出す。
- [300] PaintImageComponentクラスを継承してWriteImageComponentクラスを定義する。
- [301] writeImageメソッドを定義する。
- [302] 文字列クラスの参照変数を宣言し、初期値としてファイル名を代入する。
- [303]-[306] 指定されたファイルに指定されたフォーマットで画像を書き込む。
まとめ
このページではJavaで画像を扱う方法について簡単にご紹介した。
今回、紹介したサンプルプログラムで勉強していただきたい。
Javaの画像の取扱いについて参考にしていただければと思う。