本文由 Luzhuo 编写,转发请保留该信息.
原文: https://blog.csdn.net/Rozol/article/details/79683220
将图片加载到内存显示之前, 要先根据将要显示的容器的大小来按比例压缩图片, 这样才不至于将内存撑爆.
/**
* 加载图片
*
步骤: 获取手机和图片分辨率 -> 计算缩放比 -> 加载图片(用最大的缩放比)
*/
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着色器, 具有图片填充模式, 颜色填充模式(渐变), 图片与颜色组合填充 的操作
*/
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颜色过滤操作, 可通过 颜色矩阵过滤 光照过滤 颜色叠加过滤 等过滤方式
*/
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);
}
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
见 PorterDuff.Mode
/**
* 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操作, 可绘制 阴影, 浮雕 效果
*/
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);
}
资料:
// 二阶曲线的绘制方法 (三个点: 起点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 绘制动画 部分