gifイメージの出力
javaのImageIOで画像の出力が出来るが、今のところ、pngだと特に問題なく出力出来る。
//サーブレットで使う場合 private void writeImage(BufferedImage image){ HttpServletResponse response = ResponseUtil.getResponse(); ServletOutputStream sos = null; ImageOutputStream ios = null; try{ sos = response.getOutputStream(); response.setContentType("image/png"); ios = ImageIO.createImageOutputStream(sos); ImageWriter iw = ImageIO.getImageWritersByMIMEType("image/png").next(); iw.setOutput(ios); iw.write(image); iw.dispose(); }catch(Exception e){ e.printStackTrace(); }finally{ try { ios.close(); sos.close(); } catch (IOException e) { e.printStackTrace(); } } }
上記の場合、BufferedImageをTYPE_INT_ARGBにして、生成したBufferedImageのgraphicsに
以下のように指定すると背景がとりあえず透過色になるようです。
BufferedImage image = new BufferedImage(500, 500, BufferedImage.TYPE_INT_ARGB); Graphics2D gdImage = image.createGraphics(); gdImage.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f));
しかし、gifで出力した際に、上記指定をして出力すると背景が真っ黒になってしまう。
なぜだろう?と思ったが、gifは256色までしか扱えないが、pngはフルカラーをサポートし、
さらにアルファチャンネルというのを持ち、半透明などの色も扱える。
gifは透過色を1色しか指定出来ない。
なので、pngで微妙に透過された表示できていた色が滅色されて真っ黒になってしまったのだろうと思いました。
じゃあgifで透過色を指定するのはどうやるの?
色々調べたところ、この
BufferedImage image = new BufferedImage(500, 500, BufferedImage.TYPE_INT_ARGB);
のところで第三引数にTYPE_INT_ARGBを指定した場合
JavaDocによると
整数型ピクセルにパックされた 8 ビット RGBA 色成分によるイメージを表します。このイメージは、DirectColorModel (アルファあり) を持ちます。このイメージのカラーデータには、アルファがあらかじめ乗算されていません。このタイプが BufferedImage コンストラクタへの imageType 引数として使用される場合、作成されるイメージは JDK 1.1 以前のリリースで作成されるイメージと一貫性があります。
と記載があり、DirectColorModelとかいうものを使っているらしいということがわかりました。
さらにその説明を見ると
なにやらよく分かりませんが、
このカラーモデルは X11 の TrueColor に類似しています。
とあるので、約1670万色を扱っているのだとわかります。
gifでサポートしているのは256色が限度なので、ImageIOで書き込みする際には微妙な色は滅色されることが予想されます。
じゃあどうするのか。
BufferedImageには
public BufferedImage(int width,
int height,
int imageType,
IndexColorModel cm)
なコンストラクタがあります。
先ほど出てきたDirectColorModelの仲間っぽい「IndexColorModel」というのが出てきます。
これはなんだ?と思ってこちらに分かりやすく説明してくれているページを見つけたのですが、
どうしても理解できず、それでまずはビット演算や、シフト演算
を最初から勉強しなおしたのでした。
[...] gifイメージの出力の続きです。 [...]