java.awt.Image を BufferedImage や byte 配列に変換する方法
Java ImageIO で Flickr 並みのサムネイル画像をつくるという記事で、
java.awt.Image を BufferedImage や byte 配列に変換する方法は次回。
と書いたにも関わらず、そのまま放置になっていた(コメントで指摘されているのに気づいたのも今日だ。すまん)。
概要
まずは java.awt.image.BufferedImage
を byte
配列に変換する方法を紹介する。
そのあと、java.awt.Image
を java.awt.image.BufferedImage
に変換する方法を紹介するので、このふたつを組み合わせれば、
Image --> BufferedImage --> byte[]
が実現できるわけだ。
BufferedImage を byte[] に変換する
BufferedImage
から byte
配列の変換は、javax.imageio.ImageWriter
でわりかし素直に実装できる。
BufferedImage image = ...;
ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
ImageWriter writer = ImageIOKit.getImageWritersByFormatName(formatName);
ImageOutputStream stream = ImageIO.createImageOutputStream(bytesOut);
try {
writer.setOutput(stream);
writer.write(image);
stream.flush();
} finally {
writer.dispose();
if (stream != null) try { stream.close(); } catch (Throwable t) {;}
}
byte[] bytes = bytesOut.toByteArray();
...
ImageWriteParam
も組み合わせれば、圧縮率などの設定ができる。
Image を BufferedImage をに変換する
一筋縄ではいかないのが、Image を BufferedImage をに変換する方法だ。
以下では、image
変数が java.awt.Image
のインスタンスであるとして、順を追って説明する。
まず、image
が BufferedImage
のインスタンスなら、以降は何もする必要がない。
if (image instanceof BufferedImage) {
...
}
次に、java.awt.Image
のインスタンスは、実際のデータが非同期でロードされているかもしれないので、変換処理を行う前に、java.awt.MediaTracker
でロードが完了するまで待機する。
// java.awt.MediaTracker でロードを待機
MediaTracker tracker = new MediaTracker(new Component(){});
tracker.addImage(image, 0);
tracker.waitForAll();
ここからが実際の変換処理になるが、基本的に、
- 新規に
BufferedImage
を生成 - 生成した
BufferedImage
にImage
のピクセルをコピー
という処理になる。
PixelGrabber pixelGrabber = new PixelGrabber(image, 0, 0, -1, -1, false);
pixelGrabber.grabPixels();
ColorModel cm = pixelGrabber.getColorModel();
final int w = pixelGrabber.getWidth();
final int h = pixelGrabber.getHeight();
WritableRaster raster = cm.createCompatibleWritableRaster(w, h);
BufferedImage renderedImage =
new BufferedImage(
cm,
raster,
cm.isAlphaPremultiplied(),
new Hashtable());
renderedImage.getRaster().setDataElements(0, 0, w, h, pixelGrabber.getPixels());
上記のコードでは、元の ColorModel
もサポートするために、PixelGrabber を使っている。
あとは、ここで生成した BufferedImage
を byte
配列に変換してやればよい。