第32夜 Java SEのあたりをつける 画像編
昨日かいたとおり、JavaSEのあたりをつけるためのエントリを描いていく。
細かい解説はしないので、詳しくはJavadocを見ながらいろいろといじってもらいたい。あくまでも索引のようなエントリということで。
特別なぞるわけではないが、このへんを参考に。
「Javaが使えます」という人の基準
画像を扱う
画像を扱う基本となるクラスは名前ですぐ気がつくと思うが、Imageクラスだ。java.awtパッケージにある。画像のサイズを保持していたり、画像に対して実際に描画するグラフィックスコンテキスト(後述)を作成したりする。
ただし、このクラスは抽象クラスである。
実態は別にある。
特に一般的にユーザーが扱うImageを継承したクラスは2つ。
BufferedImageとVolatileImageである。これらはパッケージは変わってjava.awt.imageである。
BufferedImage
いわゆる普通のビットマップを扱うクラスである。画像をピクセル単位で扱う一般的なもの。Win32であればCreateDIBSectionとかそんなかんじのもの。データがメモリにあるため、オフスクリーンでレンダリングしたり、PngやJPEGといったファイルの読み書きに利用したりするものである。業務アプリケーションでは一般的に使われるのがこいつだ。
普通にnewで生成するので非常に扱いやすい。
VolatileImage
一方、こいつはVolatile、つまり揮発性のメモリに格納される。具体的に言えばVRAMなど、直接メモリに対してCPUがやり取りが不可能な場合のものをさす。そのかわりハードウェアアクセラレーションがきくのをわりと期待している。ピクセルフォーマットがOSの設定等に左右される可能性があるというもの。いわゆるデバイス依存ビットマップである。扱いにくいが、早いものと覚えておけばよい。
JDKのバージョンがあがるたびにBufferedImageの描画が早くなってきており活躍の場は減っている。ハードウェアを意識的に使うならばOpenGLなどを積極的に利用したほうがいい体。ただし、高レベルな描画が扱えるという点でメリットはある。2Dゲーならこれで十分な場合も多い。
デバイス依存ということからわかるようにnewで生成するのではなく、VolatileImageを生成してくれる各種クラスから間接的に取得する。感覚的にはJava1.2までののImageと同じである。
グラフィックスコンテキスト
Imageクラスとその派生クラスにはgetGraphics()というメソッドがある。これがグラフィックスコンテキストを生成する命令だ。
こいつはjava.awt.Graphicsクラスのインスタンスを生成する。Graphicsクラス自体は抽象クラスである。
JavaDocを見てもらえるとわかるが、ここに実際に描画するメソッドがたくさんある。これで好き勝手に描画するとよい。
描画が終わったらGraphics#dispose()メソッドでリソースを開放する。
また使いたくなたらImage#getGraphics()するとよい。
Java2Dへ
Graphics2Dというクラスがある。これはGraphicsを継承している。そして、JavaSEでのGraphicsを生成するメソッドはすべてGraphics2Dである。つまり、Image#getGraphics()したあとにキャストをすることによって扱えるようになる。
見るとわかるが、メソッドが大量に追加される上に、拡大縮小回転など非常に実用的な命令だらけである。2Dはこいつできまりだ。
また、キャストが面倒な人はBufferedImageやVolatileImageのcreateGraphics()メソッドを利用するとよい。中身は同じ、どちらもGraphics2Dを生成するクラスだ。
こんな感じで使う
//128*128、アルファ付32bitカラーのイメージを生成 BufferedImage image = new BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB); //グラフィックスコンテキスト作成 Graphics2D g2 = image.createGraphics(); //赤い四角を描画 g2.setColor(Color.RED); g2.drawRect(0, 0, 64, 64); //緑の円を描画 g2.setColor(Color.GREEN); g2.drawOval(64, 64, 64, 64); //リソース開放 g2.dispose();
BufferedImageのコンストラクタの最初の2つが画像のサイズ、3つ目が画像のピクセルフォーマットだ。インデックスカラーとかもあるが、扱いが面倒なので今回はパレットなしのシンプルなやつにしてみた。モノクロとか16bitカラーとかもある。想定する速度に合わせて適切にピクセルフォーマットのサイズを小さくするのはありだ。が、インデックスカラーなど最近は余計に処理時間がかかったりすることもある。
とりあえず、
これらがわかればあとはそこからいろいろとたどれるはずだ。
もう、Javaで画像処理はマスターしたも当然だね!