15

私はここで壁に頭を打ちつけています、そして私は私が愚かなことをしているとかなり確信しています、それで私の愚かさを公表する時が来ました。

2つの画像を取得し、標準のブレンドアルゴリズム(ハードライト、ソフトライト、オーバーレイ、乗算など)を使用して3番目の画像にブレンドしようとしています。

Androidにはそのようなブレンドプロパティが組み込まれていないため、各ピクセルを取得し、アルゴリズムを使用してそれらを組み合わせるという道をたどりました。ただし、結果はごみです。以下は、単純な乗算ブレンドの結果です(使用された画像と期待される結果)。

ベース:代替テキスト

ブレンド:代替テキスト

期待される結果:代替テキスト

ゴミの結果:代替テキスト

どんな助けでもいただければ幸いです。以下は、私がすべての「ジャンク」を取り除こうとしたコードですが、一部は成功した可能性があります。不明な点がある場合はクリーンアップします。

    ImageView imageView = (ImageView) findViewById(R.id.ImageView01);
    Bitmap base = BitmapFactory.decodeResource(getResources(), R.drawable.base);
    Bitmap result = base.copy(Bitmap.Config.RGB_565, true);
    Bitmap blend = BitmapFactory.decodeResource(getResources(), R.drawable.blend);

    IntBuffer buffBase = IntBuffer.allocate(base.getWidth() * base.getHeight());
    base.copyPixelsToBuffer(buffBase);
    buffBase.rewind();

    IntBuffer buffBlend = IntBuffer.allocate(blend.getWidth() * blend.getHeight());
    blend.copyPixelsToBuffer(buffBlend);
    buffBlend.rewind();

    IntBuffer buffOut = IntBuffer.allocate(base.getWidth() * base.getHeight());
    buffOut.rewind();

    while (buffOut.position() < buffOut.limit()) {
        int filterInt = buffBlend.get();
        int srcInt = buffBase.get();

        int redValueFilter = Color.red(filterInt);
        int greenValueFilter = Color.green(filterInt);
        int blueValueFilter = Color.blue(filterInt);

        int redValueSrc = Color.red(srcInt);
        int greenValueSrc = Color.green(srcInt);
        int blueValueSrc = Color.blue(srcInt);

        int redValueFinal = multiply(redValueFilter, redValueSrc);
        int greenValueFinal = multiply(greenValueFilter, greenValueSrc);
        int blueValueFinal = multiply(blueValueFilter, blueValueSrc);

        int pixel = Color.argb(255, redValueFinal, greenValueFinal, blueValueFinal);

        buffOut.put(pixel);
    }

    buffOut.rewind();

    result.copyPixelsFromBuffer(buffOut);   

    BitmapDrawable drawable = new BitmapDrawable(getResources(), result);
    imageView.setImageDrawable(drawable);
}

int multiply(int in1, int in2) {
    return in1 * in2 / 255;
}
4

2 に答える 2

15

再現した後、問題は RGB565 モードで画像を操作することに関係していると思います。この投稿で説明したように、ビットマップを適切に操作するには、明らかに ARGB8888 モードにする必要があります。最初に、次のようにして、乗算ブレンドで期待される結果を得ました。

Resources res = getResources();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap base = BitmapFactory.decodeResource(res, R.drawable.base, options);
Bitmap blend = BitmapFactory.decodeResource(res, R.drawable.blend, options);

// now base and blend are in ARGB8888 mode, which is what you want

Bitmap result = base.copy(Config.ARGB_8888, true);
// Continue with IntBuffers as before...

ビットマップを ARGB8888 モードに変換することは、少なくともグラデーション テスト パターンではうまくいったようです。ただし、Screen または Multiply を実行するだけでよい場合は、次の方法も試してみてください。

// Same image creation/reading as above, then:
Paint p = new Paint();
p.setXfermode(new PorterDuffXfermode(Mode.MULTIPLY));
p.setShader(new BitmapShader(blend, TileMode.CLAMP, TileMode.CLAMP));

Canvas c = new Canvas();
c.setBitmap(result);
c.drawBitmap(base, 0, 0, null);
c.drawRect(0, 0, base.getWidth(), base.getHeight(), p);

これにより、ピクセルごとの計算は行われませんが、プリセットPorterDuff.Modes に制限されます。私の簡単な(そして汚い)テストでは、これが非グラデーション画像でブレンドを機能させることができた唯一の方法でした.

于 2011-01-05T18:32:19.277 に答える
5

この方法で簡単にオーバーレイできます (簡単にするために、bmp1 は bmp2 と同じかそれより大きいと仮定します)。

private Bitmap bitmapOverlay(Bitmap bmp1, Bitmap bmp2) 
{ 
    Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth(), bmp1.getHeight(), bmp1.getConfig()); 
    Canvas canvas = new Canvas(bmOverlay); 
    canvas.drawBitmap(bmp1, 0, 0, null);
    canvas.drawBitmap(bmp2, 0, 0, null);
    return bmOverlay; 
} 

より複雑なブレンディング アルゴリズムについては、利用可能な Bitmap/Canvas 関数をいくつか利用できるかもしれません。

于 2011-01-05T16:49:40.340 に答える