![]()
![]() JPEG画像処理 ( 19990201 ) JDK2になってJPEG関係のAPIがなくなったと思っている人が多いが、実は正規のAPI文書の他に同じ文書ディレクトリの下、\guide\2d\api-jpegの中にちゃんと説明文書がある。 このJPEG関係のAPIはJDK2の前身であるJDK1.2 beta3でいきなり登場して「おおっ!」と思わせておきながら、次のbeta4で消えてなくなってしまった。で、JDK1.2の正規リリースでふたを開けてみれば、オマケAPIとしてちゃんと復活していたのだ。 パッケージは「com.sun.image.codec.jpeg.*」で、これをimportしておけば、JPEG画像の読込み・書出し処理をJavaでタダでできてしまう。こんなお得なことはない。 たとえばフルパス名を指定してJPEG画像を読み込むには、次のようにプログラムを書けばいい。 これでJPEGImageDecoder型の変数decoderにJPEG画像のデータが保持される。 もちろん単にJPEG画像をJavaで作成したウィンドウに表示するだけなら、これらJPEG画像のAPIを使わなくてもいい。次のようにすればいいだけ。 まずImageIcon型の変数を作る。このときJPEG画像のフルパス名をわたすだけでいい。この例ではJLabelのsetIcon()メソッドを使ってJPEG画像を表示させている。setIcon()メソッドにはIconオブジェクトをわたすことになっているが、ImageIconオブジェクトはIconのサブクラスなので、型キャストなしでそのまま引数としてわたせる。 JLabelよりもiconの画像の方が大きい場合は、一部分だけが表示される。ちゃんと大きさを合わせたいなら、ImageIconの中に隠れているImageオブジェクトをgetImage()で取り出し、このImageオブジェクトのgetScaledInstance()で、大きさを変更された(scaled)Imageオブジェクトを作り出す。これを元のImageIconへsetImage()でもどしてやれば、縮小画像が表示される。 この例では、あまり意味がないけど、元の画像を40×40ドットの大きさに縮小してからもとのImageIconへもどしている。拡大・縮小するときの計算方法として、Image.SCALE_SMOOTHの他にもいろいろあるので試してみるといい。たぶんSCALE_SMOOTHがいちばん「なめらか」だと思う。 単に画面表示のために拡大・縮小をするならこれで十分だが、拡大・縮小した画像をJPEGファイルとして保存したいとなると、いよいよJPEG関係のAPIを使う必要が出てくる。 そのためには、JPEGImageDecoder型の変数に読み込んだJPEG画像を、Imageオブジェクトに変換しなきゃいけない。都合のいいことに、JPEGImageDecoderにはdecodeAsBufferedImage()というメソッドがあり、画像をBufferedImageのかたちで取り出せる。 名前からわかるようにこのBufferedImageはImageのサブクラスだ。つまり直接getScaledInstance()メソッドを呼び出して、拡大・縮小したImageを一発で取り出せる。 ところが、都合の悪いことに、getScaledInstance()で取り出したImageオブジェクトをBufferedImageにキャストするとエラーになってしまう。仕方ないので、ちょっと回り道をしよう。BufferedImageからGraphicsを取り出して、このGraphicsの上に、拡大・縮小したImageを描く。 まず、拡大・縮小後のJPEG画像を保存するBufferedImage型の変数を用意しておこう。ここでは拡大・縮小前のBufferedImageをbi、拡大・縮小後のBufferedImageをaiという名前にする。 4行目で拡大・縮小後のBufferedImageを作っている。次の行で、そこからGraphicsオブジェクトを取り出している。Graphicsオブジェクトは、Win32プログラミングで言えばデバイスコンテキストみたいなもので、実際に画像を描くための「画用紙」と考えてもらえばいい。 その次の行で「画用紙」にImageを描いている。これで変数aiの中身は、拡大・縮小後のJPEG画像になっているわけだ。 読み込んだときと同じように、まずファイル入出力関係のオブジェクトを生成する。今度は書き込みなのでFileOutputStreamだ。次にJPEGCodecというオブジェクトのstaticメソッドを呼び出してJPEGエンコーダーを一つ作る。JPEGCodecというオブジェクトはJPEGエンコーダーとJPEGデコーダーを作る「工場」みたいなもんだ。 最後に、JPEGエンコーダーのencode()メソッドに、拡大・縮小後のBufferedImageをわたしてやると、あとは勝手にJPEGファイルが出来あがる。あっけないほどかんたんでしょ? FileInputStream fin = new FileInputStream(new File("C:\images\test.jpeg"));
JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(fin);
ImageIcon icon = new ImageIcon("C:\images\test.jpeg");
JLabel imageLabel = new JLabel();
imageLabel.setIcon(icon);
ImageIcon icon = new ImageIcon("C:\images\test.jpeg");
Image image = icon.getImage();
image = image.getScaledImage(40, 40, Image.SCALE_SMOOTH);
icon.setImage(image);
JLabel imageLabel = new JLabel();
imageLabel.setIcon(icon);
FileInputStream fin = new FileInputStream(new File("C:\images\test.jpeg"));
JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(fin);
BufferedImage bi = decoder.decodeAsBufferedImage();
BufferedImage ai = new BufferedImage();
Graphics aig = ai.getGraphics();
aig.drawImage(bi.setScaledInstance(40, 40, Image.SCALE_SMOOTH), 0, 0, null);
さて、今度はこの拡大・縮小後のaiをファイルとして保存しよう。読み込むときがJPEGデコーダーだったから、書き込むときはJPEGエンコーダーを使う。 FileInputStream fin = new FileInputStream(new File("C:\images\test.jpeg"));
JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(fin);
BufferedImage bi = decoder.decodeAsBufferedImage();
BufferedImage ai = new BufferedImage();
Graphics aig = ai.getGraphics();
aig.drawImage(bi.setScaledInstance(40, 40, Image.SCALE_SMOOTH), 0, 0, null);
FileOutputStream fout = new FileOutputStream(new File("C:\images\aftertest.jpeg"));
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(fout);
encoder.encode(ai);
無断転載禁止
![]()
|