2011-10-12 19 views
8

私は、Multiplyのようなブレンドモードを使用して、Androidと一緒に2つの画像をブレンドしようとしています。2つの画像を乗算と%opacityとブレンドする

// 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()はこれでは機能しないようです。

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

P.S.私は、白色に色をあらかじめ乗算してオフセットすることによって(LightingColorFilterを使用して)このような乗算を行ういくつかの方法がありますが、それは多重モードに非常に特有です。不透明度を適用する方法を見つけようとしています/他のすべての転送モードにも影響します。

答えて

2

私はしばらく前にそのようなことをする必要があり、私はthis post about Color Channelsが多くの啓発を見つけました。 (これはあなたの "PS"で説明したものと関連していると思いますが)

+1

Valeu rapazしかし、ええ、記事はすばらしいですが、各モードの入力値の%を変更する方法ではなく、レイヤーを異なるモードで貼り付けるだけです。それは画像からそれらを読み込んだ後のピクセルのいくつかの直接操作を示しているので、おそらくそれは別のものです。私はそれを調べる必要があります。今のところ、ありがとう! – zeh

+1

リンクが見つかりません。更新してください! –

2

私は私たちのアプリケーションと同様のフォトフィルターを実装していました。彼らはsource bitmap + mask bitmap + blend mode + alpha valueのようなものです。同じ動作を実現するために、私はマスクのアルファを増やしました。 jniBlendが、私はそれがJavaで株式PorterDuffモードのように振る舞い、自分で書いたいくつかの方法であることを

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; 
} 

注:ここでは私のコードが最終的に見えるものです。

方法makeTransparentは私のものではありません - hereそれを見つけた:(Rubanからの回答)

0

コードは完全ではありません。レンダースクリプトを使用してイメージをブレンドするためのアイデアを提供するだけです。

public Bitmap blend(Bitmap image) 
{ 
    final float BLUR_RADIUS = 25f; 
    Bitmap outbitmap = Bitmap.createBitmap(image); 
    final RenderScript renderScript = RenderScript.create(this); 

    Allocation tmpin = Allocation.createFromBitmap(renderScript,image); 
    Allocation tmpout = Allocation.createFromBitmap(renderScript,outbitmap); 
    ScriptIntrinsicBlend blend = ScriptIntrinsicBlend.create(renderScript, 
    Element.U8_4(renderScript)); 

    blend.forEachMultiply(tmpin,tmpout); 
    return outbitmap; 
} 
関連する問題