12

Multiplyのようなブレンディングモードを使用して、Androidで2つの画像をブレンドしようとしています。

// Prepare -------------------------------

// Create source images
Bitmap img1 = ...
Bitmap img2 = ...

// Create result image
Bitmap result = ...
Canvas canvas = new Canvas();
canvas.setBitmap(result);

// Get proper display reference
BitmapDrawable drawable = new BitmapDrawable(getResources(), result);
ImageView imageView = (ImageView)findViewById(R.id.imageBlend1);
imageView.setImageDrawable(drawable);


// Apply -------------------------------

// Draw base
canvas.drawBitmap(img1, 0, 0, null);

// Draw overlay
Paint paint = new Paint();
paint.setXfermode(new PorterDuffXfermode(Mode.MULTIPLY));
paint.setShader(new BitmapShader(img2, TileMode.CLAMP, TileMode.CLAMP));

canvas.drawRect(0, 0, img2.getWidth(), img2.getHeight(), paint);

これは機能しますが、実行される乗算の「量」を制御することはできません。これは常に完全な乗算転送です。理想的には、0%の乗算は、変更なしでベースイメージ(img1)と同じになりますが、100%の乗算は、上記のコードで得られる結果になります。

paint.setAlpha()これにはうまくいかないようです。

新しい「レイヤー」の不透明度を%に設定する他の方法はありますか?

PSこれを使って乗算を機能させる方法はいくつかあります(を使用してLightingColorFilter)、事前に乗算して色を白にオフセットしますが、これは乗算モードに非常に固有です..不透明度を適用する方法を見つけようとしています/ %他のすべての転送モードにも当てはまります。

4

4 に答える 4

3

私たちの iOS アプリと同様の写真フィルターを実装していました。彼らはそれを次のようにしsource bitmap + mask bitmap + blend mode + alpha valueます。同じ動作を実現するために、マスクのアルファを増やしました。これが私のコードが最終的に見えるものです:

public static Bitmap blend(Bitmap back, Bitmap front, BlendMethod method, float alpha) {
    if (alpha != 1.0F) {
        front = makeTransparent(front, Math.round(alpha * 255));
    }

    Bitmap.Config config = back.getConfig();
    int width = back.getWidth();
    int height = back.getHeight();

    if (width != front.getWidth() || height != front.getHeight()) {
        Log.e(TAG, "Arrays must be of identical size! Do bitmap scaling prior to blending.");
        return null;
    }

    int[] frontArr = new int[height * width], backArr = new int[height * width], resultArr;

    back.getPixels(backArr, 0, width, 0, 0, width, height);
    front.getPixels(frontArr, 0, width, 0, 0, width, height);

    resultArr = jniBlend(frontArr, backArr, alpha, method.toInt());
    return Bitmap.createBitmap(resultArr, width, height, config);
}

public static Bitmap blend(Bitmap back, Bitmap front, BlendMethod method) {
    return blend(back, front, method, 1F);
}

public static Bitmap makeTransparent(Bitmap src, int value) {
    int width = src.getWidth();
    int height = src.getHeight();
    Bitmap transBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(transBitmap);
    canvas.drawARGB(0, 0, 0, 0);
    // config paint
    final Paint paint = new Paint();
    paint.setAlpha(value);
    canvas.drawBitmap(src, 0, 0, paint);
    return transBitmap;
}

jniBlend は私が独自に作成したメソッドであり、Java の標準の PorterDuff モードのように動作することに注意してください。

メソッドmakeTransparentは私のものではありません-ここで見つけました:(ルバンからの回答)

于 2015-01-06T11:01:14.217 に答える
3

少し前にそのようなことをする必要がありましたが、カラー チャネルに関するこの投稿は非常に啓発的でした。(しかし、これはあなたが「PS」で説明したことに関連していると思います)

@1j01 のおかげで、archive.org の上記のリンク

于 2011-10-14T23:30:39.923 に答える