圆形头像制作,仿QQ做法。

一.先展示一下效果吧。

 

 

 

PorterDuffXfermode

上代码之前我们先来了解一个类PorterDuffXfermode。

 

使用 PorterDuff 模式可以创建一个图层混合模式,下面就是18中混合模式

 

 

// these value must match their native equivalents. See SkPorterDuff.h
    public enum Mode {
        /** [0, 0] */
        CLEAR       (0),
        /** [Sa, Sc] */
        SRC         (1),
        /** [Da, Dc] */
        DST         (2),
        /** [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] */
        SRC_OVER    (3),
        /** [Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc] */
        DST_OVER    (4),
        /** [Sa * Da, Sc * Da] */
        SRC_IN      (5),
        /** [Sa * Da, Sa * Dc] */
        DST_IN      (6),
        /** [Sa * (1 - Da), Sc * (1 - Da)] */
        SRC_OUT     (7),
        /** [Da * (1 - Sa), Dc * (1 - Sa)] */
        DST_OUT     (8),
        /** [Da, Sc * Da + (1 - Sa) * Dc] */
        SRC_ATOP    (9),
        /** [Sa, Sa * Dc + Sc * (1 - Da)] */
        DST_ATOP    (10),
        /** [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] */
        XOR         (11),
        /** [Sa + Da - Sa*Da,
             Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)] */
        DARKEN      (12),
        /** [Sa + Da - Sa*Da,
             Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)] */
        LIGHTEN     (13),
        /** [Sa * Da, Sc * Dc] */
        MULTIPLY    (14),
        /** [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] */
        SCREEN      (15),
        /** Saturate(S + D) */
        ADD         (16),
        OVERLAY     (17);

 

 

 

 

 

 

其中 Sa 代表source alpha ,即源 alpha 值 ,Da 代表 Destination alpha ,即 目标alpha值 ,Sc 代表 source color ,即源色值 ,Dc 代表 Destination color ,即目标色值,并且这所有的计算都以像素为单位,在某一种混合模式下,对每一个像素的alpha 和 color 通过对应算法进行运算,得出新的像素值,进行展示;具体的例子请网上寻找例子探索。

 

制作圆形头像

现在直接进入我们的主题---制作圆形头像!

从结果上来看应该需要一个圆,一张正方形的头像。

预想方法一:底部一个圆,然后在绘制一张头像在圆上,利用圆来限制头像的显示大小。

 

 

 public void initBitmap() {

        //禁用硬件加速器,因为有些硬件加速器不支持
        setLayerType(LAYER_TYPE_SOFTWARE, null);
        //设置抗锯齿
        mpaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mpaint.setColor(Color.YELLOW);
<span style="line-height: 21.06px;"><span style="white-space: pre;">	</span>//创建以头像为底图</span>
        mbitmap = BitmapFactory.decodeResource(getResources(), R.drawable.head);
        //以后的绘制都将显示在moutbitmap上面
        moutbitmap = Bitmap.createBitmap(mbitmap.getWidth(), mbitmap.getHeight(), Config.ARGB_8888);
        Canvas canvas_outbitmap = new Canvas(moutbitmap);

        //Dst
        canvas_outbitmap.drawCircle(mbitmap.getWidth() / 2, mbitmap.getHeight() / 2, mbitmap.getWidth() / 2, mpaint);
        PorterDuffXfermode mode = new PorterDuffXfermode(Mode.SRC_IN);
        mpaint.setXfermode(mode);
        //Src
        canvas_outbitmap.drawBitmap(mbitmap, 0, 0, mpaint);

    }

 

 @Override
    protected void onDraw(Canvas canvas) {
        Log.i("clx", "onDraw");
        canvas.drawBitmap(moutbitmap, 0, 0, null);
    }


  mbitmap = BitmapFactory.decodeResource(getResources(), R.drawable.head);
        //以后的绘制都将显示在moutbitmap上面
        moutbitmap = Bitmap.createBitmap(mbitmap.getWidth(), mbitmap.getHeight(), Config.ARGB_8888);
        Canvas canvas_outbitmap = new Canvas(moutbitmap);

 

 

 

创建一张BitMap图,大小为原图的大小mbitmap.getWidth(), mbitmap.getHeight()。

因为在直接在BitMap上修改,所以创建一个Canvas画布,new Canvas(moutbitmap),在该canvas上绘制相当于在刚创建的Bitmap上绘制。

接下来就在该画布上涂涂改改咯。

混合模式就是两个图层叠加绘制,所以首先先绘制目标图层(可以理解成最底下的图层)

 canvas_outbitmap.drawCircle(mbitmap.getWidth() / 2, mbitmap.getHeight() / 2, mbitmap.getWidth() / 2, mpaint);

 

从参数来看绘制一个mbitmap大小的圆。

 

第二步就是把头像给混合上去。

需要什么样的混合模式首先要先设置,部分该mode的alpha是怎么混合了,直接看英文意思,Source In 就是接下来绘制源图层将限制在目标图层里。

  PorterDuffXfermode mode = new PorterDuffXfermode(Mode.SRC_IN);
        mpaint.setXfermode(mode);

 

第三步:绘制源图层。

        //Src
        canvas_outbitmap.drawBitmap(mbitmap, 0, 0, mpaint);

 

最后一步就是只需要把混合好的bitmap绘制到你的屏幕就好了。

 

 canvas.drawBitmap(moutbitmap, 0, 0, null);

 

 

 

 

 

-----待续------

 

 

 

“老师!!!,我还有另一种做法!!!!”

 

上面一种方法的最底层的图层是使用drawCircle绘制的,现在我们使用另一种方式,我们不用画圆,直接使用一张圆的图。

 

绘制的步骤差不多。

 

 

 // 从canvas层面去除锯齿
        canvas.setDrawFilter(mDrawFilter);
        canvas.drawColor(Color.TRANSPARENT);

        int sc = canvas.saveLayer(0, 0, mTotalWidth, mTotalHeight, null, Canvas.ALL_SAVE_FLAG);

        // 绘制波纹部分
        canvas.drawBitmap(mSrcBitmap, mSrcRect, mDestRect, mBitmapPaint);

        // 设置图像的混合模式
        mBitmapPaint.setXfermode(mPorterDuffXfermode);
        // 绘制遮罩圆
        canvas.drawBitmap(mMaskBitmap, mMaskSrcRect, mMaskDestRect, mBitmapPaint);
        mBitmapPaint.setXfermode(null);

        /**
         * canvas.saveLayer()方法会返回一个int值,用于表示layer的ID,
         * 在我们对这个新layer绘制完成后可以通过调用canvas.restoreToCount(layer)
         * 或者canvas.restore()把这个layer绘制到canvas默认的layer上去,这样就完成了一个layer的绘制工作。
         */
        canvas.restoreToCount(sc);

 

 

 

 

 

这里就不分析了。

代码代码

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值