最近实现一个业务需求,要求将用户头像、用户名和正文内容合成为一张图片,以作为给微信小程序分享的封面图。通过一些ImageView控件是很容易实现圆形头像的,但这里需要创建一块画布,在Canvas上画出圆形头像,如果细节处理不好,可能达不到理想的效果。
通常用Java代码绘制圆形图有三种方法,分别是使用BitmapShader、PorterDuffXfermode和ClipPath。这里记录一下这三种画圆形图的代码实现:

BitmapShager 图片渲染方式

public Bitmap getCirleBitmap(Bitmap bmp) {
    //获取bmp的宽高 小的一个做为圆的直径r
    int w = bmp.getWidth();
    int h = bmp.getHeight();
    int r = Math.min(w, h);
 
    //创建一个paint
    Paint paint = new Paint();
    paint.setAntiAlias(true);
 
    //新创建一个Bitmap对象newBitmap 宽高都是r
    Bitmap newBitmap = Bitmap.createBitmap(r, r, Bitmap.Config.ARGB_8888);
 
    //创建一个使用newBitmap的Canvas对象
    Canvas canvas = new Canvas(newBitmap);
 
    //创建一个BitmapShader对象 使用传递过来的原Bitmap对象bmp
    BitmapShader bitmapShader = new BitmapShader(bmp, Shader.TileMode.CLAMP,Shader.TileMode.CLAMP);
 
    //paint设置shader
    paint.setShader(bitmapShader);
 
    //canvas画一个圆 使用设置了shader的paint
    canvas.drawCircle(r / 2, r / 2, r / 2, paint);
   
    return newBitmap;
}

PorterDuffXfermode 图片混合模式

    public Bitmap getCirleBitmap(Bitmap bmp) {
        //获取bmp的宽高 小的一个做为圆的直径r
        int w = bmp.getWidth();
        int h = bmp.getHeight();
        int r = Math.min(w, h);
 
        //创建一个paint
        Paint paint = new Paint();
        paint.setAntiAlias(true);
 
        //新创建一个Bitmap对象newBitmap 宽高都是r
        Bitmap newBitmap = Bitmap.createBitmap(r, r, Bitmap.Config.ARGB_8888);
 
        //创建一个使用newBitmap的Canvas对象
        Canvas canvas = new Canvas(newBitmap);
 
        //canvas画一个圆形
        canvas.drawCircle(r / 2, r / 2, r / 2, paint);
 
        //然后 paint要设置Xfermode 模式为SRC_IN 显示上层图像(后绘制的一个)的相交部分
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
 
        //canvas调用drawBitmap直接将bmp对象画在画布上 
        //因为paint设置了Xfermode,所以最终只会显示这个bmp的一部分 
        //也就是bmp的和下层圆形相交的一部分圆形的内容
        canvas.drawBitmap(bmp, 0, 0, paint);
 
        return newBitmap;
    }

ClipPath 裁剪区域

public Bitmap getCirleBitmap(Bitmap bmp) {
    //获取bmp的宽高 小的一个做为圆的直径r
    int w = bmp.getWidth();
    int h = bmp.getHeight();
    int r = Math.min(w, h);
 
    //创建一个paint
    Paint paint = new Paint();
    paint.setAntiAlias(true);
 
    //新创建一个Bitmap对象newBitmap 宽高都是r
    Bitmap newBitmap = Bitmap.createBitmap(r, r, Bitmap.Config.ARGB_8888);
 
    //创建一个使用newBitmap的Canvas对象
    Canvas canvas = new Canvas(newBitmap);
 
    //创建一个Path对象,path添加一个圆 圆心半径均是r / 2, Path.Direction.CW顺时针方向
    Path path = new Path();
    path.addCircle(r / 2, r / 2, r / 2, Path.Direction.CW);
    //canvas绘制裁剪区域
    canvas.clipPath(path);   
    //canvas将图画到留下的圆形区域上
    canvas.drawBitmap(bmp, 0, 0, paint);
 
    return newBitmap;
}