AndroidのBitmap画像プログラミング(2) 透過処理
AndroidのAndroidのBitmap画像プログラミング第二回です。
今回は画像の透過処理です。
Androidでは画像バッファの1pixel情報であるintがARGBを表しています。
ARGBのAはalpha値で上位1byte、つまり0~255の値で表現されます。
alpha値が0の場合下位3byteにどんな値が入っていても描画されません。
つまり透過色をあらかじめ決めておいて、透過対象のpixelのalpha値を0にすれば透過処理の完成です。
以下のような関数で実現できます。
public void InvalidBufferFromColor(int color)
{
int buf_color = 0;
for (int y = 0; y < mHeight; y++) {
for (int x = 0; x < mWidth; x++) {
buf_color = mBuffer[x + y * mWidth];
if (((buf_color >>> 24) & 0xff) > 0) {
if ((buf_color & 0xffffff) == (color & 0xffffff)) {
mBuffer[x + y * mWidth] = (buf_color & 0xffffff);
}
}
}
}
}
サンプルとして、赤色を透過してみました。
サンプル
package net.n2works.BitmapTest;
// SYSTEM PACKAGE
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.PorterDuff.Mode;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class BitmapTest extends Activity
{
// Bitmap
private Bitmap mBitmap;
private Bitmap mBitmap2;
/**
* Component
*/
// SurfaceView
private SurfaceView mView;
/**
* クラス定数
*/
private final int BG_COLOR = 0xff000000;
private final int BITMAP_W = 200;
private final int BITMAP_H = 200;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// BITMAPの作成
ImageBuffer buf = new ImageBuffer(BITMAP_W, BITMAP_H);
buf.FillClip(
buf.new ClipFillInfo(
0,
0,
BITMAP_W,
BITMAP_H,
0xffff0000
)
);
buf.FillClip(
buf.new ClipFillInfo(
BITMAP_W / 4,
BITMAP_H / 4,
BITMAP_W / 2,
BITMAP_H / 2,
0xff0000ff
)
);
mBitmap = Bitmap.createBitmap(BITMAP_W, BITMAP_H, Bitmap.Config.ARGB_8888);
mBitmap.setPixels(buf.GetBuffer(), 0, BITMAP_W, 0, 0, BITMAP_W, BITMAP_H);
// コピー
ImageBuffer buf2 = new ImageBuffer(BITMAP_W, BITMAP_H);
buf2.BltClip(
buf,
buf2.new ClipBltInfo(
0,
0,
0,
0,
BITMAP_W,
BITMAP_H
)
);
// 赤成分を無効
buf2.InvalidBufferFromColor(0xffff0000);
mBitmap2 = Bitmap.createBitmap(BITMAP_W, BITMAP_H, Bitmap.Config.ARGB_8888);
mBitmap2.setPixels(buf2.GetBuffer(), 0, BITMAP_W, 0, 0, BITMAP_W, BITMAP_H);
// Viewの設定
mView = new SurfaceViewEx(this);
setContentView(mView);
}
private class SurfaceViewEx extends SurfaceView
implements SurfaceHolder.Callback
{
/**
* Component
*/
private ScheduledExecutorService executor;
/**
* クラス定数
*/
private static final int FPS = 60;
public SurfaceViewEx(Context context)
{
super(context);
getHolder().addCallback(this);
getHolder().setType(SurfaceHolder.SURFACE_TYPE_GPU);
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
}
public void surfaceCreated(SurfaceHolder holder)
{
executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(
new Runnable()
{
public void run()
{
Canvas c = getHolder().lockCanvas();
Draw(c);
getHolder().unlockCanvasAndPost(c);
}
},
1000 / FPS, 1000 / FPS,
TimeUnit.MILLISECONDS
);
}
public void surfaceDestroyed(SurfaceHolder holder)
{
mBitmap.recycle();
mBitmap2.recycle();
executor.shutdown();
}
protected void Draw(Canvas c)
{
// 背景色クリア
c.drawColor(BG_COLOR, Mode.SCREEN);
// Bitmap描画
c.drawBitmap(mBitmap, 0, 0, null);
c.drawBitmap(mBitmap2, 0.0f, 200.0f, null);
}
}
}