読者です 読者をやめる 読者になる 読者になる

chikuchikugonzalezの雑記帳

趣味とか日記とかメモとか(∩゚д゚)

画像のRGB分離ツールとか作ってた

M.U.G.E.Nは基本256色画像しか扱えない。その上で24bit画像を再現しようとすると結局のところRGBそれぞれ256階調の画像を用意してTrans=Addで重ねる方法が基本だと思う*1
で、今まではGIMPを使って

  1. RGB分離
  2. グレースケール保存
  3. edgeでRGBそれぞれの階調のグラデーションパレットに変更

とかしてました。

でも画像がいっぱいあると凄まじく面倒なのですよ。ついでに最近は32bit画像 (つまりはアルファ) の再現も使用した結果、DirectXのテクスチャツールも併用するから面倒くささ倍増中だった *2
いい加減楽したかったのでRGBAを分離してそれぞれ256階調のbmpにして吐き出すプログラムを書いた。以下がそのソース。

import java.awt.image.*;
import java.io.*;
import java.util.*;
import java.util.concurrent.*;

import javax.imageio.*;


public class RGBSeparator implements Runnable {

//----------------------------------------------------------------------------//
// Fields --------------------------------------------------------------------//
//----------------------------------------------------------------------------//

    private File output = null;
    private File source = null;


//----------------------------------------------------------------------------//
// Class Methods -------------------------------------------------------------//
//----------------------------------------------------------------------------//

    public static void main(String[] args) throws Exception {
        BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
        ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 8, 30, TimeUnit.SECONDS, queue);
        for (String arg : args) {
            RGBSeparator sep = new RGBSeparator(arg);
            executor.execute(sep);
        }
        executor.shutdown();
        executor.awaitTermination(30, TimeUnit.MINUTES);
    }

    private static synchronized boolean createDirectory(File dir) {
        if (!dir.exists()) {
            return dir.mkdirs();
        }
        return true;
    }


//----------------------------------------------------------------------------//
// Constructors --------------------------------------------------------------//
//----------------------------------------------------------------------------//

    public RGBSeparator(String file) {
        this(new File(file));
    }

    public RGBSeparator(File file) {
        this(file, new File(System.getProperty("user.dir")));
    }

    public RGBSeparator(File src, File dir) {
        super();
        this.output = dir;
        this.source = src;
    }


//----------------------------------------------------------------------------//
// Methods -------------------------------------------------------------------//
//----------------------------------------------------------------------------//

    public void run() {
        System.out.println(String.format("[Object#%x] Started at %d [ms]", this.hashCode(), System.currentTimeMillis()));
        try {
            this.resolve();
        } catch (Exception ex) {
            throw new RuntimeException(ex.getMessage(), ex);
        }
        System.out.println(String.format("[Object#%x] Finished at %d [ms]", this.hashCode(), System.currentTimeMillis()));
    }

    public void resolve() throws IOException {
        BufferedImage image = ImageIO.read(this.source);
        //System.out.println(String.format("Image Type = %d", image.getType()));

        // 出力パレット
        byte[] palette = new byte[256];
        for (int i = 0; i < 256; i++) {
            palette[i] = (byte) i;
        }
        byte[] emptyPalette = new byte[256];
        for (int i = 0; i < 256; i++) {
            emptyPalette[i] = 0;
        }
        IndexColorModel red = new IndexColorModel(8, 256, palette, emptyPalette, emptyPalette);
        IndexColorModel green = new IndexColorModel(8, 256, emptyPalette, palette, emptyPalette);
        IndexColorModel blue = new IndexColorModel(8, 256, emptyPalette, emptyPalette, palette);

        // 出力画像を作成
        BufferedImage redImg = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_INDEXED, red);
        BufferedImage greenImg = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_INDEXED, green);
        BufferedImage blueImg = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_INDEXED, blue);
        BufferedImage alphaImg = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);

        // ピクセルを操作
        int imageWidth = image.getWidth();
        int imageHeight = image.getHeight();
        int[] pixels = new int[4];
        Raster data = image.getRaster();
        WritableRaster redData = redImg.getRaster();
        WritableRaster greenData = greenImg.getRaster();
        WritableRaster blueData = blueImg.getRaster();
        WritableRaster alphaData = alphaImg.getRaster();
        for (int x = 0; x < imageWidth; x++) {
            for (int y = 0; y < imageHeight; y++) {
                pixels = data.getPixel(x, y, pixels);
                //System.out.println(String.format("R=0x%02x,G=0x%02x,B=0x%02x", pixels[0], pixels[1], pixels[2]));

                // 書き込み
                redData.setPixel(x, y, new int[]{pixels[0]});
                greenData.setPixel(x, y, new int[]{pixels[1]});
                blueData.setPixel(x, y, new int[]{pixels[2]});
                alphaData.setPixel(x, y, new int[]{pixels[3]});
            }
        }

        // 書き込み
        File redDir = new File(this.output, "red");
        File greenDir = new File(this.output, "green");
        File blueDir = new File(this.output, "blue");
        File alphaDir = new File(this.output, "alpha");
        createDirectory(redDir);
        createDirectory(greenDir);
        createDirectory(blueDir);
        createDirectory(alphaDir);

        ImageIO.write(redImg, "bmp", new File(redDir, this.source.getName() + ".bmp"));
        ImageIO.write(greenImg, "bmp", new File(greenDir, this.source.getName() + ".bmp"));
        ImageIO.write(blueImg, "bmp", new File(blueDir, this.source.getName() + ".bmp"));
        ImageIO.write(alphaImg, "bmp", new File(alphaDir, this.source.getName() + ".bmp"));
    }

}

コンパイルは各人でお願いします*3

*1:5667氏がフルカラーOPを作ってたはず

*2:ツールでpngを開いてアルファ値だけを表示にして、それをキャプチャしてグレースケール変換とか

*3:アップロードが面倒なだけ