2010/02/24

openFrameworksで背景を透過させてキャプチャする方法

openFrameworksで背景を透明化したPNG画像を書き出す方法。
標準のライブラリだけでは上手いこと書き出せなかったので
イメージピクセルにアクセスして、アルファ値を変更して画像保存した。
簡単に書くと
・イメージ宣言の際にOF_IMAGE_COLOR_ALPHAを代入
・pixels宣言でwidth*height*4
・getPixels()
・アルファ値[(widthOfLine * y + x )* 4 + 3]
・setFromPixels → saveImage

ベースとなるサンプルはimageSaverExampleを使うと良い。
void testApp::setup(){

img.allocate(300,300,OF_IMAGE_COLOR_ALPHA);
img2.allocate(300,300,OF_IMAGE_COLOR_ALPHA);

・ キャプチャ用イメージとアルファ変更用イメージのサイズを宣言。
この時OF_IMAGE_COLOR_ALPHAを代入しておく。

void testApp::draw(){
if(bSnapshot2 == false){
    ofSetColor(0xffffff);colorImg.draw(20,20);//元画像
   }
if(bSnapshot2 == true){
    ofEnableAlphaBlending();
    ofSetColor(0xffffff);
    img2.draw(200,200);//アルファ変更画像
    ofDisableAlphaBlending();
}
//保存
if (bSnapshot2 == true){
        char fileName[255];
        sprintf(fileName, "snapshot_%0.3i.png", snapCounter);
        img2.saveImage(fileName);
        sprintf(snapString, "saved %s", fileName);
        bSnapshot2 = false;
}
if (bSnapshot == true){
        img.grabScreen(200,200,300,300);
        unsigned char * pixels;
        unsigned char * pixels2;
        pixels = (unsigned char*)malloc(300*300*4);
        pixels2 = (unsigned char*)malloc(300*300*4);

        pixels =  img.getPixels();
       
        int widthOfLine = 300;  // 画像の幅
        for (int y = 0; y < 300; y++) {
            for (int x = 0; x < 300; x++) {
               
                int red = pixels[(widthOfLine * y + x) * 4];
                int green = pixels[(widthOfLine * y + x )* 4 + 1];
                int blue = pixels[(widthOfLine * y + x )* 4 + 2];
               
                pixels2[(widthOfLine * y + x) * 4]     = blue;
                pixels2[(widthOfLine * y + x) * 4 + 1]     = green;
                pixels2[(widthOfLine * y + x )* 4 + 2]     = red;
                if(red > 150 && green > 150 && blue > 150){
                   pixels2[(widthOfLine * y + x )* 4 + 3]     = 0;//アルファを変更
                }else{  pixels2[(widthOfLine * y + x )* 4 + 3]     = 255;}
               
            }
        }
        img2.setFromPixels(pixels2, 300, 300, OF_IMAGE_COLOR_ALPHA);//アルファ用に格納
               
        snapCounter++;
        bSnapshot = false;
        bSnapshot2 = true;

    }

・これはビデオイメージから白い部分を判別し、透過させ書き出している。
・ピクセルに対しての変更は以下を参考にする。
RGBAがBGRAになっているので格納の際に逆にすると良い。
   pixels[(widthOfLine * y + x) * 4]     = red;
   pixels[(widthOfLine * y + x) * 4 + 1]     = green;
   pixels[(widthOfLine * y + x )* 4 + 2]     = blue;
   pixels[(widthOfLine * y + x )* 4 + 3]     = alpha;
・あとはOF_IMAGE_COLOR_ALPHAをGL_RGBAにしないこと。
・alpha値は0〜255で透明〜不透明になっている。100くらいだと半透明で保存できる。

0 件のコメント:

コメントを投稿