2011年8月19日金曜日

画像を色抜き合成する

「画像を重ねてよ」って言われて、どうしようかって思ったんです


どうも。
いち、プログラマのyu1rowです。
2枚のBufferedImageがありまして、2枚目の画像の特定の色を透明にしてしまいたいという要件がありました。
なんせあんまりJavaの画像処理のコトしらないし、とりあえず以下のソースのように対処しました。
package com.yu1row.blog;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.MemoryImageSource;
import java.awt.image.PixelGrabber;

public class Practice02 {
    /**
     * 画像同士を合成した {@link BufferedImage} を取得します。
     * <p>元画像に対し、重ね合わせ画像の特定の色を透明にし、元画像に重ね合わせて合成画像を得ます。</p>
     * @param src 元画像
     * @param lay 重ね合わせ画像
     * @param alphaColor 重ね合わせ画像の透明色
     * @return 合成画像
     */
    public static BufferedImage getOverlayedImage(BufferedImage src, BufferedImage lay, Color alphaColor) {
        if (src == null) { return null; }   // 元画像がnullの場合
        if (lay == null) { return src; } // 重ね合わせ画像がnullの場合

        // 重ね合わせ画像のサイズ取得
        int width = lay.getWidth();
        int height = lay.getHeight();
        // 重ね合わせ画像→int[]変換
        int[] pixel = new int[width*height];
        PixelGrabber pg = new PixelGrabber(lay,0,0,width,height,pixel,0,width);
        try { pg.grabPixels(); } catch (InterruptedException e) { return null; }
        // 重ね合わせ画像の色抜き
        int color = alphaColor.getRGB();
        for(int i = 0; i < width * height; ++i) {
            if (pixel[i] == color) {
                pixel[i] = pixel[i] & 0x00FFFFFF;
            }
        }

        // 色抜きされたイメージを作成
        Image alphaImage = Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(width, height, pixel, 0, width));

        // 結果画像を作成
        // 元画像のクローンに、色抜きイメージを描画してオーバーレイを行う
        BufferedImage result = getBufferedImageClone(src);
        Graphics g = result.getGraphics();
        g.drawImage(alphaImage,0,0,null);
        g.dispose();

        return result;
    }

    /**
    * {@link BufferedImage} のクローンを取得します。
    * @param src 元の {@link BufferedImage} オブジェクト
    * @return {@link BufferedImage} のクローン
    */
    public static BufferedImage getBufferedImageClone(BufferedImage src) {
        if (src == null) { return null; }

        // 同サイズ、同タイプのBufferedImageを作成
        BufferedImage dst = new BufferedImage(src.getWidth(), src.getHeight(), src.getType());

        // クローンに描画
        Graphics g = dst.getGraphics();
        g.drawImage(src, 0, 0, src.getWidth(), src.getHeight(), null);
        g.dispose();
        return dst;
    }
}

getOverlayedImage()のsrcにlayを重ね合わせます。
layの中で、alphaColorに指定した色が透明になって透けます。

自信ねーんですよ、コレ


実際コレで一応実現しましたがね、歯車の再開発してるようにしか思えないんですよ。
もっと楽にできる素晴らしいやりかた、誰か教えてください。

※追記
改良?しました

0 件のコメント:

コメントを投稿