關於Xfermode的介紹和用處(遮罩圖層,圓形圖片)
1.關於Xfermode類
從上面看出Xfermode有三個子類:AvoidXfermode,PixelXorXfermode,PoterDuffXfermode。它們分別表示:
AvoidXfermode:在繪圖時,要麼繪製在最頂層,要麼繪製在除最頂層以外的地方。
PixelXorXfermode:這種轉換不遵循自左乘的約定,因此這種模式總返回不透明的顏色(alpha=255),由此,對於混合顏色操作是沒有用的。
PoterDuffXfermode:可以使用影象合成的任何一條PoterDuff模式。
注意:只有當一個Xfermode被分配給一個Paint時,使用Paint繪製Xfermode才有效。
2.PoterDuffXfemode
關於PoterDuff的所有Mode的效果圖如下:
16種模式表示的意思分別是:
PoterDuff.Mode.CLEAR:繪製的圖不會提交到畫布上
PoterDuff.Mode.SRC:只顯示繪製的上層圖
PoterDuff.Mode.DST:只顯示繪製的下層圖
PoterDuff.Mode.SRC_OVER:繪製的上層圖和下層圖都顯示,但上層圖會覆蓋下層圖
PoterDuff.Mode.DST_OVER:繪製的上層圖和下層圖都顯示,但下層圖會覆蓋上層圖
PoterDuff.Mode.SRC_IN:取繪製的圖的交集部分,顯示上層
PoterDuff.Mode.DST_IN:取繪製的圖的交集部分,顯示下層
PoterDuff.Mode.SRC_OUT:取繪製的圖的非交集部分,顯示上層
PoterDuff.Mode.DST_OUT:取繪製的圖的非交集部分,顯示下層
PoterDuff.Mode.SRC_ATOP:取繪製的圖的下層部分,和上層與下層的交集部分
PoterDuff.Mode.DST_ATOP:取繪製的圖的上層部分,和下層與上層的交集部分
PoterDuff.Mode.XOR:取繪製的圖的上層和下層的非交集部分
PoterDuff.Mode.DARKEN:取繪製的圖的全集,上層和下層交集部分加深
PoterDuff.Mode.LIGHTEN:取繪製的圖的全集,上層和下層交集部分點亮
PoterDuff.Mode.MULTIPLY:取繪製的圖的交集部分並且交集部分顏色加深
PoterDuff.Mode.SCREEN:取繪製的圖的全集,上層和下層的交集部分透明
附加:關於圖的示例來自於SDK中的Sample,在我電腦上的路勁為:\sdk\samples\android-16\ApiDemos\src\com\example\android\apis\graphics\Xfermode.java
3.運用示例:
3.1 拍照遮罩
先看效果圖:
總體為一個FramLayout,遮罩層在相機預覽的上面,為了實現這個效果,最核心的就是在畫遮罩層的時候,讓中間矩形這塊區域不可見。那麼從上面分析的PoterDuff.Mode中,很明顯CLEAR模式下,可以實現上面的效果。
因此,只需要兩步,第一步畫一個整體的遮罩圖(下層圖),第二步畫一個不顯示的矩形圖(上層圖):
設定畫矩形區域的畫筆: mRectPaint.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.CLEAR));
在onDraw()方法中,先畫下層圖: canvas.drawRect(0, 0, mScreenWidth, mScreenHeight, mAreaPaint);,再畫上層圖:canvas.drawRect(mVisibleRect, mRectPaint);
因此,這樣就可以實現上面的顯示效果。
3.2 圓形圖片
先看效果圖:
思路:在PoterDuff.Mode的SRC_IN下,畫一個圓形的下層圖,再把目標圖片畫在上面,那麼這樣最後的結果就是圓形圖片(取繪製的圖的交集部分,顯示上層)。
程式碼示例:
public static Bitmap getRoundedCornerBitmap(Bitmap srcBitmap) {
int width = srcBitmap.getWidth();
int height = srcBitmap.getHeight();
int radius = 0;
if (width <= height) {
radius = width / 2;
} else {
radius = height / 2;
}
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setDither(true);
paint.setColor(Color.WHITE);
Rect rect = new Rect(0, 0, 2 * radius, 2 * radius);
RectF rectF = new RectF(rect);
Bitmap desBitmap = Bitmap.createBitmap(2 * radius, 2 * radius, Bitmap.Config.ARGB_4444);
Canvas canvas = new Canvas(desBitmap);
//除去抗鋸齒
canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
canvas.drawARGB(0, 0, 0, 0);
//繪製下層圖
canvas.drawRoundRect(rectF, radius, radius, paint);
// 設定PorterDuffXfermode模式,取繪製的圖的交集部分,顯示上層
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
//繪製上層圖
canvas.drawBitmap(srcBitmap, rect, rect, paint);
return desBitmap;
}
總結:關於Xfermode的運用還很多,上面遮罩圖層和圓形圖片只是兩種比較常見的運用,從中也可以看出其影象合成的強大所在。另外關於PorterDuff的由來是有兩個人名的組合:Thomas Porter 和 Tom Duff。