本来两篇文章要写到一篇里的,但是太长了只能分两篇文章
我们继续接着上篇文章
第一: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);
}
}