2013-02-10 9 views
29

私はここからコードを試しました:Creating an ImageView with a mask。 Iオリジナルマスクとして、以下の画像を使用しています:Android ImageViewでマスクを適用するには?

enter image description hereenter image description here

はしかし、私が得る結果がこれです:ウィンドウの背景が黒ではないことを

enter image description here

ますが、ホロの光(銀河のネクサスには非常に淡いグレーのように見えますが、完全に白くはありません)。 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); 

私が期待した結果を得る:

enter image description here

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

ImageViewのonDrawメソッドでは、ウィンドウの背景を表示する代わりに、この黒い背景を作成するにはどうしますか?

enter image description here

私は自分でそれを把握することはできません。どのような興味深いのは、元の画像自体は、いくつかの透明性を持っている場合は、その透明性は、例えば、尊敬されていることです。ビットマップをソースとマスクとしてのみ機能するので、ビットマップを事前に作成するのではなく、むしろonDrawでそれを行うことができます。私はグラデーションやソリッドカラーのような他のdrawableでそれをやりたいと思っていますが、幅と高さは設定されていません。

+1

をここで更新があります。 http://stackoverflow.com/questions/3467334/erase-bitmap-parts-using-porterduff-modeを読んだあと、ビットマップ設定をARGB_8888の代わりにRGB_565に設定すると、同じ動作を再現できます。また、onDrawメソッドで渡されるキャンバスまで問題を絞り込むこともできます。 onDrawキャンバスを使用すると、黒い境界線が表示されます。onDrawに渡されたキャンバスにはビットマップが関連付けられていないため、ネイティブに透明性をサポートしていない可能性があります。私が知ったもう一つのことは、リストビューがスクロールしている間に黒い枠線が消えることです。 – AngraX

+1

これを読んだ後、http://stackoverflow.com/questions/5231260/android-shader-behave-different-in-ondrawcanvas-and-new-canvasbitmapバグは実際には私がウィンドウキャンバスのピクセルを透明にしているようですonDraw()に渡されたキャンバスに適用すれば窓の後ろには黒い背景があります。私は別のDSTモードが見つからない限り、一時的なビットマップを使用してレンダリングするしかありません。 – AngraX

+0

私は画像と1つの画像ビューと2番目のwih黒マスクを持っているのと同様の機能を実装しようとしていますが、触ってみればサークルの裏側の画像ビューを表示する必要があります。 – ViVekH

答えて

25

私は、すべてのstackoverflow投稿を調べた後、黒い枠線なしにマスキングを作成するための完璧な組み合わせを見つけました。それは私の目的によく合っています。

現在、私は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(); 
} 
+1

ねえ。 xferモードに関するいくつかの記事を読んだ後にロジックをチェックしたところ、あなたのソリューションはかなりうまくいくと思います。正式な答えとしてそれを受け入れる。 xferモードの詳細については、http://www.piwai.info/transparent-jpegs-done-right/およびhttp://ssp.impulsetrain.com/2013-03-17_Porter_Duff_Compositing_and_Blend_Modes.htmlを参照してください。 – AngraX

+0

アルゴリズム上記がうまくいかなかった場合は、maskPaintのsetXfermodeをPorterDuff.Mode.DST_OUTに変更してください。 – morph85

+0

これは、CLEARとDST_OUTの両方のモードで動作します。興味深いことに、私がxferモードについて読んだドキュメンテーションから、CLEARはすべてをクリアするはずですが、AndroidではDST_OUTとまったく同じように動作します。ところで、私はxferモードの代わりにシェーダを使用していますので、描画パスを少なくして、赤から緑にオーバードロップします:) – AngraX

2

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

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

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); 
関連する問題