[Java]byte配列から画像(BufferedImage)を生成する方法

 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配列をまるっとコピーしてしまえばいいわけですね。

 流れとしては、以下のような感じになります。

  1. ピクセルの値を入れたbyte配列を用意する
  2. 新しいBufferedImageを作成する
  3. 新しく作成した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の配列にコピーでぶち込むよりも時間がかかるようです。

その他コメントなど

 たまに配列から画像を生成したくなったりするのですが、その時ごとに過去のソースを探すのも結構手間がかかるので、まとめました。

広告

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA