2011年9月8日木曜日

画像ファイルから読み込む方法

画像ファイルからImageを取得するには、ImageIO#read()を使用する。
内部で画像ファイルの種類を自動的に判断して読んでくれるらしい。
なお、画像として不正なファイル(対応していない種類の画像)だったときは例外は発生せず、nullが返る。

対応状況

種類

JDK1.4

JDK1.5

ビットマップ

bmp

×

 

png

jpeg

jpg

GIF

gif

 

パターン

コーディング例

File

import java.awt.Image;
import javax.imageio.ImageIO;
        public static Image loadImage(File f) {
               try {
                       BufferedImage img = ImageIO.read
(f);
                       return img;
               } catch (IOException e) {
                       throw new RuntimeException(e);
               }
        }

InputStream

        public static Image loadImage(String fileName) {
               InputStream is = null;
               try {
                       is = new FileInputStream(fileName);
                       BufferedImage img = ImageIO.read(is);
                       return img;
               } catch (IOException e) {
                       throw new RuntimeException(e);
               } finally {
                       if (is != null) try { is.close(); } catch (IOException e) {}
               }
        }

URL

        public static Image loadImage(String url) {
               try {
                       URL u = new URL(url);
                       BufferedImage img = ImageIO.read(u);
                       return img;
               } catch (IOException e) {
                       throw new RuntimeException(e);
               }
        }

他に、ToolKitを使う方法もあるようだ。[2010-01-08]

import java.awt.Toolkit;
               Image img = Toolkit.getDefaultToolkit().createImage(name);
               return img;

nameの型はString・URL・byte[]等。
また、ToolKit#getImage()というメソッドもある。こちらは画像インスタンスがバッファリングされる(同一の画像であれば同じインスタンスを返す)らしい。

新しい画像を作る方法

任意のサイズの新しい画像を作るには、BufferedImageを使用する。

import java.awt.Image;
import java.awt.image.BufferedImage;
        public static Image createImage(int width, int height) {
               return new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        }

TYPE_*_RGBを指定すると、Graphics#drawImage()を使った際にそのままGraphicsに描画される。[2007-02-26]
TYPE_*_ARGB(アルファ付き)を指定すると、RGB値が0のドットは透明色として扱われ、その部分は元のGraphicsの色が残る。

JDK1.5からはBufferedImagegetTransparency()というメソッドが追加された。
これが返す値により、透明色が扱えるかどうか判断できる。
返る値はOPAQUE(完全に不透明)、TRANSLUCENT(透明が使える)等。(この定数はTransparencyで定義されているが、Colorにも継承されている)
 

表示されている画面を取得する方法

現在 画面に表示されている内容を、そのまま取得(キャプチャー)することが出来る。
WindowsのPrint Screenキーに相当。

import java.awt.Rectangle;
import java.awt.Robot;
        public static Image captureScreen(int x, int y, int w, int h) throws AWTException {
               Robot robot = new Robot();
               Image img = robot.createScreenCapture(new Rectangle(x, y, w, h));
               return img;
        }

なお、画面サイズはToolkit#getScreenSize()で取得できる。

import java.awt.Dimension;
import java.awt.Toolkit;
        public static Image captureScreen() {
               Dimension sz = Toolkit.getDefaultToolkit().getScreenSize();
 
               try {
                       Robot robot = new Robot();
                       Image img = robot.createScreenCapture(new Rectangle(0, 0, sz.width, sz.height));
                       return img;
               } catch (AWTException e) {
                       throw new RuntimeException(e);
               }
        }

画像を加工する方法

Imageを加工するには、Graphicsを取得し、それに対して描画してやればよい。

黒で埋める例:

import java.awt.Graphics;
        public static void fill(Image img) {
               int w = img.getWidth(null);    //Imageの幅
               int h = img.getHeight(null);   //Imageの高さ
 
               Graphics g = img.getGraphics();
               g.setColor(Color.BLACK);              //黒
               g.fillRect(0, 0, w, h);
               g.dispose();
        }

BufferedImageの場合は、setRGB()で直接RGBコードを指定できる。
BufferedImageにアルファが指定されている場合、RGB値が0だと透明なドットとして扱われる。

指定された色を透明色に変更する例:

        public static void changeTransparent(BufferedImage img, Color c) {
               int w = img.getWidth();        //BufferedImageの幅
               int h = img.getHeight();       //BufferedImageの高さ
               int t = c.getRGB();    //透明色に変換する色のRGB値
 
               //RGB値を0(透明色)に置換
               for (int y = 0; y < h; y++) {
                       for (int x = 0; x < w; x++) {
                               if (img.getRGB(x, y) == t) img.setRGB(x, y, 0);
                       }
               }
        }

ImageをBufferedImageに変換する方法

BufferedImageのコンストラクターにImageをとるものがあればいいんだけど、そういうのは無いようだ(苦笑) [2010-01-08]

一番単純なのは、Graphicsを経由してコピー(描画)してやる方法。

(この方法だと、アルファ(透明色)とかの設定は引き継げないが)

           public static BufferedImage createBufferedImage(Image img) {

                      BufferedImage bimg = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB);

 

                      Graphics g = bimg.getGraphics();

                      g.drawImage(img, 0, 0, null);

                      g.dispose();

 

                      return bimg;

           }

BufferedImageの一部分から新しいBufferedImageを作りたい場合は、専用のメソッドがある。

               BufferedImage simg = bimg.getSubimage(x, y, w, h);

画像をダイアログで表示する

どんな画像なのかを確認したい場合、アプレットならGraphicsが取得できるのでそこにImageを描画(コピー)すればよいが、Graphicsを持たないアプリケーションでもダイアログを使って表示してみることが出来る。

メッセージ表示ダイアログではアイコンを自分で指定できるので、Imageからアイコンを作ってそれを表示してやる。

           public static void showImageDialog(Image img) {

                      Icon icon = new ImageIcon(img);

 

                      JOptionPane.showMessageDialog(null,

                                  "←イメージ",                //メッセージ

                                  "イメージ確認",             //タイトル

                                  JOptionPane.PLAIN_MESSAGE,

                                  icon                            //画像のアイコン

                      );

           }

※(JDK1.4までは)ウィンドウアプリ以外からダイアログを使う場合のお約束として、main()の最後でSystem.exit()が必要。

 

画像をファイルに保存する例

BufferedImageは簡単にファイルに保存することが出来る。[2007-12-29]

ImageIO#write()でRenderedImageをファイル(File)やストリーム(OutputStream)に出力する。

RenderedImageはインターフェースで、BufferedImageはそれをimplementsしている。(Imageはダメ)

           public static void save(BufferedImage img, File f) throws IOException {

                      if (!ImageIO.write(img, "PNG", f)) {

                                  throw new IOException("フォーマットが対象外");

                      }

           }

           /**

            * BufferedImageをバイト配列に変換する例. [2010-01-08]

            * @param img イメージ

            * @return バイト配列

            * @throws IOException 変換できなかった場合

            */

           public static byte[] getBytes(BufferedImage img) throws IOException {

                      ByteArrayOutputStream bos = new ByteArrayOutputStream();

                      if (!ImageIO.write(img, "PNG", bos)) {

                                  throw new IOException("フォーマットが対象外");

                      }

                      return bos.toByteArray();

           }

2引数は画像の形式(フォーマット)を文字列で指定する。

どんなフォーマット文字列がサポートされているかは 以下のようにして確認できる。

                      String[] fs = ImageIO.getWriterFormatNames();

                      System.out.println(Arrays.toString(fs));

JDK1.6の場合:

[BMP, bmp, jpg, JPG, wbmp, jpeg, png, PNG, JPEG, WBMP, GIF, gif]

 

0 件のコメント:

コメントを投稿