ImageIO#readのBugSolver(代替方法)
画像送信プログラムを作製中、、
Bug ID: JDK-4821108 IIOException thrown when reading PNG images
このバグ報告が出ていることに暫く気づかず、ずっとImageIOクラスで戦っていました。
しかしながら、Bugにより、ImageIO#readを使用しての画像送信は無理です。
そこで様々な解決策を考えました。
真っ先に思いつくのが、画像をByte配列に変換し、送信し、デコードして復元する。
ByteArrayOutputStreamなどを使用すれば、変換することはできます。
しかし、複雑で送信に時間がかかったため、非採用としました。
もうひとつの方法として、ObjectOutputStreamを使用し、オブジェクトとして送信することです。
Imageオブジェクトを送信しても、読み込み側でImageIOを使用しなくてはいけないため意味がありません。
そこで、BufferedImageオブジェクトをObjectOutputStream#writeObjectに乗せて送信することを思いつきました。
しかし、まだ問題はあります。
それは、ObjectOutputStreamは直列化(serialize)されたオブジェクトしか扱えないということです。
BufferedImageはSerializeされていないため、そのまま送ることは不可能です。
そこで、自作クラスでラップし、そのクラスをSerializeしてみます。
Serializeする独自クラスは以下のようになります。
import java.awt.image.BufferedImage; import java.io.Serializable; public class BufferedImageSerializer implements Serializable { private static final long serialVersionUID = 1L; private int width, height; private int[] pixels; /** * 受け取ったBufferedImageクラスのインスタンスの情報を収集します。 * @param image 送信したいBufferedImageクラスインスタンス */ public BufferedImageSerializer(BufferedImage image) { width = image.getWidth(); height = image.getHeight(); pixels = new int[width * height]; image.getRGB(0, 0, width, height, pixels, 0, width); } /** * BufferedImageクラスのインスタンスを受け取ります。 * 画像受信元にて使用します。 * @return 送信されたBufferedImageインスタンス */ public BufferedImage getImage() { BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); image.setRGB(0, 0, width, height, pixels, 0, width); return image; } }
利用方法はコードを示すまでもなく、
画像を送信する側は、コンストラクタにBufferedImageのインスタンスを指定する。
画像を受信する側は、getImageで取得する。
これでOKです。
サーバークライアントソフトウェアはこの問題を最後についにリリース版となりました!!
これからもバージョンアップを重ねていきます。