王學崗高級UI3——paint的高級使用(上)

一渲染

在這裏插入圖片描述
第一種情況——位圖渲染

package com.example.paintgaojishiyong.render;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

import com.example.paintgaojishiyong.R;

/**
 * @author writing
 * @time 2019/11/27 20:06
 * @note 渲染
 */
public class MyGradientView extends View {

    private Bitmap mBitmap;
    private Paint mPaint;
    private int width;
    private int height;

    public MyGradientView(Context context) {
        super(context);
        init();
    }
    public MyGradientView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MyGradientView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }
    private void init() {
        mBitmap = ((BitmapDrawable)getResources().getDrawable(R.drawable.xyjy2)).getBitmap();
        mPaint = new Paint();
        width = mBitmap.getWidth();
        height = mBitmap.getHeight();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.GREEN);
        /**
         * TileMode.CLAMP 拉伸最後一個像素去鋪滿剩下的地方
         * TileMode.MIRROR 通過鏡像翻轉鋪滿剩下的地方。
         * TileMode.REPEAT 重複圖片平鋪整個畫面(電腦設置壁紙)
         * 在圖片和顯示區域大小不符的情況進行擴充渲染
         */
        /**
         * 位圖渲染,BitmapShader(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY)
         * Bitmap:構造shader使用的bitmap
         * tileX:X軸方向的TileMode
         * tileY:Y軸方向的TileMode
         */
        BitmapShader bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT,Shader.TileMode.MIRROR);
        mPaint.setShader(bitmapShader);
        mPaint.setAntiAlias(true);
        canvas.drawRect(new Rect(0,0,1000,1600),mPaint);
    }
}

MainActivity中的設置

package com.example.paintgaojishiyong;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import com.example.paintgaojishiyong.render.MyGradientView;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new MyGradientView(this));
    }
}

其中的一種效果
在這裏插入圖片描述
第二種情況——線性渲染

package com.example.paintgaojishiyong.render;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

import com.example.paintgaojishiyong.R;

/**
 * @author writing
 * @time 2019/11/27 20:06
 * @note 渲染
 */
public class MyGradientView extends View {

    private Bitmap mBitmap;
    private Paint mPaint;
    private int[] colors = new int[]{Color.RED,Color.GREEN,Color.BLUE,Color.YELLOW};

    public MyGradientView(Context context) {
        super(context);
        init();
    }
    public MyGradientView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MyGradientView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }
    private void init() {
        mBitmap = ((BitmapDrawable)getResources().getDrawable(R.drawable.xyjy2)).getBitmap();
        mPaint = new Paint();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.WHITE);
        /**線性渲染
         * x0, y0, 起始點
         * x1, y1, 結束點
         * int[]  mColors, 中間依次要出現的幾個顏色
         * float[] positions 位置數組,position的取值範圍[0,1],作用是指定幾個顏色分別放置在那個位置上,
         * 如果傳null,漸變就線性變化。
         *    tile 用於指定控件區域大於指定的漸變區域時,空白區域的顏色填充方法
         */
        LinearGradient linearGradient = new LinearGradient(0,0,800,800,colors,new float[]{0.25f,0.5f,0.75f,0.9f},Shader.TileMode.MIRROR);
        mPaint.setShader(linearGradient);
        canvas.drawRect(0,0,800,800,mPaint);
    }
}

我們看下效果
在這裏插入圖片描述
例子:跑馬燈效果

package com.dn_alan.myapplication.render;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.util.AttributeSet;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;

/**
 * 線性渲染
 */

public class LinearGradientTextView extends AppCompatTextView {
    private LinearGradient mLinearGradient;
    private Matrix mGradientMatrix;
    private Paint mPaint;

    private int mViewWidth = 0;
    private int mTranslate = 0;

    private int delta = 15;

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

    public LinearGradientTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }
    //    控件大小發生改變時調用,初始化只會被調用一次
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if (mViewWidth == 0) {
            //得到控件的寬度
            mViewWidth = getMeasuredWidth();
            //大於0表示TextView有內容。
            if (mViewWidth > 0) {
                //TextView中獲取畫筆
                mPaint = getPaint();
                //獲取文字長度
                String text = getText().toString();
                //下面就是計算高亮文字的大小是多少。
                int size;
                if (text.length() > 0) {
                    //mViewWidth除字體總數就得到了每個字的像素    然後*3 表示3個文字的像素
                    size = mViewWidth / text.length() * 3;
                } else {
                    size = mViewWidth;
                }
                // 從左邊-size開始,左邊看不見的地方開始,滾動掃描過來
                mLinearGradient = new LinearGradient(-size, 0, 0, 0,
                        new int[]{0x33ffffff, 0xffffffff, 0x33ffffff},
                        new float[]{0, 0.2f, 1}, Shader.TileMode.CLAMP); //邊緣融合
                mPaint.setShader(mLinearGradient);`在這裏插入代碼片`
                mGradientMatrix = new Matrix();
            }
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //getTextBounds() 還可以獲得高度信息,因爲其使用一個 Rect 對象對寬高信息進行存儲;而measureText() 則只是返回寬度信息。
        float mTextWidth = getPaint().measureText(getText().toString());
        mTranslate += delta;
        /**
         * 如果位置已經移動到了整方了那個文字的地就開始往回滾動。
         * 但是如果小於1 了那麼又開始遞增,走另外一個邏輯
         */
        if (mTranslate > mTextWidth + 1 || mTranslate < 1) {
            delta = -delta;
        }
        mGradientMatrix.setTranslate(mTranslate, 0);
        mLinearGradient.setLocalMatrix(mGradientMatrix);
        //paint是textview的所以只需要不斷色控制畫筆的shader  然後利用矩陣控制位移即可
        postInvalidateDelayed(30);
    }
}

佈局文件

   <com.dn_alan.myapplication.render.LinearGradientTextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="30sp"
        android:textColor="#666666"
        android:text="歡迎同學們來到動腦學院高級UI"/>

在這裏插入圖片描述

第三種情況,掃描渲染

package com.example.gaojiui;


import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

public class MyGradientView extends View {
    private int[] colors = new int[]{Color.RED,Color.GREEN,Color.BLUE,Color.YELLOW};
    private Paint paint;

    public MyGradientView(Context context) {
        super(context);
        init();
    }

    public MyGradientView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MyGradientView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        paint = new Paint();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        /**
         * 第一、二個參數:漸變中心座標
         * 第三個參數:漸變開始和結束的顏色
         * 最後一個參數爲null時候,根據顏色線性漸變
         */
        SweepGradient sweepGradient = new SweepGradient(200,200,colors,new float[]{0,0.5f,0.6f,0.9f});
        paint.setShader(sweepGradient);
        canvas.drawCircle(200,200,200,paint);
    }
}

在這裏插入圖片描述
例子不斷旋轉掃描

package com.dn_alan.myapplication.render;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import androidx.annotation.Nullable;

/**
 * 漸變渲染/梯度渲染
 */
public class RadarGradientView extends View {
    private int mWidth, mHeight;

    //五個圓
    private float[] pots = {0.05f, 0.1f, 0.15f, 0.2f, 0.25f};

    private Shader scanShader; // 掃描渲染shader
    private Matrix matrix = new Matrix(); // 旋轉需要的矩陣
    private int scanSpeed = 5; // 掃描速度
    private int scanAngle; // 掃描旋轉的角度

    private Paint mPaintCircle; // 畫圓用到的paint
    private Paint mPaintRadar; // 掃描用到的paint


    public RadarGradientView(Context context) {
        super(context);

        // 畫圓用到的paint
        mPaintCircle = new Paint();
        mPaintCircle.setStyle(Paint.Style.STROKE); // 描邊
        mPaintCircle.setStrokeWidth(1); // 寬度
        mPaintCircle.setAlpha(100); // 透明度
        mPaintCircle.setAntiAlias(true); // 抗鋸齒
        mPaintCircle.setColor(Color.parseColor("#ff0000")); // 設置紅色

        // 掃描用到的paint
        mPaintRadar = new Paint();
        mPaintRadar.setStyle(Paint.Style.FILL_AND_STROKE); // 填充
        mPaintRadar.setAntiAlias(true); // 抗鋸齒

        post(run);
    }

    public RadarGradientView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public RadarGradientView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        // 取屏幕的寬高是爲了把雷達放在屏幕的中間
        mWidth = getMeasuredWidth();
        mHeight = getMeasuredHeight();
        mWidth = mHeight = Math.min(mWidth, mHeight);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //畫圈圈
        for (int i = 0; i < pots.length; i++) {
            canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth * pots[i], mPaintCircle);
        }

        // 畫布的旋轉變換 需要調用save() 和 restore()
        canvas.save();
        //顏色漸變從透明到綠色
        scanShader = new SweepGradient(mWidth / 2, mHeight / 2,
                new int[]{Color.TRANSPARENT, Color.parseColor("#00ff00")}, null);
        mPaintRadar.setShader(scanShader); // 設置着色器
        /**
         * 1,canvas.concat的作用可以理解成對matrix的變換應用到canvas上的所有對象.
         * 2,在自定義View的時候,我們經常會用到Canvas進行繪製,其中也會用到Matrix對圖像進行移動、旋轉等操作,
         *    這個時候就會涉及到concat和setMatrix這兩個方法,將Matrix的變化效果設置到Canvas上
         * 3,setMatrix作用的是當前的畫布,而concat作用的是畫布上的組件。具體講的詳細一點的話,如果我對matrix放大兩倍,使用setMatrix的話,
         *    相當於整個座標軸放大了兩倍,而繪製的參數並沒有改變。因爲canvas的原點並沒有在左上角,導致實際上會有偏差。
         *    而concat改變的是繪製的參數,200變400,100變200,而座標軸不變,所以整體上就當好是兩倍的效果。
         */

        canvas.concat(matrix);
        canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth * pots[4], mPaintRadar);

        canvas.restore();
    }


    private Runnable run = new Runnable() {
        @Override
        public void run() {
            scanAngle = (scanAngle + scanSpeed) % 360; // 旋轉角度 對360取餘,保證旋轉角度在360以內
            /**
             * setRotate   : 使用的是setRotate()方法對指針圖片進行旋轉操作,再用了setTranslate()方法進行平移操作,則之前的旋轉效果就沒有                        了,只有平移效果
             * 原因:Matrix方法中的setRotate()方法會先清除該矩陣,之後設置旋轉操作的,同樣,setTranslate()等方法也是一樣的。所以各種效果           是不能疊加在一起的
             * postRotate   :可以實現多種效果同時使用
             */
            matrix.postRotate(scanSpeed, mWidth / 2, mHeight / 2); // 旋轉矩陣
            invalidate(); // 通知view重繪
            postDelayed(run, 50); // 調用自身 重複繪製
        }
    };

}

在這裏插入圖片描述
第四種情況:環形渲染

 package com.example.gaojiui;


import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

public class MyGradientView extends View {
    private int[] colors = new int[]{Color.RED,Color.GREEN,Color.BLUE,Color.YELLOW};
    private Paint paint;

    public MyGradientView(Context context) {
        super(context);
        init();
    }

    public MyGradientView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MyGradientView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        paint = new Paint();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        /**
         * 環形渲染
         * centerX ,centerY:shader的中心座標,開始漸變的座標
         * radius:漸變的半徑
         * centerColor,edgeColor:中心點漸變顏色,邊界的漸變顏色
         * colors:漸變顏色數組
         * stops:漸變位置數組,類似掃描漸變的positions數組,取值[0,1],中心點爲0,半徑到達位置爲1.0f
         * tileMode:shader未覆蓋以外的填充模式
         */
        RadialGradient radialGradient = new RadialGradient(300,300,100,colors,null, Shader.TileMode.REPEAT);
        paint.setShader(radialGradient);
        canvas.drawCircle(300,300,300,paint);
    }
}

看下效果
在這裏插入圖片描述
例子:手指點擊出現波紋效果

package com.example.gaojiui;


import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;

public class MyGradientView extends View {
    private Shader radialGradient;
    private Paint paint;
    private int x;
    private int y;
    private int radious;

    public MyGradientView(Context context) {
        super(context);
        init();
    }

    public MyGradientView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MyGradientView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {

        paint = new Paint();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        int width = getMeasuredWidth();
        int height = getMeasuredHeight();
        radious = Math.max(width,height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.BLUE);
        if(radialGradient!=null){
           paint.setShader(radialGradient);
           canvas.drawCircle(x,y,radious,paint);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //蛇者alpha通道(透明度)
        x = (int) event.getX();
        y = (int) event.getY();
        paint.setAlpha(400);
        radialGradient = new RadialGradient(event.getX(),event.getY(),48,new int[]{Color.WHITE,Color.TRANSPARENT},
                null,Shader.TileMode.REPEAT);
        postInvalidate();
        return true;
    }
}

在這裏插入圖片描述
第五種情況組合模式

package com.example.paintgaojishiyong.render;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ComposeShader;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

import com.example.paintgaojishiyong.R;

/**
 * @author writing
 * @time 2019/11/27 20:06
 * @note 渲染
 */
public class MyGradientView extends View {


    private int width;
    private int height;
    private Paint paint;

    public MyGradientView(Context context) {
        super(context);
        init();
    }
    public MyGradientView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MyGradientView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }
    private void init() {
        paint = new Paint();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = getMeasuredWidth();
        height = getMeasuredHeight();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        /**
         * 組合渲染,
         * ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, Xfermode mode)
         * ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, PorterDuff.Mode mode)
         * shaderA,shaderB:要混合的兩種shader
         * Xfermode mode: 組合兩種shader顏色的模式
         * PorterDuff.Mode mode: 組合兩種shader顏色的模式
         */
        /*ComposeShader mComposeShader = new ComposeShader(linearGradient, mBitmapShader, PorterDuff.Mode.SRC_OVER);
        mPaint.setShader(mComposeShader);
        canvas.drawRect(0, 0, 800, 1000, mPaint);*/

        /***************用ComposeShader即可實現心形圖漸變效果*********************************/
        //創建BitmapShader,用以繪製心
        Bitmap mBitmap = ((BitmapDrawable)getResources().getDrawable(R.drawable.heart)).getBitmap();
        BitmapShader bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        //創建LinearGradient,用以產生從左上角到右下角的顏色漸變效果
        LinearGradient linearGradient = new LinearGradient(0, 0, width, height,
                Color.RED, Color.BLACK, Shader.TileMode.CLAMP);
        //bitmapShader對應目標像素,linearGradient對應源像素,像素顏色混合採用MULTIPLY模式
        ComposeShader composeShader = new ComposeShader(linearGradient, bitmapShader, PorterDuff.Mode.MULTIPLY);
        //將組合的composeShader作爲畫筆paint繪圖所使用的shader
        paint.setShader(composeShader);
        //用composeShader繪製矩形區域
        canvas.drawRect(0, 0, mBitmap.getWidth(), mBitmap.getHeight(), paint);
    }
}

運行效果,本來我們的心,是白色的圖片,運行完變成紅色了。我們看下效果
在這裏插入圖片描述
例子,放大鏡效果

package com.dn_alan.myapplication.render;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Shader;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.view.MotionEvent;
import android.view.View;

import com.dn_alan.myapplication.R;

/**
 * 放大鏡效果
 */

public class ZoomImageView extends View {

    //放大倍數
    private static final int FACTOR = 2;
    //放大鏡的半徑
    private static final int RADIUS  = 100;
    // 原圖
    private Bitmap mBitmap;
    // 放大後的圖
    private Bitmap mBitmapScale;
    // 製作的圓形的圖片(放大的局部),蓋在Canvas上面
    private ShapeDrawable mShapeDrawable;

    private Matrix mMatrix;

    public ZoomImageView(Context context) {
        super(context);
         //加載一張圖片,要放大的圖片
        mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.xyjy3);
        mBitmapScale = mBitmap;
        //放大後的整個圖片
        mBitmapScale = Bitmap.createScaledBitmap(mBitmapScale,mBitmapScale.getWidth() * FACTOR,
                mBitmapScale.getHeight() * FACTOR,true);
        BitmapShader bitmapShader = new BitmapShader(mBitmapScale, Shader.TileMode.CLAMP,
                Shader.TileMode.CLAMP);

        mShapeDrawable = new ShapeDrawable(new OvalShape());
        mShapeDrawable.getPaint().setShader(bitmapShader);
        // 切出矩形區域,用來畫圓(內切圓)
        mShapeDrawable.setBounds(0,0,RADIUS * 2,RADIUS * 2);

        mMatrix = new Matrix();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // 1、畫原圖
        canvas.drawBitmap(mBitmap, 0 , 0 , null);

        // 2、畫放大鏡的圖
        mShapeDrawable.draw(canvas);
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();

        // 將放大的圖片往相反的方向挪動
        mMatrix.setTranslate(RADIUS - x * FACTOR, RADIUS - y *FACTOR);
        mShapeDrawable.getPaint().getShader().setLocalMatrix(mMatrix);
        // 切出手勢區域點位置的圓
        mShapeDrawable.setBounds(x-RADIUS,y - RADIUS, x + RADIUS, y + RADIUS);
        invalidate();
        return true;
    }
}

二濾鏡

在這裏插入圖片描述
濾鏡效果就是拿到圖像裏所有的像素點,改變其RGB值。有一種簡單的方法,就是使用顏色矩陣。
效果一模糊遮罩濾鏡

package com.example.paintgaojishiyong.guolv;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

import com.example.paintgaojishiyong.R;

/**
 * @author writing
 * @time 2019/12/3 16:17
 * @note
 */
public class FilterView extends View {

    private Paint paint;
    private Bitmap bitmap;

    public FilterView(Context context) {
        super(context);
        init();
    }

    public FilterView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public FilterView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(Color.RED);
        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.xyjy2);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //關閉單個View的硬件加速功,只針對當前View,不讓它硬件加速
        setLayerType(View.LAYER_TYPE_SOFTWARE,null);
        RectF rectF = new RectF(200,100,bitmap.getWidth()+200,bitmap.getHeight());
        //50是陰影的半徑
        // 四種模式:NORMOL -- 整個圖像都被模糊掉
         // SOLID -- 圖像邊界外產生一層與Paint顏色一致陰影效果,不影響圖像的本身
         // OUTER -- 圖像邊界外產生一層陰影,並且將圖像變成透明效果
         // INNER -- 在圖像內部邊沿產生模糊效果
        paint.setMaskFilter(new BlurMaskFilter(50,BlurMaskFilter.Blur.NORMAL));
        canvas.drawRect(rectF,paint);
    }
}

在這裏插入圖片描述
效果二浮雕遮罩濾鏡

package com.example.paintgaojishiyong.guolv;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.EmbossMaskFilter;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

import com.example.paintgaojishiyong.R;

/**
 * @author writing
 * @time 2019/12/3 16:17
 * @note
 */
public class FilterView extends View {

    private Paint paint;
    private Bitmap bitmap;

    public FilterView(Context context) {
        super(context);
        init();
    }

    public FilterView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public FilterView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(Color.RED);
        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.xyjy2);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //關閉單個View的硬件加速功,只針對當前View,不讓它硬件加速
        setLayerType(View.LAYER_TYPE_SOFTWARE,null);
        RectF rectF = new RectF(200,100,bitmap.getWidth()+200,bitmap.getHeight());
        /**
         * Create an emboss maskfilter
         *
         * @param direction  指定光源的位置,長度爲xxx的數組標量[x,y,z]
         * @param ambient    環境光的因子 (0~1),越接近0,環境光越暗
         * @param specular   鏡面反射係數 越接近0,鏡面反射越強
         * @param blurRadius 模糊半徑 值越大,模糊效果越明顯
         */
        paint.setMaskFilter(new EmbossMaskFilter(new float[]{1,1,1},0.2f,60,80));
        canvas.drawRect(rectF,paint);
    }
}

在這裏插入圖片描述
以上兩個效果都不常用,常用的是使用矩形改變像素點
效果三矩陣——平移運算,加法

package com.example.paintgaojishiyong.guolv;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

import com.example.paintgaojishiyong.R;

/**
 * @author writing
 * @time 2019/12/3 16:17
 * @note
 */
public class FilterView extends View {

    private Paint paint;
    private Bitmap bitmap;

    public FilterView(Context context) {
        super(context);
        init();
    }

    public FilterView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public FilterView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(Color.RED);
        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.xyjy2);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        ColorMatrix colorMatrix = new ColorMatrix(new float[]{
                //第一行表示R,第二行表示G,第三行表示B,第四行表示A
                1,0,0,0,0,
                0,1,0,0,100,
                0,0,1,0,0,
                0,0,0,1,0,
        });
        RectF rectF = new RectF(200,100,bitmap.getWidth()+200,bitmap.getHeight()+100);
        paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
        canvas.drawBitmap(bitmap,null,rectF,paint);
    }
}

在這裏插入圖片描述
效果四:矩陣反相效果 – 底片效果

package com.example.paintgaojishiyong.guolv;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

import com.example.paintgaojishiyong.R;

/**
 * @author writing
 * @time 2019/12/3 16:17
 * @note
 */
public class FilterView extends View {

    private Paint paint;
    private Bitmap bitmap;

    public FilterView(Context context) {
        super(context);
        init();
    }

    public FilterView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public FilterView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(Color.RED);
        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.xyjy2);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        ColorMatrix colorMatrix = new ColorMatrix(new float[]{
                -1, 0,0,0,255,
                0,-1,0,0,255,
                0,0,-1,0,255,
                0,0,0,1,0,
        });
        RectF rectF = new RectF(200,100,bitmap.getWidth()+200,bitmap.getHeight()+100);
        paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
        canvas.drawBitmap(bitmap,null,rectF,paint);
    }
}

在這裏插入圖片描述
效果五:縮放運算—乘法 – 顏色增強

package com.example.paintgaojishiyong.guolv;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

import com.example.paintgaojishiyong.R;

/**
 * @author writing
 * @time 2019/12/3 16:17
 * @note
 */
public class FilterView extends View {

    private Paint paint;
    private Bitmap bitmap;

    public FilterView(Context context) {
        super(context);
        init();
    }

    public FilterView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public FilterView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(Color.RED);
        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.xyjy2);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
                ColorMatrix colorMatrix = new ColorMatrix(new float[]{
                1.2f, 0,0,0,0,
                0,1.2f,0,0,0,
                0,0,1.2f,0,0,
                0,0,0,1.2f,0,
        });
        RectF rectF = new RectF(200,100,bitmap.getWidth()+200,bitmap.getHeight()+100);
        paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
        canvas.drawBitmap(bitmap,null,rectF,paint);
    }
}

在這裏插入圖片描述
上圖是原圖,下圖是應用了效果後的圖
效果五:黑白效果

package com.example.paintgaojishiyong.guolv;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

import com.example.paintgaojishiyong.R;

/**
 * @author writing
 * @time 2019/12/3 16:17
 * @note
 */
public class FilterView extends View {

    private Paint paint;
    private Bitmap bitmap;

    public FilterView(Context context) {
        super(context);
        init();
    }

    public FilterView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public FilterView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(Color.RED);
        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.xyjy2);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        RectF rectF = new RectF(200,100,bitmap.getWidth()+200,bitmap.getHeight());
        canvas.drawBitmap(bitmap,null, rectF,paint);
        paint.reset();
        /** 黑白照片
         *是將我們的三通道變爲單通道的灰度模式
         *去色原理:只要把R G B 三通道的色彩信息設置成一樣,那麼圖像就會變成灰色,
         *同時爲了保證圖像亮度不變,同一個通道里的R+G+B =1
         */
        ColorMatrix colorMatrix = new ColorMatrix(new float[]{
                0.213f, 0.715f,0.072f,0,0,
                0.213f, 0.715f,0.072f,0,0,
                0.213f, 0.715f,0.072f,0,0,
                0,0,0,1,0,
        });
        RectF rectF1 = new RectF(200,bitmap.getHeight()+100,bitmap.getWidth()+200,bitmap.getHeight()*2+100);
        paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
        canvas.drawBitmap(bitmap,null,rectF1,paint);
    }
}

在這裏插入圖片描述
上圖是原圖,下圖是效果圖
效果六 髮色效果—(比如紅色和綠色交換)

package com.example.paintgaojishiyong.guolv;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

import com.example.paintgaojishiyong.R;

/**
 * @author writing
 * @time 2019/12/3 16:17
 * @note
 */
public class FilterView extends View {

    private Paint paint;
    private Bitmap bitmap;

    public FilterView(Context context) {
        super(context);
        init();
    }

    public FilterView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public FilterView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(Color.RED);
        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.xyjy2);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        RectF rectF = new RectF(200,100,bitmap.getWidth()+200,bitmap.getHeight());
        canvas.drawBitmap(bitmap,null, rectF,paint);
        paint.reset();
        // 髮色效果---(比如紅色和綠色交換)
        ColorMatrix colorMatrix = new ColorMatrix(new float[]{
                1,0,0,0,0,
                0, 0,1,0,0,
                0,1,0,0,0,
                0,0,0,0.5F,0,
        });
        RectF rectF1 = new RectF(200,bitmap.getHeight()+100,bitmap.getWidth()+200,bitmap.getHeight()*2+100);
        paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
        canvas.drawBitmap(bitmap,null,rectF1,paint);
    }
}

在這裏插入圖片描述
效果七復古效果

package com.example.paintgaojishiyong.guolv;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

import com.example.paintgaojishiyong.R;

/**
 * @author writing
 * @time 2019/12/3 16:17
 * @note
 */
public class FilterView extends View {

    private Paint paint;
    private Bitmap bitmap;

    public FilterView(Context context) {
        super(context);
        init();
    }

    public FilterView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public FilterView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(Color.RED);
        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.xyjy2);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        RectF rectF = new RectF(200,100,bitmap.getWidth()+200,bitmap.getHeight());
        canvas.drawBitmap(bitmap,null, rectF,paint);
        paint.reset();
        // 復古效果
        ColorMatrix colorMatrix = new ColorMatrix(new float[]{
                1/2f,1/2f,1/2f,0,0,
                1/3f, 1/3f,1/3f,0,0,
                1/4f,1/4f,1/4f,0,0,
                0,0,0,1,0,
        });
        RectF rectF1 = new RectF(200,bitmap.getHeight()+100,bitmap.getWidth()+200,bitmap.getHeight()*2+100);
        paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
        canvas.drawBitmap(bitmap,null,rectF1,paint);
    }
}

在這裏插入圖片描述

第三Xfermode

在這裏插入圖片描述
https://developer.android.google.cn/reference/android/graphics/PorterDuff.Mode?hl=en#ADD
https://blog.csdn.net/cquwentao/article/details/51423371
https://www.jianshu.com/p/d11892bbe055
以上是三篇參考的文章
第一:PorterDuff.Mode.DST_IN效果
保留覆蓋源像素的目標像素,丟棄其餘的源像素和目標像素。
我們看下兩張圖片

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章