0917Android基础自定义View(颜色渲染PorterDuff及Xfermode)

颜色渲染

  补充基础知识请点我http://blog.csdn.net/t12x3456/article/details/10432935

颜色渲染实例1

  新建一个类继承View,继承他的俩构造器和onDraw以及onMeasure方法。PorterDuff必须画在bitmap上。步骤:

  • 创建一个位图
//      创建一个宽with高height的新位图,第三个参数传位图配置,这里的配置意思为:每个像素被存储在4个字节中。
        mBitmap=Bitmap.createBitmap(mWith,mHeight, Bitmap.Config.ARGB_8888);
  • 绘制一个由该位图构成的画布(自定义)
//        绘制一个由指定位图构成的画布
        canvasBit=new Canvas(mBitmap);
  • 设置渲染方式
//        可以使用图像合成的16条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互
        PorterDuffXfermode mode=new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER);
        mPaintSrc.setXfermode(mode);
  • 在自定义画布上对位图进行渲染操作,注意是那个画笔调用了setXfermode方法
//        图像渲染只能在bitmap中进行,通过canvasBit对bitmap进行渲染操作
        canvasBit.drawCircle(mWith / 2, mHeight / 2, 250, mPaintDst);
        canvasBit.drawRect(10, 200, mWith/2, mHeight/2, mPaintSrc);
  • 在onDraw中的画布中将已经进行渲染操作的位图画在画布上。
//        将位图放在画布中,在进行了渲染操作的位图放到画布中显示出来。
        canvas.drawBitmap(mBitmap,0,0,null);

该实例的效果图(PorterDuff.Mode.SRC_OVER)

0917Android基础自定义View(颜色渲染PorterDuff及Xfermode)_第1张图片

参考:API中提供的能够进行的16中操作种类(PorterDuff.Mode为枚举类,一共有16个枚举值)
0917Android基础自定义View(颜色渲染PorterDuff及Xfermode)_第2张图片
1.PorterDuff.Mode.CLEAR
所绘制不会提交到画布上。
2.PorterDuff.Mode.SRC
显示上层绘制图片
3.PorterDuff.Mode.DST
显示下层绘制图片
4.PorterDuff.Mode.SRC_OVER
正常绘制显示,上下层绘制叠盖。
5.PorterDuff.Mode.DST_OVER
上下层都显示。下层居上显示。
6.PorterDuff.Mode.SRC_IN
取两层绘制交集。显示上层。
7.PorterDuff.Mode.DST_IN
取两层绘制交集。显示下层。
8.PorterDuff.Mode.SRC_OUT
取上层绘制非交集部分。
9.PorterDuff.Mode.DST_OUT
取下层绘制非交集部分。
10.PorterDuff.Mode.SRC_ATOP
取下层非交集部分与上层交集部分
11.PorterDuff.Mode.DST_ATOP
取上层非交集部分与下层交集部分
12.PorterDuff.Mode.XOR
异或:去除两图层交集部分
13.PorterDuff.Mode.DARKEN
取两图层全部区域,交集部分颜色加深
14.PorterDuff.Mode.LIGHTEN
取两图层全部,点亮交集部分颜色
15.PorterDuff.Mode.MULTIPLY
取两图层交集部分叠加后颜色
16.PorterDuff.Mode.SCREEN
取两图层全部区域,交集部分变为透明色

全部代码

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
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.example.laowang.android0916canvas_.R;

/**
 * Created by Administrator on 2015/9/17.
 */
public class MyBitmapView2 extends View {
    private int mWith;
    private int mHeight;
    private Paint mPaintSrc;
    private Paint mPaintDst;
    private Bitmap mBitmap;
    private Canvas canvasBit;

    public MyBitmapView2(Context context) {
        super(context);
    }

    public MyBitmapView2(Context context, AttributeSet attrs) {
        super(context, attrs);
//        初始化bitmap对象
        mBitmap= BitmapFactory.decodeResource(getResources(), R.mipmap.dogno);
        mPaintSrc=new Paint();
        mPaintDst=new Paint();
        mPaintSrc.setColor(Color.argb(0xff, 0x63, 0xAA, 0xFF));//自定义颜色
        mPaintSrc.setAntiAlias(true);
        mPaintDst.setColor(Color.argb(0xff, 0xFF, 0xCF, 0x42));
        mPaintDst.setAntiAlias(true);
//        可以使用图像合成的16条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互
        PorterDuffXfermode mode=new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER);
        mPaintSrc.setXfermode(mode);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWith = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        mHeight = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(mWith, mHeight);
//      创建一个宽with高height的新位图,第三个参数传位图配置,这里的配置意思为:每个像素被存储在4个字节中。
        mBitmap=Bitmap.createBitmap(mWith,mHeight, Bitmap.Config.ARGB_8888);
//        绘制一个由指定位图构成的画布
        canvasBit=new Canvas(mBitmap);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.GRAY);
//        图像渲染只能在bitmap中进行,通过canvasBit对bitmap进行渲染操作
        canvasBit.drawCircle(mWith / 2, mHeight / 2, 250, mPaintDst);
        canvasBit.drawRect(10, 200, mWith/2, mHeight/2, mPaintSrc);
//        将位图放在画布中,在进行了渲染操作的位图放到画布中显示出来。
        canvas.drawBitmap(mBitmap,0,0,null);
    }
}

颜色渲染实例2

  在实例1的基础上面加以修改,达到这个效果,鼠标按下后拖动将蓝色部分去掉,点击保存照片将照片保存。
  
0917Android基础自定义View(颜色渲染PorterDuff及Xfermode)_第3张图片
  
  首先添加权限

    "android.permission.READ_EXTERNAL_STORAGE"/>
    "android.permission.WRITE_EXTERNAL_STORAGE"/>

  创建一个Bitmap背景对象,在构造器中初始化。

      mBitmapBackground=BitmapFactory.decodeResource(getResources(),R.mipmap.nurse);

  在onMeasure方法中获得他的宽高


        mImageWith = mBitmapBackground.getWidth();
        mImageHeight = mBitmapBackground.getHeight();

  设置画笔移动时的效果!!!!!!

        mPaintDst.setAntiAlias(true);
//        可以使用图像合成的16条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互
        PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.XOR);
        mPaintDst.setXfermode(mode);//mPaintDst加上以后加图片处理,所以后面话圆的时候要用这个画笔

        mPaintDst.setStrokeJoin(Paint.Join.ROUND);//圆角 连接时使用的方式
        mPaintDst.setStrokeCap(Paint.Cap.ROUND);//圆角 覆盖式使用的方式
        mPaintDst.setStyle(Paint.Style.STROKE);//要用上面的方法必须将画笔设置成STROKE或者FILL_AND_STROKE

  将背景图片添加到画布中,通过path画出线条

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
//        添加背景图片,拉伸到屏幕大小
        canvas.drawBitmap(mBitmapBackground, new Rect(0, 0, mImageWith, mImageHeight), new Rect(0, 0, mWith, mHeight), null);
//        图像渲染只能在bitmap中进行,通过canvasBit对bitmap进行渲染操作
//        canvasBit.drawCircle(mWith / 2, mHeight / 2, 250, mPaintDst);

        canvasBit.drawRect(0, 0, mWith, mHeight, mPaintSrc);//先画底层的
//             通过Path实现画多个圆,不取消前面画的圆
        canvasBit.drawPath(mPath, mPaintDst);
//        将位图放在画布中,在进行了渲染操作的位图放到画布中显示出来。
        canvas.drawBitmap(mBitmap, 0, 0, null);
    }

  添加touch效果

   @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                x = event.getX();
                y = event.getY();
                mPath.moveTo(x, y);
                invalidate();//刷新
                old_x = x;
                old_y = y;
                return true;
            case MotionEvent.ACTION_MOVE:
                x = event.getX();
                y = event.getY();
                mPath.moveTo(old_x, old_y);
                mPath.lineTo(x, y);
                invalidate();
                old_y = y;
                old_x = x;
                return true;

            case MotionEvent.ACTION_UP:
                break;
            default:
                break;
        }
        return super.onTouchEvent(event);
    }

  
0917Android基础自定义View(颜色渲染PorterDuff及Xfermode)_第4张图片

修改后的代码

package com.example.laowang.myview2;

import android.content.Context;
import android.content.res.TypedArray;
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.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

/**
 * Created by Administrator on 2015/9/18.
 */
public class MyBitmapView extends View {
    private int mWith;
    private int mHeight;
    private Paint mPaintSrc;
    private Paint mPaintDst;
    private Bitmap mBitmap;
    private Bitmap mBitmapBackground;
    private Canvas canvasBit;
    private int mImageWith;
    private int mImageHeight;
    private Path mPath;
    private float x;
    private float y;
    private float old_y;
    private float old_x;

    public MyBitmapView(Context context) {
        super(context);
    }

    public MyBitmapView(Context context, AttributeSet attrs) {
        super(context, attrs);

        mPath = new Path();
        mPaintSrc = new Paint();
        mPaintDst = new Paint();
        mPaintSrc.setColor(Color.argb(0xff, 0x63, 0xAA, 0xFF));//自定义颜色
        mPaintSrc.setAntiAlias(true);
        mPaintDst.setColor(Color.argb(0xff, 0xFF, 0xCF, 0x42));
        mPaintDst.setStrokeWidth(30);


        mPaintDst.setAntiAlias(true);
//        可以使用图像合成的16条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互
        PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.XOR);
        mPaintDst.setXfermode(mode);//mPaintDst加上以后加图片处理,所以后面话圆的时候要用这个画笔

        mPaintDst.setStrokeJoin(Paint.Join.ROUND);//圆角 连接时使用的方式
        mPaintDst.setStrokeCap(Paint.Cap.ROUND);//圆角 覆盖式使用的方式
        mPaintDst.setStyle(Paint.Style.STROKE);//要用上面的方法必须将画笔设置成STROKE或者FILL_AND_STROKE

//        背景图片      mBitmapBackground=BitmapFactory.decodeResource(getResources(),R.mipmap.dog);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWith = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        mHeight = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(mWith, mHeight);
//      创建一个宽with高height的新位图,第三个参数传位图配置,这里的配置意思为:每个像素被存储在4个字节中。
        mBitmap = Bitmap.createBitmap(mWith, mHeight, Bitmap.Config.ARGB_8888);
//        绘制一个由指定位图构成的画布
        canvasBit = new Canvas(mBitmap);

        mImageWith = mBitmapBackground.getWidth();
        mImageHeight = mBitmapBackground.getHeight();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
//        添加背景图片,拉伸到屏幕大小
        canvas.drawBitmap(mBitmapBackground, new Rect(0, 0, mImageWith, mImageHeight), new Rect(0, 0, mWith, mHeight), null);
//        图像渲染只能在bitmap中进行,通过canvasBit对bitmap进行渲染操作
//        canvasBit.drawCircle(mWith / 2, mHeight / 2, 250, mPaintDst);

        canvasBit.drawRect(0, 0, mWith, mHeight, mPaintSrc);//先画底层的
//             通过Path实现画多个圆,不取消前面画的圆
        canvasBit.drawPath(mPath, mPaintDst);
//        将位图放在画布中,在进行了渲染操作的位图放到画布中显示出来。
        canvas.drawBitmap(mBitmap, 0, 0, null);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                x = event.getX();
                y = event.getY();
                mPath.moveTo(x, y);
                invalidate();//刷新
                old_x = x;
                old_y = y;
                return true;
            case MotionEvent.ACTION_MOVE:
                x = event.getX();
                y = event.getY();
                mPath.moveTo(old_x, old_y);
                mPath.lineTo(x, y);
                invalidate();
                old_y = y;
                old_x = x;
                return true;

            case MotionEvent.ACTION_UP:
                break;
            default:
                break;
        }
        return super.onTouchEvent(event);
    }
}

你可能感兴趣的:(android,位图,图像渲染,PorterDuff)