本來兩篇文章要寫到一篇裏的,但是太長了只能分兩篇文章
我們繼續接着上篇文章
第一:PorterDuff.Mode.DST_IN效果
保留覆蓋源像素的目標像素,丟棄其餘的源像素和目標像素。
我們看下兩張圖片
第一張圖片是一張有圓角的白素圖片
package com.dn_alan.myapplication.xfermode;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.View;
import com.dn_alan.myapplication.R;
public class RoundImageView_DSTIN extends View {
private Paint mBitPaint;
private Bitmap BmpDST,BmpSRC;
public RoundImageView_DSTIN(Context context, AttributeSet attrs) {
super(context, attrs);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
mBitPaint = new Paint();
//目標像素 頭像
BmpDST = BitmapFactory.decodeResource(getResources(), R.drawable.xyjy6,null);
//原像素
BmpSRC = BitmapFactory.decodeResource(getResources(),R.drawable.shade,null);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// saveLayer可以爲canvas創建一個新的透明圖層,在新的圖層上繪製,並不會直接繪製到屏幕上,而會在restore之後,繪製到上一個圖層或者屏幕上(如果沒有上一個圖層)。
// 爲什麼會需要一個新的圖層,例如在處理xfermode的時候,原canvas上的圖(包括背景)會影響src和dst的合成,這個時候,使用一個新的透明圖層是一個很好的選擇。
// 又例如需要當前繪製的圖形都帶有一定的透明度,那麼創建一個帶有透明度的圖層,也是一個方便的選擇。
int layerId = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
//目標像素--頭像
canvas.drawBitmap(BmpDST,0,0,mBitPaint);
mBitPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
//源像素--白色背景
canvas.drawBitmap(BmpSRC,0,0,mBitPaint);
//清除混合模式
mBitPaint.setXfermode(null);
canvas.restoreToCount(layerId);
}
}
看下效果
水中倒影效果
第一張圖片是一張名叫invert_shade的透明圖片
第二張圖片是一張名叫xyjy6的美女圖片
package com.dn_alan.myapplication.xfermode;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.View;
import com.dn_alan.myapplication.R;
public class InvertedImageView_DSTIN extends View {
private Paint mBitPaint;
private Bitmap BmpDST,BmpSRC,BmpRevert;
public InvertedImageView_DSTIN(Context context, AttributeSet attrs) {
super(context, attrs);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
mBitPaint = new Paint();
BmpDST = BitmapFactory.decodeResource(getResources(), R.drawable.xyjy6,null);
BmpSRC = BitmapFactory.decodeResource(getResources(),R.drawable.invert_shade,null);
Matrix matrix = new Matrix();
// 設置Matrix進行縮放,sx,sy控制X,Y方向上的縮放比例;
matrix.setScale(1F, -1F);
// 生成倒影圖
BmpRevert = Bitmap.createBitmap(BmpDST, 0, 0, BmpDST.getWidth(), BmpDST.getHeight(), matrix, true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(BmpDST,0,0,mBitPaint);
//再畫出倒影
int layerId = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
canvas.translate(0,BmpSRC.getHeight());
canvas.drawBitmap(BmpRevert,0,0,mBitPaint);
//PorterDuff.Mode.DST_IN:在兩者相交的地方繪製目標圖像,並且繪製的效果會受到源圖像對應地方透明度的影響
mBitPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
canvas.drawBitmap(BmpSRC,0,0,mBitPaint);
//清除混合模式
mBitPaint.setXfermode(null);
canvas.restoreToCount(layerId);
}
}
看下效果圖
我們可以看到,由於透明度的影響,倒影圖片與原圖是有區別的。
水波紋效果
原圖一 名叫wav的圖片
原圖二 名叫circle_shape的圖片
package com.dn_alan.myapplication.xfermode;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;
import com.dn_alan.myapplication.R;
public class IrregularWaveView_DSTIN extends View {
private Paint mPaint;
private int mItemWaveLength = 0;
private int dx=0;
private Bitmap BmpSRC,BmpDST;
public IrregularWaveView_DSTIN(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
BmpDST = BitmapFactory.decodeResource(getResources(), R.drawable.wav,null);
BmpSRC = BitmapFactory.decodeResource(getResources(),R.drawable.circle_shape,null);
mItemWaveLength = BmpDST.getWidth();
startAnim();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//先畫上圓形
canvas.drawBitmap(BmpSRC,0,0,mPaint);
//再畫上結果
int layerId = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
canvas.drawBitmap(BmpDST,new Rect(dx,0,dx+BmpSRC.getWidth(),BmpSRC.getHeight()),new Rect(0,0,BmpSRC.getWidth(),BmpSRC.getHeight()),mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
canvas.drawBitmap(BmpSRC,0,0,mPaint);
//清除混合模式
mPaint.setXfermode(null);
canvas.restoreToCount(layerId);
}
public void startAnim(){
ValueAnimator animator = ValueAnimator.ofInt(0,mItemWaveLength);
animator.setDuration(4000);
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.setInterpolator(new LinearInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
dx = (int)animation.getAnimatedValue();
postInvalidate();
}
});
animator.start();
}
}
看下效果,是波動的效果,藍色圖片自左向右在圓白色圖片中移動。
心電圖效果
明爲heartmap的圖片
看下代碼
package com.dn_alan.myapplication.xfermode;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;
import com.dn_alan.myapplication.R;
public class HeartMap_DSTIN extends View {
private Paint mPaint;
private int mItemWaveLength = 0;
private int dx=0;
private Bitmap BmpSRC,BmpDST;
public HeartMap_DSTIN(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mPaint.setColor(Color.RED);
BmpDST = BitmapFactory.decodeResource(getResources(), R.drawable.heartmap,null);
// ARGB_8888: 默認的選項,每像素佔用4字節,ARGB分別佔8位,支持1600萬種顏色,質量最高,當然內存佔用也高。
BmpSRC = Bitmap.createBitmap(BmpDST.getWidth(), BmpDST.getHeight(), Bitmap.Config.ARGB_8888);
mItemWaveLength = BmpDST.getWidth();
startAnim();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Canvas c = new Canvas(BmpSRC);
//清空bitmap
c.drawColor(Color.RED, PorterDuff.Mode.CLEAR);
//畫上矩形
c.drawRect(BmpDST.getWidth() - dx,0,BmpDST.getWidth(),BmpDST.getHeight(),mPaint);
//模式合成
int layerId = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
canvas.drawBitmap(BmpDST,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
canvas.drawBitmap(BmpSRC,0,0,mPaint);
//清除混合模式
mPaint.setXfermode(null);
canvas.restoreToCount(layerId);
}
public void startAnim(){
ValueAnimator animator = ValueAnimator.ofInt(0,mItemWaveLength);
animator.setDuration(6000);
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.setInterpolator(new LinearInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
dx = (int)animation.getAnimatedValue();
postInvalidate();
}
});
animator.start();
}
}
還有另外一種寫法
package com.dn_alan.myapplication.xfermode;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;
import com.dn_alan.myapplication.R;
public class HeartMap_DSTIN extends View {
private Paint mPaint;
private int mItemWaveLength = 0;
private int dx=0;
private Bitmap BmpSRC,BmpDST;
public HeartMap_DSTIN(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mPaint.setColor(Color.RED);
BmpDST = BitmapFactory.decodeResource(getResources(), R.drawable.heartmap,null);
// ARGB_8888: 默認的選項,每像素佔用4字節,ARGB分別佔8位,支持1600萬種顏色,質量最高,當然內存佔用也高。
BmpSRC = Bitmap.createBitmap(BmpDST.getWidth(), BmpDST.getHeight(), Bitmap.Config.ARGB_8888);
mItemWaveLength = BmpDST.getWidth();
startAnim();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//模式合成
int layerId = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
canvas.drawBitmap(BmpDST,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
canvas.drawBitmap(BmpSRC,0-dx,0,mPaint);
//清除混合模式
mPaint.setXfermode(null);
canvas.restoreToCount(layerId);
}
public void startAnim(){
ValueAnimator animator = ValueAnimator.ofInt(0,mItemWaveLength);
animator.setDuration(6000);
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.setInterpolator(new LinearInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
dx = (int)animation.getAnimatedValue();
postInvalidate();
}
});
animator.start();
}
}
效果是一種動畫的效果,心電圖從左往右依次出現
SRC模式
效果一:圓角
先看兩張要合成的圖片
代碼
package com.dn_alan.myapplication.xfermode;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.View;
import com.dn_alan.myapplication.R;
public class RoundImageView_SRCIN extends View {
private Paint mBitPaint;
private Bitmap BmpDST,BmpSRC;
public RoundImageView_SRCIN(Context context, AttributeSet attrs) {
super(context, attrs);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
mBitPaint = new Paint();
BmpDST = BitmapFactory.decodeResource(getResources(), R.drawable.shade,null);
BmpSRC = BitmapFactory.decodeResource(getResources(),R.drawable.xyjy6,null);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//將繪製操作保存到新的圖層,因爲圖像合成是很昂貴的操作,將用到硬件加速,這裏將圖像合成的處理放到離屏緩存中進行
int layerId = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
//目標圖像------白色背景
canvas.drawBitmap(BmpDST,0,0,mBitPaint);
// 在兩者相交的地方繪製源圖像,並且繪製的效果會受到目標圖像對應地方透明度的影響
mBitPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
//源圖像-----美女頭像
canvas.drawBitmap(BmpSRC,0,0,mBitPaint);
mBitPaint.setXfermode(null);
canvas.restoreToCount(layerId);
}
}
看下效果
效果二:倒影
代碼
package com.dn_alan.myapplication.xfermode;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.View;
import com.dn_alan.myapplication.R;
public class InvertedImageView_SRCIN extends View {
private Paint mBitPaint;
private Bitmap BmpDST,BmpSRC,BmpRevert;
public InvertedImageView_SRCIN(Context context, AttributeSet attrs) {
super(context, attrs);
//關閉硬件加速
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
mBitPaint = new Paint();
BmpDST = BitmapFactory.decodeResource(getResources(), R.drawable.invert_shade,null);
BmpSRC = BitmapFactory.decodeResource(getResources(),R.drawable.xyjy6,null);
Matrix matrix = new Matrix();
matrix.setScale(1F, -1F);
// 生成倒影圖
BmpRevert = Bitmap.createBitmap(BmpSRC, 0, 0, BmpSRC.getWidth(), BmpSRC.getHeight(), matrix, true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//美女圖像
canvas.drawBitmap(BmpSRC,0,0,mBitPaint);
//再畫出倒影
int layerId = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
canvas.translate(0,BmpSRC.getHeight());
//目標圖像
canvas.drawBitmap(BmpDST,0,0,mBitPaint);
// 在兩者相交的地方繪製源圖像,並且繪製的效果會受到目標圖像對應地方透明度的影響
mBitPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
//源圖像
canvas.drawBitmap(BmpRevert,0,0,mBitPaint);
mBitPaint.setXfermode(null);
canvas.restoreToCount(layerId);
}
}
效果
效果三,橡皮擦
代碼
package com.dn_alan.myapplication.xfermode;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.dn_alan.myapplication.R;
public class EraserView_SRCOUT extends View {
private Paint mBitPaint;
private Bitmap BmpDST,BmpSRC;
private Path mPath;
private float mPreX,mPreY;
public EraserView_SRCOUT(Context context, AttributeSet attrs) {
super(context, attrs);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
mBitPaint = new Paint();
mBitPaint.setColor(Color.BLUE);
mBitPaint.setStyle(Paint.Style.STROKE);
mBitPaint.setStrokeWidth(45);
BmpSRC = BitmapFactory.decodeResource(getResources(), R.drawable.xyjy6,null);
BmpDST = Bitmap.createBitmap(BmpSRC.getWidth(), BmpSRC.getHeight(), Bitmap.Config.ARGB_8888);
mPath = new Path();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int layerId = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
//先把手指軌跡畫到目標Bitmap上
canvas.drawPath(mPath,mBitPaint);
//然後把目標圖像畫到畫布上
canvas.drawBitmap(BmpDST,0,0,mBitPaint);
//在不相交的地方繪製源圖像,表示如果相交處的目標色的alpha是完全不透明的,
// 這時候源圖像會完全被過濾掉,否則會受到相交處目標色 alpha 影響,呈現出對應色值。
mBitPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
canvas.drawBitmap(BmpSRC,0,0,mBitPaint);
mBitPaint.setXfermode(null);
canvas.restoreToCount(layerId);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
mPath.moveTo(event.getX(),event.getY());
mPreX = event.getX();
mPreY = event.getY();
return true;
case MotionEvent.ACTION_MOVE:
float endX = (mPreX+event.getX())/2;
float endY = (mPreY+event.getY())/2;
mPath.quadTo(mPreX,mPreY,endX,endY);
mPreX = event.getX();
mPreY =event.getY();
break;
case MotionEvent.ACTION_UP:
break;
}
postInvalidate();
return super.onTouchEvent(event);
}
}
另一種寫法
package com.dn_alan.myapplication.xfermode;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.dn_alan.myapplication.R;
public class EraserView_SRCOUT extends View {
private Paint mBitPaint;
private Bitmap BmpDST,BmpSRC;
private Path mPath;
private float mPreX,mPreY;
public EraserView_SRCOUT(Context context, AttributeSet attrs) {
super(context, attrs);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
mBitPaint = new Paint();
mBitPaint.setColor(Color.BLUE);
mBitPaint.setStyle(Paint.Style.STROKE);
mBitPaint.setStrokeWidth(45);
BmpSRC = BitmapFactory.decodeResource(getResources(), R.drawable.xyjy6,null);
BmpDST = Bitmap.createBitmap(BmpSRC.getWidth(), BmpSRC.getHeight(), Bitmap.Config.ARGB_8888);
mPath = new Path();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int layerId = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
//先把手指軌跡畫到目標Bitmap上
Canvas c = new Canvas(BmpDST);
c.drawPath(mPath,mBitPaint);
//然後把目標圖像畫到畫布上
canvas.drawBitmap(BmpDST,0,0,mBitPaint);
//在不相交的地方繪製源圖像,表示如果相交處的目標色的alpha是完全不透明的,
// 這時候源圖像會完全被過濾掉,否則會受到相交處目標色 alpha 影響,呈現出對應色值。
mBitPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
canvas.drawBitmap(BmpSRC,0,0,mBitPaint);
mBitPaint.setXfermode(null);
canvas.restoreToCount(layerId);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
mPath.moveTo(event.getX(),event.getY());
mPreX = event.getX();
mPreY = event.getY();
return true;
case MotionEvent.ACTION_MOVE:
float endX = (mPreX+event.getX())/2;
float endY = (mPreY+event.getY())/2;
mPath.quadTo(mPreX,mPreY,endX,endY);
mPreX = event.getX();
mPreY =event.getY();
break;
case MotionEvent.ACTION_UP:
break;
}
postInvalidate();
return super.onTouchEvent(event);
}
}
第一種寫法效果圖
第二種寫法效果圖
效果4:刮刮樂效果
代碼
package com.dn_alan.myapplication.xfermode;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.dn_alan.myapplication.R;
public class GuaGuaCardView_SRCOUT extends View {
private Paint mBitPaint;
private Bitmap BmpDST,BmpSRC,BmpText;
private Path mPath;
private float mPreX,mPreY;
public GuaGuaCardView_SRCOUT(Context context, AttributeSet attrs) {
super(context, attrs);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
mBitPaint = new Paint();
mBitPaint.setColor(Color.RED);
mBitPaint.setStyle(Paint.Style.STROKE);
mBitPaint.setStrokeWidth(45);
BmpText = BitmapFactory.decodeResource(getResources(), R.drawable.guaguaka_text1,null);
BmpSRC = BitmapFactory.decodeResource(getResources(),R.drawable.guaguaka,null);
BmpDST = Bitmap.createBitmap(BmpSRC.getWidth(), BmpSRC.getHeight(), Bitmap.Config.ARGB_8888);
mPath = new Path();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(BmpText,0,0,mBitPaint);
int layerId = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
//先把手指軌跡畫到目標Bitmap上
Canvas c = new Canvas(BmpDST);
c.drawPath(mPath,mBitPaint);
//然後把目標圖像畫到畫布上
canvas.drawBitmap(BmpDST,0,0,mBitPaint);
//計算源圖像區域
mBitPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
canvas.drawBitmap(BmpSRC,0,0,mBitPaint);
mBitPaint.setXfermode(null);
canvas.restoreToCount(layerId);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
mPath.moveTo(event.getX(),event.getY());
mPreX = event.getX();
mPreY = event.getY();
return true;
case MotionEvent.ACTION_MOVE:
float endX = (mPreX+event.getX())/2;
float endY = (mPreY+event.getY())/2;
mPath.quadTo(mPreX,mPreY,endX,endY);
mPreX = event.getX();
mPreY =event.getY();
break;
case MotionEvent.ACTION_UP:
break;
}
postInvalidate();
return super.onTouchEvent(event);
}
}
效果圖
效果5圓角
先看圖
看源碼
package com.dn_alan.myapplication.xfermode;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.View;
import com.dn_alan.myapplication.R;
public class RoundImageView_SRCATOP extends View {
private Paint mBitPaint;
private Bitmap BmpDST,BmpSRC;
public RoundImageView_SRCATOP(Context context, AttributeSet attrs) {
super(context, attrs);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
mBitPaint = new Paint();
BmpDST = BitmapFactory.decodeResource(getResources(), R.drawable.shade,null);
BmpSRC = BitmapFactory.decodeResource(getResources(),R.drawable.xyjy6,null);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int layerId = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
//目標圖片,白色背景
canvas.drawBitmap(BmpDST,0,0,mBitPaint);
//源圖像和目標圖像相交處繪製源圖像,不相交的地方繪製目標圖像,
// 並且相交處的效果會受到源圖像和目標圖像alpha的影響
mBitPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
//源圖片,美女頭像
canvas.drawBitmap(BmpSRC,0,0,mBitPaint);
mBitPaint.setXfermode(null);
canvas.restoreToCount(layerId);
}
}
看效果圖
效果圖6
先看兩張圖
看代碼
package com.dn_alan.myapplication.xfermode;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.View;
import com.dn_alan.myapplication.R;
public class LightBookView_LIGHTEN extends View {
private Paint mBitPaint;
private Bitmap BmpDST,BmpSRC;
public LightBookView_LIGHTEN(Context context, AttributeSet attrs) {
super(context, attrs);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
mBitPaint = new Paint();
BmpDST = BitmapFactory.decodeResource(getResources(), R.drawable.book_bg,null);
BmpSRC = BitmapFactory.decodeResource(getResources(),R.drawable.book_light,null);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int layerId = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
//目標
canvas.drawBitmap(BmpDST,0,0,mBitPaint);
/**
* DARKEN 該模式處理過後,會感覺效果變暗,即進行對應像素的比較,取較暗值,如果色值相同則進行混合;
* 從算法上看,alpha值變大,色值上如果都不透明則取較暗值,非完全不透明情況下使用上面算法進行計算,
* 受到源圖和目標圖對應色值和alpha值影響。
* LIGHTEN
* 可以和 DARKEN 對比起來看,DARKEN 的目的是變暗,LIGHTEN 的目的則是變亮,如果在均完全不透明的情況下,
* 色值取源色值和目標色值中的較大值,否則按上面算法進行計算。
*/
mBitPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN));
//源
canvas.drawBitmap(BmpSRC,0,0,mBitPaint);
mBitPaint.setXfermode(null);
canvas.restoreToCount(layerId);
}
}
各自混合效果
package com.dn_alan.myapplication.xfermode;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.View;
import com.dn_alan.myapplication.R;
public class TwitterView_MULTIPLY extends View {
private Paint mBitPaint;
private Bitmap BmpDST,BmpSRC;
public TwitterView_MULTIPLY(Context context, AttributeSet attrs) {
super(context, attrs);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
mBitPaint = new Paint();
//目標圖像
BmpDST = BitmapFactory.decodeResource(getResources(), R.drawable.twiter_bg,null);
//原圖像
BmpSRC = BitmapFactory.decodeResource(getResources(),R.drawable.twiter_light,null);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int layerId = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
canvas.drawBitmap(BmpDST,0,0,mBitPaint);
// 解釋一: [Sa * Da, Sc * Dc],正片疊底,即查看每個通道中的顏色信息,並將基色與混合色複合。
// 結果色總是較暗的顏色,任何顏色與黑色複合產生黑色,任何顏色與白色複合保持不變,
// 當用黑色或白色以外的顏色繪畫時,繪畫工具繪製的連續描邊產生逐漸變暗的顏色。
//解釋二:正片疊底,源圖像素顏色值乘以目標圖像素顏色值除以255得到混合後圖像像素顏色值
mBitPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
canvas.drawBitmap(BmpSRC,0,0,mBitPaint);
mBitPaint.setXfermode(null);
canvas.restoreToCount(layerId);
}
}