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路徑只提供兩種貝塞爾曲線繪製方法