Paint setXfermode混合像素

来源:互联网 发布:红帽linux下配置samba 编辑:程序博客网 时间:2024/05/19 20:19
一、Xfermode


通过使用Xfermode将绘制的图形的像素和Canvas上对应位置的像素按照一定的规则进行混合,形成新的像素,再更新到Canvas中形成最终的图形


使用的时候都是通过Paint.setXfermode




我们一个像素的颜色都是由四个分量组成,即ARGB,A表示的是我们Alpha值,RGB表示的是颜色


S表示的是原像素,原像素的值表示[Sa,Sc] Sa表示的就是源像素的Alpha值,Sc表示源像素的颜色值


D表示的是目标像素,目标像素的值表示[Da,Dc] Da表示的就是目标像素的Alpha值


蓝色矩形表示的是原图片,黄色圆表示的是目标图片


二、混合模式分类


1、SRC类
----优先显示的是源图片


SRC [Sa, Sc]  ---- 处理图片相交区域时,总是显示的是原图片


SRC_IN [Sa * Da, Sc * Da] ---- 处理图片相交区域时,受到目标图片的Alpha值影响
当我们的目标图片为空白像素的时候,目标图片也会变成空白
简单的来说就是用目标图片的透明度来改变源图片的透明度和饱和度,当目标图片的透明度为0时,源图片就不会显示
 示例:圆角头像 、倒影图片




SRC_OUT [Sa * (1 - Da), Sc * (1 - Da)] --- 同SRC_IN类似  (1 - Da)
用我们目标图片的透明度的补值来改变源图片的透明度和饱和度,当目标图片的透明度为不透明时,源图片就不会显示
示例:橡皮擦效果
目标图片 --- 手势的轨迹
源图片 --- 擦除的图片

刮刮卡效果?----作业




SRC_ATOP [Da, Sc * Da + (1 - Sa) * Dc]
---- 当透明度为100%和0%时,SRC_IN 和 SRC_ATOP是通用的
    当透明度不为上述的两个值时,SRC_ATOP  比 SRC_IN  源图像的饱和度会增加,变得更亮一些
 
示例:用SRC_ATOP来实现  圆角头像 、倒影图片 对比一下SRC_IN  


2、DST类
----优先显示的是目标图片

DST_IN [Sa * Da, Sa * Dc] ----- 对比一下SRC_IN,正好和我们SRC_IN想法,在相交的时候以源图片的透明度来改变目标图片的透明度和饱和度
当源图片的透明度为0的时候,目标图片完全不显示


示例:心电图效果,不规则水波纹效果,当然也可以做SRC_IN 的效果(注意选择谁为源图片,谁为目标图片)


心电图效果-
目标图片 ---心电图
源图片 ---- 不透明的图 就是通过改变透明图片的不透明区域的宽度,来实现心电图的动画效果


3、其他的叠加效果


MULTIPLY[Sa * Da, Sc * Dc] --- 

应用:可以把图片的轮廓取出来


LIGHTEN -- 变亮

书架 头顶灯光变亮效果

//画出这16种yang's

import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.PorterDuff;import android.graphics.PorterDuffXfermode;import android.graphics.Xfermode;import android.os.Build;import android.util.AttributeSet;import android.view.View;/** * Created by lin on 2017/5/11. */public class MyView extends View {    Paint mPaint;    float mItemSize = 0;    float mItemHorizontalOffset = 0;    float mItemVerticalOffset = 0;    float mCircleRadius = 0;    float mRectSize = 0;    int mCircleColor = 0xffffcc44;//黄色    int mRectColor = 0xff66aaff;//蓝色    float mTextSize = 25;    private static final Xfermode[] sModes = {            new PorterDuffXfermode(PorterDuff.Mode.CLEAR),            new PorterDuffXfermode(PorterDuff.Mode.SRC),            new PorterDuffXfermode(PorterDuff.Mode.DST),            new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER),            new PorterDuffXfermode(PorterDuff.Mode.DST_OVER),            new PorterDuffXfermode(PorterDuff.Mode.SRC_IN),            new PorterDuffXfermode(PorterDuff.Mode.DST_IN),            new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT),            new PorterDuffXfermode(PorterDuff.Mode.DST_OUT),            new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP),            new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP),            new PorterDuffXfermode(PorterDuff.Mode.XOR),            new PorterDuffXfermode(PorterDuff.Mode.DARKEN),            new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN),            new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY),            new PorterDuffXfermode(PorterDuff.Mode.SCREEN)    };    private static final String[] sLabels = {            "Clear", "Src", "Dst", "SrcOver",            "DstOver", "SrcIn", "DstIn", "SrcOut",            "DstOut", "SrcATop", "DstATop", "Xor",            "Darken", "Lighten", "Multiply", "Screen"    };    public MyView(Context context) {        super(context);        init(null, 0);    }    public MyView(Context context, AttributeSet attrs) {        super(context, attrs);        init(attrs, 0);    }    public MyView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        init(attrs, defStyle);    }    private void init(AttributeSet attrs, int defStyle) {        if(Build.VERSION.SDK_INT >= 11){            setLayerType(LAYER_TYPE_SOFTWARE, null);        }        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mPaint.setTextSize(mTextSize);        mPaint.setTextAlign(Paint.Align.CENTER);        mPaint.setStrokeWidth(2);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        //设置背景色        //canvas.drawARGB(255, 139, 197, 186);        int canvasWidth = canvas.getWidth();        int canvasHeight = canvas.getHeight();        for(int row = 0; row < 4; row++){            for(int column = 0; column < 4; column++){                canvas.save();                int layer = canvas.saveLayer(0, 0, canvasWidth, canvasHeight, null, Canvas.ALL_SAVE_FLAG);                mPaint.setXfermode(null);                int index = row * 4 + column;                float translateX = (mItemSize + mItemHorizontalOffset) * column;                float translateY = (mItemSize + mItemVerticalOffset) * row;                canvas.translate(translateX, translateY);                //画文字                String text = sLabels[index];                mPaint.setColor(Color.BLACK);                float textXOffset = mItemSize / 2;                float textYOffset = mTextSize + (mItemVerticalOffset - mTextSize) / 2;                canvas.drawText(text, textXOffset, textYOffset, mPaint);                canvas.translate(0, mItemVerticalOffset);                //画边框                mPaint.setStyle(Paint.Style.STROKE);                mPaint.setColor(0xff000000);                canvas.drawRect(2, 2, mItemSize - 2, mItemSize - 2, mPaint);                mPaint.setStyle(Paint.Style.FILL);                //画圆                mPaint.setColor(mCircleColor);                float left = mCircleRadius + 3;                float top = mCircleRadius + 3;                canvas.drawCircle(left, top, mCircleRadius, mPaint);                mPaint.setXfermode(sModes[index]);                //画矩形                mPaint.setColor(mRectColor);                float rectRight = mCircleRadius + mRectSize;                float rectBottom = mCircleRadius + mRectSize;                canvas.drawRect(left, top, rectRight, rectBottom, mPaint);                mPaint.setXfermode(null);                //canvas.restore();                canvas.restoreToCount(layer);            }        }    }    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        mItemSize = w / 4.5f;        mItemHorizontalOffset = mItemSize / 6;        mItemVerticalOffset = mItemSize * 0.426f;        mCircleRadius = mItemSize / 3;        mRectSize = mItemSize * 0.6f;    }}
代码绘制的图片
官网图片