透過色のあるgif画像の出力
gifイメージの出力の続きです。
「透過色」「gif」「java」で検索してもそのものの答えが出なかったのですが、
今日、ついに決着がついたのでメモしておきます。
1. BufferedImageの生成
BufferedImageはBufferedImage.TYPE_BYTE_INDEXEDで作成します。
カラーモデルを指定するコンストラクタです。
BufferedImage(int, int, int, java.awt.image.IndexColorModel)
ですね。第4引数のIndexColorModelは
BufferedImage(int, int, int)
のソースのTYPE_BYTE_INDEXEDの所から引用させていただいて、以下のように作成しました。
private IndexColorModel createIndexColorModel(){ // Create a 6x6x6 color cube int[] cmap = new int[256]; int i=0; for (int r=0; r < 256; r += 51) { for (int g=0; g < 256; g += 51) { for (int b=0; b < 256; b += 51) { cmap[i++] = (r<<16)|(g<<8)|b; } } } // And populate the rest of the cmap with gray values int grayIncr = 256/(256-i); // The gray ramp will be between 18 and 252 int gray = grayIncr*3; for (; i < 256; i++) { cmap[i] = (gray<<16)|(gray<<8)|gray; gray += grayIncr; } return new IndexColorModel(8, 256, cmap, 0, true, 215, DataBuffer.TYPE_BYTE); }
元ソースと違うところは、最後のIndexColoeModelを生成する所で、第5引数(hasAlpha)にtrue、
第6引数に透過色とする為のインデックス番号を指定している所です。
(IndexColorModelのコンストラクタIndexColorModel(int, int, int[], int, boolean, int, int))
処理の最初のほうでcmapという変数に色を詰め込んでいますが、この場合は215番目が白(0xffffff = 16777215)になります。
白を透過色とする場合です。
これはコンストラクタかユーティリティを用意して欲しいところですね。
2. Graphics2Dの生成
そのBufferedImageからGraphics2Dを生成します。
生成して色々設定していきますが、gif出力の場合、描画のアンチエイリアス設定をすると白背景にしたつもりが真っ黒になってしまいます。
pngで出力する場合は描画のアンチエイリアス設定をしても問題ありません。
BufferedImage b = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_INDEXED, createIndexColorModel()); Graphics2D g = b.createGraphics(); Map renderingHints = new HashMap(); //描画のアンチエイリアス // renderingHints.put(RenderingHints.KEY_ANTIALIASING, // RenderingHints.VALUE_ANTIALIAS_ON); //文字描画のアンチエイリアス renderingHints.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); //描画ヒントキー renderingHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); //アルファ補完 renderingHints.put(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); g.setRenderingHints(renderingHints); g.setComposite(AlphaComposite.Clear); g.fillRect(0, 0, width, height); g.setComposite(AlphaComposite.SrcOver); :
また、AlphaCompositeのClearを設定、塗りつぶし、AlphaCompositeのSrcOver設定を順番にやります。
この後に内容を描画していきます。
3. gifファイル出力
private void writeImage(String outputFile, BufferedImage image) { File file = new File(outputFile); ImageOutputStream ios = null; ImageWriter iw = null; try { ios = ImageIO.createImageOutputStream(file); iw = ImageIO.getImageWritersByFormatName("gif").next(); iw.setOutput(ios); iw.write(image); } catch (IOException e) { throw new Exception("ファイル作成に失敗しました"); } finally { iw.dispose(); try { ios.close(); } catch (IOException e) { throw new Exception("ファイルのClose処理に失敗しました"); } } }
描画内容の色が白にあまりにも近い場合(今回は0xfffffeで試した)ら、白に滅色されてしまっているのか、
出力されませんでした。
可能であればWebセーフカラーにあわせておいたら確実でしょう。