34

だから私はここからコードを試しました:マスクを使用してImageViewを作成します。次の画像を元のマスクとして使用しています。

ここに画像の説明を入力ここに画像の説明を入力

ただし、得られる結果は次のとおりです。

ここに画像の説明を入力

ウィンドウの背景は黒ではなく、ホロ ライトであることに注意してください (ギャラクシー ネクサスでは、完全な白ではなく、非常に淡いグレーに見えます)。2 番目の画像は、リスト ビューで項目を選択したときに得られる結果です。

代わりに、同じアルゴリズムを使用して新しいビットマップを作成し、onDraw() をオーバーライドする代わりにイメージ ビューに渡すと、正しく描画されます。

Canvas canvas = new Canvas();
Bitmap mainImage = //get original image
Bitmap maskImage = //get mask image
Bitmap result = Bitmap.createBitmap(mainImage.getWidth(), mainImage.getHeight(), Bitmap.Config.ARGB_8888);

canvas.setBitmap(result);
Paint paint = new Paint();
paint.setFilterBitmap(false);

canvas.drawBitmap(mainImage, 0, 0, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
canvas.drawBitmap(maskImage, 0, 0, paint);
paint.setXfermode(null);

imageView.setImageBitmap(result);

期待される結果が得られます:

ここに画像の説明を入力

フェードが正しく適用されていることに注意してください。これは、選択が行われるとより明白になります。

では、ウィンドウの背景が透けて見えるようにする代わりに、この黒い背景を作成する ImageView の onDraw メソッドで何が起こっているのでしょうか? 興味深いのは、元の画像自体にある程度の透明度がある場合、その透明度が尊重されることです。次に例を示します。

ここに画像の説明を入力

私は自分でそれを理解することはできません。ビットマップをソースおよびマスクとしてのみ機能するため、ビットマップを事前に作成するのではなく、onDrawで実行できるようにしたいと思います。グラデーションや単色などの他のドローアブルで実行できるようにしたいのですが、その場合、幅と高さが設定されていません。

4

3 に答える 3

28

すべてのスタックオーバーフローの投稿を調査した後、黒い境界線のないマスキングを作成するための完璧な組み合わせを見つけました。それは私の目的に非常に適しています。

現在、1 つの通常の画像とマスキング画像 (透過性のある png) を使用してドラッグ可能なビューを作成しているため、onDraw 関数をオーバーライドする必要があります。

private Bitmap mImage = ...;
private Bitmap mMask = ...;  // png mask with transparency
private int mPosX = 0;
private int mPosY = 0;

private final Paint maskPaint;
private final Paint imagePaint;

public CustomView (final Context context) {
    maskPaint = new Paint();
    maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

    imagePaint = new Paint();
    imagePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OVER));
}

/* TODO
 if you have more constructors, make sure you initialize maskPaint and imagePaint
 Declaring these as final means that all your constructors have to initialize them.
 Failure to do so = your code won't compile.
*/

@Override
public void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    canvas.save();      
    canvas.drawBitmap(mMask, 0, 0, maskPaint);
    canvas.drawBitmap(mImage, mPosX, mPosY, imagePaint);
    canvas.restore();
}
于 2013-07-05T11:23:28.627 に答える
2

私自身の質問に答えます。Xfermode は意図したとおりに機能していました。ペイントにより、キャンバスの結果が透明になりました (これは、ウィンドウ アクティビティで使用されるキャンバスでした)。キャンバス自体が透明に設定されていたため、ウィンドウにはその背後にあるもの、つまり黒い背景が表示されていました。

それを適切に行うには、アルファ マスクの結果を保持するために新しいビットマップを作成する必要があります。すべてのタイプのドローアブルを考慮してコードを更新しました。

于 2013-02-12T18:56:27.133 に答える
0

このコードで適用:

 mask_over = BitmapFactory.decodeResource(
            getResources(), mask_over1[0]);
    icon = Bitmap.createScaledBitmap(icon, screenwidth, screenwidth, false);
    mask_over = Bitmap.createScaledBitmap(mask_over, screenwidth, screenwidth, false);
             back_img=createBitmap_ScriptIntrinsicBlur(Bitmap.createScaledBitmap(cropview.croppedImage, screenwidth, screenwidth, false),25.0f);
    LinearLayout.LayoutParams layoutParams111 = new LinearLayout.LayoutParams(screenwidth, screenwidth);
于 2017-09-15T04:26:52.600 に答える