注册

Android 图片描边效果

前言


先看下我们阔爱滴海绵宝宝,其原图是一张PNG图片,我们给宝宝加上描边效果,今天我们使用的是图片蒙版技术。


fire_78.gif


说到蒙版可能很多人想起PS抠图软件,Android上也一样,同一个大树上可能会长出两种果实,但果实的根基是一样的。


什么是蒙版:所谓蒙版是只保留了alpha通道的一种二维正交投影,简单的说就是你躺在地上,太阳光直射下来,背后的那片就是你的蒙版。因此,它既不存在三维特征,也不存在色彩特征,只有alpha特征。那只有alpha通道的图片是什么颜色,这块没有具体了解过,但是理论上取决于默认填充色,在Android上最终是白色的,其他平台暂时还没了解。


提取蒙版


Android上提取蒙版比想象的容易,按照以往的思路,我们是要进行图片扫描这里,其实就是把所有颜色的red、green、blue都排除掉,只保留alpha,相当于缩小了通道数,排除采样和缩小图片,当然这个工作量是很大的,尤其是超高清图片。


企业微信20231210-120604@2x.png


Android 上提取蒙版,只需要把原图绘制到alpha通道的Bitmap上


bms = decodeBitmap(R.mipmap.mm_07);
bmm = Bitmap.createBitmap(bms.getWidth(), bms.getHeight(), Bitmap.Config.ALPHA_8);
Canvas canvas = new Canvas(bmm);
canvas.drawBitmap(bms, 0, 0, null);

蒙版绘制


蒙版绘制和其他Bitmap绘制是有差异的,ARGB_8888和RGB_565等色彩格式的图片,其本身是具备颜色的,但是蒙版图片不一样,他没有颜色,所以你绘制的时候,bitmap的颜色是你画笔Paint的填充色,突然想到可以做一个人体扫描的动画效果或者人体热力图。


canvas.drawBitmap(bmm, x, y, paint);

扩大蒙版(影子)


要让蒙版比比原图大,理论上是需要等比例放大蒙版在平移,还有一种方式是进行偏移绘制,我们这里使用偏移绘制。当然,这里取一定360,保证尽可能每个方向都有偏移,这是看到的外国人的算法。至于step>0 但是也要控制粒度,太小可能绘制次数太多,太大可能有些边缘做不到偏移。


for (int i = 0; i < 360; i += step) {
float x = width * (float) Math.cos(Math.toRadians(i));
float y = width * (float) Math.sin(Math.toRadians(i));
canvas.drawBitmap(bmm, x, y, paint);
}

闪烁效果


我们价格颜色闪烁的效果,其实很简单,也不是本篇重要的部份,其实就是在色彩中间插入透明色,然后定时闪烁。


int index = -1;
int max = 15;
int[] colors = new int[max];
final int[] highlightColors = {0xfff00000,0,0xffff9922,0,0xff00ff00,0};

public void shake() {
index = 0;
for (int i = 0; i < max; i+=2) {
colors[i] = highlightColors[i % highlightColors.length];
}
postInvalidate();
}

总结


本篇到这里就结束了,希望利用蒙版+偏移做出更多东西。


全部代码


public class ViewHighLight extends View {
final Bitmap bms; //source 原图
final Bitmap bmm; //mask 蒙版
final Paint paint;
final int width = 4;
final int step = 15; // 1...45
int index = -1;
int max = 15;
int[] colors = new int[max];
final int[] highlightColors = {0xfff00000,0,0xffff9922,0,0xff00ff00,0};
public ViewHighLight(Context context) {
super(context);
bms = decodeBitmap(R.mipmap.mm_07);
bmm = Bitmap.createBitmap(bms.getWidth(), bms.getHeight(), Bitmap.Config.ALPHA_8);
Canvas canvas = new Canvas(bmm);
canvas.drawBitmap(bms, 0, 0, null);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
}

private Bitmap decodeBitmap(int resId) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inMutable = true;
return BitmapFactory.decodeResource(getResources(), resId, options);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// draw blur shadow

for (int i = 0; i < 360; i += step) {
float x = width * (float) Math.cos(Math.toRadians(i));
float y = width * (float) Math.sin(Math.toRadians(i));
canvas.drawBitmap(bmm, x, y, paint);
}
canvas.drawBitmap(bms, 0, 0, null);

if(index == -1){
return;
}
index++;
if(index > max +1){
return;
}
if(index >= max){
paint.setColor(Color.TRANSPARENT);
}else{
paint.setColor(colors[index]);
}
postInvalidateDelayed(200);
}


public void shake() {
index = 0;
for (int i = 0; i < max; i+=2) {
colors[i] = highlightColors[i % highlightColors.length];
}
postInvalidate();
}
}

作者:时光少年
来源:juejin.cn/post/7310786575213920306

0 个评论

要回复文章请先登录注册