Android 圖片處理(Canvas/Paint/Matrix/Path/Bezier曲線)

Android 圖片處理(Canvas/Paint/Matrix/Path/Bezier曲線)


本文由 Luzhuo 編寫,轉發請保留該信息.
原文: https://blog.csdn.net/Rozol/article/details/79683220


加載圖片

將圖片加載到內存顯示之前, 要先根據將要顯示的容器的大小來按比例壓縮圖片, 這樣才不至於將內存撐爆.

/**
 * 加載圖片
 * <br>步驟: 獲取手機和圖片分辨率 -> 計算縮放比 -> 加載圖片(用最大的縮放比)
 */
public void onclick(View view){
    // 獲取手機分辨率
    DispalyHW screenHW = getScreenHeightWidth(this);
    Log.i(TAG, "手機分辨率: width: " + screenHW.width + " height: " + screenHW.height);

    // 獲取圖片分辨率
    File file = new File(Environment.getExternalStorageDirectory(), "dog.jpg");
    DispalyHW imageHW = getImageHeightWidth(file);
    Log.i(TAG, "圖片分辨率: width: " + imageHW.width + " height: " + imageHW.height);

    // 計算縮放比: 圖片寬高 ÷ 手機寬高 的比率, 取最大的縮放比
    int scale = 1;
    int scalex =  imageHW.width / screenHW.width;
    int scaley = imageHW.height / screenHW.height;
    if (scalex >= scaley && scalex > scale) {
        scale = scalex;
    }
    if (scaley > scalex && scaley > scale) {
        scale = scaley;
    }
    Log.i(TAG, "縮放比爲: " + scale);

    // 加載圖片
    Bitmap bitmap = getBitmap(file, scale);

    imageView.setImageBitmap(bitmap);
}
  • 獲取手機分辨率

    /**
     * 獲取手機分辨率
     * @param context
     */
    public static DispalyHW getScreenHeightWidth(Context context){
        DispalyHW hw = new DispalyHW();
    
        WindowManager wm = (WindowManager) context.getSystemService(WINDOW_SERVICE);
    
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR2) {
            hw.width = wm.getDefaultDisplay().getWidth();
            hw.height = wm.getDefaultDisplay().getHeight();
        } else {
            // api>13
            Point point = new Point();
            wm.getDefaultDisplay().getSize(point);
            hw.width = point.x;
            hw.height = point.y;
        }
    
        return hw;
    }
  • 獲取圖片分辨率

    /**
     * 獲取圖片的分辨率率
     * @param file 圖片文件
     * @return 如果文件不存在返回null
     */
    public static DispalyHW getImageHeightWidth(File file){
        if (!file.exists()) return null;
    
        DispalyHW hw = new DispalyHW();
    
        // bitmap工廠的配置參數
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true; // 加載圖片信息, 不加載圖片
        BitmapFactory.decodeFile(file.getAbsolutePath(), options);
    
        // 獲取圖片的寬和高
        hw.width = options.outWidth;
        hw.height = options.outHeight;
        return hw;
    }
  • 加載圖片

    /**
     * 加載圖片
     * @param file 圖片文件
     * @param scale 縮放比 >= 1
     * @return 文件不存在返回null
     */
    public static Bitmap getBitmap(File file, int scale){
        if (!file.exists()) return null;
    
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = scale; // 按縮放比壓縮
        options.inJustDecodeBounds = false; // 加載圖片
        Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath(), options);
    
        return bitmap;
    }

圖片處理

只能對副本圖片進行處理

創建副本

public void onclick(View view){
    // 從資源加載Bitmap
    Bitmap srcBitmap = getBitmapOnRes(this, R.mipmap.abc);
    iv_src.setImageBitmap(srcBitmap);

    // 創作模板
    Bitmap copyBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());
    Canvas canvas = new Canvas(copyBitmap); // 畫布
    Paint paint = new Paint(); // 畫筆
    Matrix matrix = new Matrix(); // 矩陣
    canvas.drawBitmap(srcBitmap, matrix, paint); // 繪畫

    iv_copy.setImageBitmap(copyBitmap);
}
  • 從資源加載圖片

    /**
     * 從資源文件中加載圖片
     * @param context 上下文
     * @param drawableID 資源圖片id
     */
    public static Bitmap getBitmapOnRes(Context context, @DrawableRes int drawableID){
        Bitmap resBitmap = BitmapFactory.decodeResource(context.getResources(), drawableID);
        return resBitmap;
    }

畫布

 /**
  * 對畫布Canvas進行操作, 畫布具有 移動, 狀態保存與恢復, 繪製等操作
  */
 public void onclick(View view){
     Bitmap srcBitmap = getBitmapOnRes(this, R.mipmap.abc);
     iv_src.setImageBitmap(srcBitmap);
     Bitmap copyBitmap = Bitmap.createBitmap(srcBitmap.getWidth() * 3, srcBitmap.getHeight() * 3, srcBitmap.getConfig());
     Paint paint = new Paint(); // 畫筆
     paint.setStyle(Paint.Style.STROKE); // 只畫線不填充
     Matrix matrix = new Matrix(); // 矩陣

     Path path = new Path(); // 路徑
     path.moveTo(10, 50);
     path.lineTo(30, 100);
     path.lineTo(60, 300);
     path.close();


     Canvas canvas = new Canvas(copyBitmap); // 畫布
     // --- 效果疊加 ---
     // 平移(參數: x, y)
     canvas.translate(10, 10);
     // 縮放(參數: 縮放倍數, x, y)
     canvas.scale(0.5f, 0.5f, srcBitmap.getWidth() / 2, srcBitmap.getHeight() / 2);
     // 旋轉(參數: 角度, x, y)
     canvas.rotate(30, srcBitmap.getWidth() / 2, srcBitmap.getHeight() / 2);


     // --- 畫布操作動作的保存與恢復 (僅對 平移等操作有效, 對繪製操作無效) ---
     // 保存畫布修改狀態
     int save = canvas.save();
     // 還原到最近保存的狀態
     // canvas.restore();
     // 還原到指定狀態
     canvas.restoreToCount(save);


     // --- 繪製 ---
     // 繪製點(參數: x,y / [x,y,x,y,x,y])
     canvas.drawPoint(10, 10, paint);
     canvas.drawPoints(new float[]{11, 11, 12, 11, 13, 11}, paint);
     // 繪製文字(參數: 文字, x,y)
     canvas.drawText("luzhuo.me", 50, 50, paint);
     // 根據路徑繪製文字(參數: 文字, 路徑, 起始偏移, 上下編譯)
     canvas.drawTextOnPath("luzhuo.meluzhuo.meluzhuo.meluzhuo.meluzhuo.me", path, 0, 0, paint);
     // 繪製直線(參數, x,y, x1,y1)
     canvas.drawLine(100, 100, 300, 300, paint);
     // 繪製矩形(參數: 左上x,y, 右下x,y)
     canvas.drawRect(0, 0, 200, 200, paint);
     // 繪製圓形(參數: 圓心x,y, 半徑)
     canvas.drawCircle(100,100, 50, paint);
     // 繪製橢圓(參數: 左上右下)
     canvas.drawOval(new RectF(100, 100, 300, 200), paint);
     // 繪製弧線(參數: RectF, 起始角度, 掃過角度, 是否中心連線)(矩形擦除部分)
     canvas.drawArc(new RectF(100, 100, 300, 200), 30, 180, false, paint);
     // 繪製路徑(參數: 路徑)
     canvas.drawPath(path, paint);
     // 繪製圖片
     canvas.drawBitmap(srcBitmap, matrix, paint); // 繪畫


     iv_copy.setImageBitmap(copyBitmap);
 }

矩陣

 /**
  * Matrix矩陣的變換
  */
 public void onclick(View view){
     Bitmap srcBitmap = getBitmapOnRes(this, R.mipmap.abc);
     iv_src.setImageBitmap(srcBitmap);

     Bitmap copyBitmap = Bitmap.createBitmap(srcBitmap.getWidth() * 2, srcBitmap.getHeight() * 2, srcBitmap.getConfig()); // 白紙
     Canvas canvas = new Canvas(copyBitmap); // 畫布
     Paint paint = new Paint(); // 畫筆
     paint.setStyle(Paint.Style.STROKE); // 只畫線不填充

     /*
        x: [MSCALE_X,   MSKEW_X,    MTRANS_X]
        y: [MSKEW_Y,    MSCALE_Y,   MTRANS_Y]
        z: [MPERSP_0,   MPERSP_1,   MPERSP_2]

        MSCALE:縮放, MSKEW:錯切, MTRANS:位移, MPERSP:透視
     */
     Matrix matrix = new Matrix(); // 矩陣


     // --- setxxx 覆蓋 ---
     // 平移(參數: x, y)
     matrix.setTranslate(100, 100);
     // 縮放(參數: 縮放倍數, x, y)
     matrix.setScale(0.5f, 0.5f, srcBitmap.getWidth() / 2, srcBitmap.getHeight() / 2);
     // 旋轉(參數: 角度, x, y絕對座標)
     matrix.setRotate(30, srcBitmap.getWidth() / 2, srcBitmap.getHeight() / 2);
     // 旋轉(參數: sin, cos, x,y)
     matrix.setSinCos(1, 0, srcBitmap.getWidth() / 2, srcBitmap.getHeight() / 2);
     // 錯切(參數:x錯切因子,y因子, 中心x,y) (錯切因子爲tan值: 45° tan=1)
     matrix.setSkew(1, 0);

     // 重置
     matrix.reset();



     // --- prexxx 前乘疊加 √ M' = M * T(dx, dy) ---
     matrix.preTranslate(100, 100);
     matrix.preScale(0.5f, 0.5f, srcBitmap.getWidth() / 2, srcBitmap.getHeight() / 2);
     matrix.preRotate(30, srcBitmap.getWidth() / 2, srcBitmap.getHeight() / 2);
     matrix.preSkew(1, 0);


     // --- postxxx 後乘疊加 M' = T(dx, dy) * M ---
     matrix.postTranslate(100, 100);
     matrix.postScale(0.5f, 0.5f, srcBitmap.getWidth() / 2, srcBitmap.getHeight() / 2);
     matrix.postRotate(30, srcBitmap.getWidth() / 2, srcBitmap.getHeight() / 2);
     matrix.postSkew(1, 0);



     // --- 自由變換矩陣 ---
     // 參數: 源點[左上x,y, 右上x1,y1, 左下x2,y2, 右下x3,y3], 第一個src點的索引, 目標點[x,y,x1,y1,...], 第一個dst點的索引, 一次使用多少個點(0-4)
     // public boolean setPolyToPoly(float[] src, int srcIndex,float[] dst, int dstIndex,int pointCount)
     matrix.setPolyToPoly(new float[]{0, 0}, 0, new float[]{100, 100}, 0, 1); // 平移
     matrix.setPolyToPoly(new float[]{0, 0, copyBitmap.getWidth(), 0}, 0, new float[]{copyBitmap.getHeight(), 0, copyBitmap.getHeight(), copyBitmap.getWidth()}, 0, 2); // 旋轉
     matrix.setPolyToPoly(new float[]{0, 0, 0, copyBitmap.getHeight(), copyBitmap.getWidth(), copyBitmap.getHeight()}, 0, new float[]{0, 0, 100, copyBitmap.getHeight(), copyBitmap.getWidth() + 100, copyBitmap.getHeight()}, 0, 3); // 錯切
     matrix.setPolyToPoly(new float[]{0, 0, copyBitmap.getWidth(), 0, 0, copyBitmap.getHeight(), copyBitmap.getWidth(), copyBitmap.getHeight()}, 0, new float[]{0 + 100, 0, copyBitmap.getWidth() - 100, 0, 0, copyBitmap.getHeight(), copyBitmap.getWidth(), copyBitmap.getHeight()}, 0, 4); // 透視


     canvas.drawBitmap(srcBitmap, matrix, paint); // 繪畫

     iv_copy.setImageBitmap(copyBitmap);
 }

畫筆

 /**
  * Paint畫筆的操作, 可設置, 繪畫, 漸變, 濾鏡
  */
 public void onclick(View view){
     Bitmap copybitmap = Bitmap.createBitmap(1000, 1000, Bitmap.Config.ARGB_8888); // 白紙
     Canvas canvas = new Canvas(copybitmap); // 畫布
     Paint paint = new Paint(); // 畫筆

     // --- 樣式 ---
     // 填充: STROKE:畫線, FILL:填充, FILL_AND_STROKE:畫線並填充
     paint.setStyle(Paint.Style.STROKE);
     // 線帽(線條末端): BUTT:無(直角頭), ROUND:圓頭, SQUARE:直角頭
     paint.setStrokeCap(Paint.Cap.ROUND);
     // 角: MITER:直角, ROUND:圓角, BEVEL:平角
     paint.setStrokeJoin(Paint.Join.BEVEL);
     // 排列: LEFT:左, CENTER:中, RIGHT:右
     paint.setTextAlign(Paint.Align.CENTER);



     // --- 屬性 ---
     // 是否抗鋸齒 (可抗鋸齒)
     paint.setAntiAlias(true);
     // 是否抖動 (可使線條柔和)
     paint.setDither(true);
     // 對位圖進行濾波處理 (可加快顯示)
     paint.setFilterBitmap(true);
     // 設置着色器: BitmapShader / ComposeShader / LinearGradient / RadialGradient / SweepGradient
     paint.setShader(new LinearGradient(0, 0, copybitmap.getWidth(), 0, new int[]{Color.RED, Color.YELLOW, Color.BLUE}, null, LinearGradient.TileMode.CLAMP));
     // 設置顏色過濾器: ColorMatrixColorFilter / LightingColorFilter / PorterDuffColorFilter
     paint.setColorFilter(new ColorMatrixColorFilter(new ColorMatrix(new float[]{1, 0, 0, 0, 0,  0, 1, 0, 0, 0,  0, 0, 1, 0, 0,  0, 0, 0, 1, 0,})));
     // 設置疊加模式 PorterDuffXfermode(ADD / CLEAR / DARKEN / DST / DST_ATOP / DST_IN / DST_OUT / DST_OVER / LIGHTEN / MULTIPLY / OVERLAY / SCREEN / SRC / SRC_ATOP / SRC_IN / SRC_OUT / SRC_OVER / XOR)
     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
     // 設置路徑效果: ComposePathEffect / CornerPathEffect / DashPathEffect / DiscretePathEffect / PathDashPathEffect / SumPathEffect
     paint.setPathEffect(new CornerPathEffect(50));
     // 設置濾鏡: BlurMaskFilter(模糊) / EmbossMaskFilter(浮雕)
     // paint.setMaskFilter(new BlurMaskFilter(20, BlurMaskFilter.Blur.SOLID));

     // 是否不緩存文本
     paint.setLinearText(true);
     // 設置亞像素 (可使文字清晰)
     paint.setSubpixelText(true);
     // 設置文本下劃線
     paint.setUnderlineText(true);
     // 設置文本刪除線
     paint.setStrikeThruText(true);
     // 設置文本粗體
     paint.setFakeBoldText(true);
     // 設置字體樣式
     paint.setTypeface(Typeface.DEFAULT_BOLD);
     // 設置字體大小
     paint.setTextSize(100);
     // 設置陰影 (參數: 角度, 距離x,y, 顏色)
     paint.setShadowLayer(5, 10, 10, Color.BLACK);
     // 設置語言 api>17
     // paint.setTextLocale(Locale.getDefault());
     // 水平縮放 (放大 > 1 > 縮小)
     paint.setTextScaleX(1);
     // 傾斜
     paint.setTextSkewX(0);
     // 行間距 api>21
     // paint.setLetterSpacing(0);
     // 測量文字長度
     float width = paint.measureText("luzhuo.me");

     // 顏色
     paint.setColor(Color.RED);
     paint.setColor(Color.argb(50, 255, 100, 100));
     paint.setARGB(50, 255, 100, 100);
     // 透明度 [0,255]
     paint.setAlpha(50);
     // 寬度
     paint.setStrokeWidth(15);


     // 重置
     paint.reset();


     canvas.drawLine(20, 20, 500, 20, paint);
     canvas.drawText("luzhuo.me", 60, 60, paint);
     iv_copy.setImageBitmap(copybitmap);
 }

Shader

/**
  * Shader着色器, 具有圖片填充模式, 顏色填充模式(漸變), 圖片與顏色組合填充 的操作
  */
 public void shaderclick(View view){
     Bitmap srcbitmap = getBitmapOnRes(this, R.mipmap.abc);
     Bitmap copybitmap = Bitmap.createBitmap(1000, 1000, Bitmap.Config.ARGB_8888); // 白紙
     Canvas canvas = new Canvas(copybitmap);
     Paint paint = new Paint();

     Shader shader;
     Shader shader1;
     // 着色器: BitmapShader / ComposeShader / LinearGradient / RadialGradient / SweepGradient
     // BitmapShader(圖片填充模式)  TileMode(平鋪模式):CLAMP(拉伸最後一個像素) / MIRROR(翻轉) / REPEAT(重複)
     shader = new BitmapShader(srcbitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
     shader = new BitmapShader(srcbitmap, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR);
     shader1 = new BitmapShader(srcbitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);

     // LinearGradient(線性漸變)
     // (參數:起點x,y, 終點x,y, 漸變顏色[],  顏色分佈[0,1]/null, 填充模式)
     shader = new LinearGradient(0, 0, copybitmap.getWidth() / 2, copybitmap.getHeight() / 2, new int[]{Color.RED, Color.YELLOW, Color.BLUE}, null, Shader.TileMode.CLAMP);
     shader = new LinearGradient(0, 0, copybitmap.getWidth() / 2, copybitmap.getHeight() / 2, new int[]{Color.RED, Color.YELLOW, Color.BLUE}, null, Shader.TileMode.MIRROR);
     shader = new LinearGradient(0, 0, copybitmap.getWidth() / 2, copybitmap.getHeight() / 2, new int[]{Color.RED, Color.YELLOW, Color.BLUE}, null, Shader.TileMode.REPEAT);

     // RadialGradient(徑向漸變)
     shader = new RadialGradient(copybitmap.getWidth() / 2, copybitmap.getHeight() / 2, 300, new int[]{Color.RED, Color.YELLOW, Color.BLUE}, null, Shader.TileMode.CLAMP);
     shader = new RadialGradient(copybitmap.getWidth() / 2, copybitmap.getHeight() / 2, 300, new int[]{Color.RED, Color.YELLOW, Color.BLUE}, null, Shader.TileMode.MIRROR);
     shader = new RadialGradient(copybitmap.getWidth() / 2, copybitmap.getHeight() / 2, 300, new int[]{Color.RED, Color.YELLOW, Color.BLUE}, null, Shader.TileMode.REPEAT);

     // SweepGradient(掃描漸變)
     shader = new SweepGradient(copybitmap.getWidth() / 2, copybitmap.getHeight() / 2, new int[]{Color.RED, Color.YELLOW, Color.BLUE}, null);

     // ComposeShader(組合渲染)
     // (參數: 渲染器1, 渲染器2, 組合模式Xfermode/PorterDuff.Mode)
     shader = new ComposeShader(shader, shader1, new PorterDuffXfermode(PorterDuff.Mode.ADD));

     paint.setShader(shader);


     // 矩形方框用於限制 Shader 的範圍
     canvas.drawRect(0, 0, 1000, 1000, paint);
     iv_copy.setImageBitmap(copybitmap);
 }

ColorFilter

 /**
  * colorFilter顏色過濾操作, 可通過 顏色矩陣過濾 光照過濾 顏色疊加過濾 等過濾方式
  */
 public void colorFilterClick(View view){
     Bitmap srcbitmap = MainActivity.getBitmapOnRes(this, R.mipmap.abc);
     Bitmap copybitmap = Bitmap.createBitmap(1000, 1000, Bitmap.Config.ARGB_8888); // 白紙
     Canvas canvas = new Canvas(copybitmap); // 畫布
     Paint paint = new Paint(); // 畫筆

     /*
     ColorMatrix顏色矩陣4*5 (矩陣不會調, 可以調用其方法)
     m = [ a, b, c, d, e,   C = [ R
           f, g, h, i, j,         G
           k, l, m, n, o,         B
           p, q, r, s, t ]        A ]

     R' = a*R + b*G + c*B + d*A + e
     G' = f*R + g*G + h*B + i*A + j
     B' = k*R + l*G + m*B + n*A + o
     A' = p*R + q*G + r*B + s*A + t
     */
     ColorMatrix colorMatrix = new ColorMatrix(new float[]{
             1, 0, 0, 0, 0,
             0, 1, 0, 0, 0,
             0, 0, 1, 0, 0,
             0, 0, 0, 1, 0,});
     colorMatrix.setRotate(0, 50); // 色調(參數: 顏色:0RED/1GREEN/2BLUE)
     colorMatrix.setSaturation(99); // 飽和度
     colorMatrix.setScale(5, 5, 5, 10); // 亮度

     ColorFilter colorFilter;
     // 設置顏色過濾器: ColorMatrixColorFilter / LightingColorFilter / PorterDuffColorFilter
     // ColorMatrixColorFilter(顏色矩陣過濾)
     colorFilter = new ColorMatrixColorFilter(colorMatrix);

     // LightingColorFilter(光照過濾) (參數:與原色相乘, 與原色相加) R' = R * mul.R + add.R
     colorFilter = new LightingColorFilter(0xFFFFFF00, 0x00000000);

     // PorterDuffColorFilter(波特達夫混合模式)
     colorFilter = new PorterDuffColorFilter(0XFFFFFF00, PorterDuff.Mode.MULTIPLY);

     /*
     PorterDuff.Mode:

     CLEAR       (0), 清除圖像
     SRC         (1), 只顯示src
     DST         (2), 只顯示dst
     SRC_OVER    (3), src局頂
     DST_OVER    (4), dst局頂
     SRC_IN      (5), 交集, 取src
     DST_IN      (6), 交集, 取dst
     SRC_OUT     (7), 不相交, 取src
     DST_OUT     (8), 不相交, 取dst
     SRC_ATOP    (9), 交集src, 不相交dest
     DST_ATOP    (10), 交集dst, 不相交src
     XOR         (11), 異或

     DARKEN      (16), 取全部, 變暗
     LIGHTEN     (17), 取全部, 變亮
     MULTIPLY    (13), 取全部, 正片疊底
     SCREEN      (14), 取全部, 濾色
     ADD         (12), 取全部, 線性減淡
     OVERLAY     (15); 取全部, 疊加
      */

     paint.setColorFilter(colorFilter);
     canvas.drawBitmap(srcbitmap, new Matrix(), paint);
     iv_copy.setImageBitmap(copybitmap);
 }

PorterDuff.Mode

PorterDuffXfermode

paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));

見 PorterDuff.Mode

PathEffect

/**
  * PathEffect的操作, 可對path進行 角處理, 線段處理, 線段組合等操作
  */
 public void pathEffectClick(View view){
     Bitmap copybitmap = Bitmap.createBitmap(1000, 1000, Bitmap.Config.ARGB_8888); // 白紙
     Canvas canvas = new Canvas(copybitmap); // 畫布
     Paint paint = new Paint(); // 畫筆
     paint.setStyle(Paint.Style.STROKE);
     paint.setStrokeWidth(10);
     Path path = new Path();
     path.addRect(10, 10, 600, 600, Path.Direction.CW);


     PathEffect pathEffect, pathEffect1, pathEffect2;
     Path path1 = new Path();
     path1.addCircle(100, 100, 5, Path.Direction.CW);
     // --- 屬性 ---
     // 設置路徑效果: ComposePathEffect / CornerPathEffect / DashPathEffect / DiscretePathEffect / PathDashPathEffect / SumPathEffectSumPathEffect
     // CornerPathEffect(線段之間的直角變圓角)
     pathEffect1 = new CornerPathEffect(50);
     // DashPathEffect(虛線) (參數:[實線長度, 空線長度, ...] , 起始偏移量)
     pathEffect2 = new DashPathEffect(new float[]{10, 10}, 1);
     // DiscretePathEffect(離散線段) (參數:線段長度, 線段偏移量)
     pathEffect = new DiscretePathEffect(10, 10);
     // PathDashPathEffect(用指定path實線的虛線) (參數:間隔, 起始偏移量, 模式) 模式:TRANSLATE平移, ROTATE旋轉, MORPH連接處平滑
     pathEffect = new PathDashPathEffect(path1, 30, 0, PathDashPathEffect.Style.TRANSLATE);
     pathEffect = new PathDashPathEffect(path1, 30, 0, PathDashPathEffect.Style.ROTATE);
     pathEffect = new PathDashPathEffect(path1, 30, 0, PathDashPathEffect.Style.MORPH);
     // SumPathEffectSumPathEffect(path疊加)
     pathEffect = new SumPathEffect(pathEffect1, pathEffect2);
     // ComposePathEffect(path組合)(注意path先後順序)
     pathEffect = new ComposePathEffect(pathEffect2, pathEffect1);


     paint.setPathEffect(pathEffect);
     canvas.drawPath(path, paint);
     iv_copy.setImageBitmap(copybitmap);
 }

MaskFilter

 /**
  * MaskFilter操作, 可繪製 陰影, 浮雕 效果
  */
 public void maskFilterClick(View view){
     Bitmap copybitmap = Bitmap.createBitmap(1000, 1000, Bitmap.Config.ARGB_8888); // 白紙
     Canvas canvas = new Canvas(copybitmap); // 畫布
     Paint paint = new Paint(); // 畫筆
     paint.setColor(Color.argb(100, 255, 0, 0));


     MaskFilter maskFilter;
     // 設置濾鏡: BlurMaskFilter(模糊) / EmbossMaskFilter(浮雕)
     // BlurMaskFilter(模糊) (參數:擴散範圍, 類型) 類型:SOLID(陰影不融合) / NORMAL(陰影融合) / OUTER(外陰影) / INNER(內陰影)
     maskFilter = new BlurMaskFilter(30, BlurMaskFilter.Blur.SOLID);
     maskFilter = new BlurMaskFilter(20, BlurMaskFilter.Blur.NORMAL);
     maskFilter = new BlurMaskFilter(20, BlurMaskFilter.Blur.OUTER);
     maskFilter = new BlurMaskFilter(20, BlurMaskFilter.Blur.INNER);

     // EmbossMaskFilter(浮雕) (參數:光源tan[x,y,z], 暗部光線, 亮部光線, 突出的距離)
     maskFilter = new EmbossMaskFilter(new float[]{1, 1, 1}, 0.1f, 10, 10);


     paint.setMaskFilter(maskFilter);
     canvas.drawRect(10, 10, 600, 600, paint);
     iv_copy.setImageBitmap(copybitmap);
 }

BlurMaskFilter.Blur

路徑

/**
 * Path路徑的操作, 具有 線, 布爾, 反向, 平移 等操作
 */
public void onclick(View view){
    Bitmap copybitmap = Bitmap.createBitmap(1000, 1000, Bitmap.Config.ARGB_8888); // 白紙
    Canvas canvas = new Canvas(copybitmap); // 畫布
    Paint paint = new Paint(); // 畫筆
    paint.setStyle(Paint.Style.STROKE);

    Path path = new Path(); // 路徑


    // 移動畫筆
    path.moveTo(10, 50);
    // 繪製直線
    path.lineTo(30, 100);
    // 繪製貝塞爾曲線(參數:控制點x,y, 終點x1,y1)
    path.quadTo(100, 50, 150, 150); // 2次
    path.cubicTo(0, 150, 300, 450, 0, 600); // 3次 (參數: 控制點x,y, 控制點x1,y1, 終點x2,y2)
    // 繪製圓弧 (參數:矩形, 起始角度, 繪製角度, 是否首尾相連:false相連)
    path.arcTo(new RectF(0, 0, 300, 300), 0, 90, false);
    // 閉合路徑(首尾相連)
    path.close();


    // --- addxxx 添加xxx到路徑中 ---
    // addArc、addRoundRect、addOval、addRect、addCircle
    // 添加圓弧到路徑中
    path.addArc(new RectF(10, 10, 100, 100), 0, 180);
    // 添加矩形
    path.addRect(new RectF(10, 110, 200, 200), Path.Direction.CW); // CW:順時針 / CCW:逆時針
    // 添加圓角矩形
    path.addRoundRect(new RectF(10, 210, 300, 300), 25, 25, Path.Direction.CW);
    // 添加橢圓
    path.addOval(new RectF(10, 310, 400, 400), Path.Direction.CW);
    // 添加圓
    path.addCircle(100, 410, 50, Path.Direction.CW);

    canvas.drawPath(path, paint);
    paint.setStyle(Paint.Style.FILL);
    paint.setARGB(80, 255, 100, 100);



    path = new Path();
    Path path1 = new Path();
    path.addCircle(200, 200, 100, Path.Direction.CW);
    path1.addRect(200, 200, 300, 300, Path.Direction.CW);

    // --- Path.Op 路徑布爾模式 api >= 19 (疊加) ---
    // DIFFERENCE:刪除
    path.op(path1, Path.Op.DIFFERENCE);
    // INTERSECT:相交
    path.op(path1, Path.Op.INTERSECT);
    // REVERSE_DIFFERENCE:反向刪除(DIFFERENCE相反)
    path.op(path1, Path.Op.REVERSE_DIFFERENCE);
    // UNION:相加
    path.op(path1, Path.Op.UNION);
    // XOR:異或
    path.op(path1, Path.Op.XOR);

    path.addRect(200, 200, 300, 300, Path.Direction.CW);
// --- FillType 填充樣式 ---
    // WINDING:相加
    path.setFillType(Path.FillType.WINDING);
    // EVEN_ODD:異或
    path.setFillType(Path.FillType.EVEN_ODD);
    // INVERSE_WINDING:相加後反向
    path.setFillType(Path.FillType.INVERSE_WINDING);
    // INVERSE_EVEN_ODD:異或後反向
    path.setFillType(Path.FillType.INVERSE_EVEN_ODD);
    // 是否是反向填充
    boolean isInverse = path.isInverseFillType(); // false:WINDING / EVEN_ODD; true:INVERSE_WINDING / INVERSE_EVEN_ODD
    // 進行反向填充
    path.toggleInverseFillType();



    // 平移
    path.offset(100, 100);


    canvas.drawPath(path, paint);
    iv_copy.setImageBitmap(copybitmap);
}

Path.Op

Path.FillType

Bezier曲線

基礎知識

代碼實現

 // 二階曲線的繪製方法 (三個點: 起點x,y, 控制點x,y, 終點x,y)
mPath.moveTo(mStartPointX, mStartPointY);
 mPath.quadTo(mFlagPointX, mFlagPointY, mEndPointX, mEndPointY); // quadTo絕對座標 / rQuadTo 相對座標

 // 三階曲線的繪製方法 (四個點: 起點x,y, 控制點x1,y1, 控制點x2,y2, 終點x,y)
mPath.moveTo(mStartPointX, mStartPointY);
 mPath.cubicTo(mFlagPointOneX, mFlagPointOneY, mFlagPointTwoX, mFlagPointTwoY, mEndPointX, mEndPointY);

// Android Path路徑只提供兩種貝塞爾曲線繪製方法

圖片繪製與屬性動畫結合

詳見 Android 繪製動畫 部分

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