一渲染
第一种情况——位图渲染
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效果
保留覆盖源像素的目标像素,丢弃其余的源像素和目标像素。
我们看下两张图片