byte配列からBufferedImageを生成する方法について、色々調べたのですが、どうもいい感じの方法がなかったので、さらに調べて自分で書いたりした方法を書きます。
広告
目次
よくあるbyte配列からの生成方法
よく検索等でHitするのは、バイトストリームを作ってBufferedImageに流し込む方法です。
大体以下のような感じ。
InputStream is = new ByteArrayInputStream(byteArray);
BufferedImage bi = ImageIO.read(is);
でもこれだと一寸美しくないというか、なんというか。
ですので、別の方法を書いておきます。
BuffredImageの内部配列に流し込む方法
BufferedImageから配列の値を取り出す方法について書いた記事に、BufferedImageの内部にあるRasterからgetDataBufferでDataBufferを取り出し、それをDataBufferByteでキャストしてgetDataすることで内部のbyte配列を取り出せることをコードで示したと思います。
ということは、そのbyte配列に、用意したbyte配列をまるっとコピーしてしまえばいいわけですね。
流れとしては、以下のような感じになります。
- ピクセルの値を入れたbyte配列を用意する
- 新しいBufferedImageを作成する
- 新しく作成したBufferedImageのDataBufferByte内配列にbyte配列をコピーして流し込む
カラースペースはTYPE_4BYTE_AGBRなど、BYTEで保存されているらしいものを使ってBufferedImageを作る感じです。
コードにすると下のような感じ。
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_AGBR);
byte[] biByteArray = ((DataBufferByte)bi.getRaster().getDataBuffer()).getData();
System.arraycopy(bArray,0,biByteArray,0,bArray.length);
なお、bArrayは用意したbyte配列です。これをbiByteArrayに入れるわけです。biByteArray=bArrayというように何故直接代入しないかというと、biByteArrayの指すポインタがかわるだけで、getDataした配列の中身は変わらないかもしれない、と思ったからです。どうなのかはあまり確かめていませんが、こちらのほうがbyte配列を写すとき、間に何かの処理をはさめるので、便利かもしれません。
参考にしたのは、以下や公式ドキュメントです。
WritableRasterを生成する方法
次の方法は、一寸遠回りです。どちらかといえばint配列からBufferedImageを生成するほうに使えるかもしれません。
まずbyte配列からint配列を準備します。intはARGB形式の場合、byte a, byte r, byte g, byte bについて、
int argb = (((int)a & 0xff) << 24 | ((int)r & 0xff)<<16 |((int)g &
0xff) << 8| ((int)b & 0xff))
という変換をかませることで色の値をbyteからintに変換することができます。これについてはいろいろなサイトがありますので、「int 色 変換」とか、そんな感じで検索していただければと思います。
なおこのときのbyteからintへの変換のとき、rから変換した値を重ねるのを省くとか、ちょっとした処理も可能です。
このようにしてbyte配列からargb4つの色の値をまとめたintの配列を作成し、それを元にWritebleRasterを作成して、BufferedImageにsetData()でセットすることで可能になります。
コードにするとこんな感じ。iArrayはint配列を格納した変数です。
DataBufferInt dbufint = new DataBufferInt(iArray, iArray.length);
WritableRaster r = Raster.createPackedRaster(dbufint, width, height, new int[]{0x00ff0000,0x0000ff00,0x000000ff,0xff000000},null);
BufferedImage bi = new BufferedImage(width,height, BufferedImage,TYPE_4BYTE_ABGR);
bi.setData(r);
なお、この方法は以下のリンクや公式ドキュメントを参考にしました。
また、このRasterを作成するものは、byte配列からの変換では、WritableRasterを生成するからか、BufferedImageの配列にコピーでぶち込むよりも時間がかかるようです。
その他コメントなど
たまに配列から画像を生成したくなったりするのですが、その時ごとに過去のソースを探すのも結構手間がかかるので、まとめました。