美文网首页
Android 编辑图片 Canvas画图,涂鸦,马赛克等(三)

Android 编辑图片 Canvas画图,涂鸦,马赛克等(三)

作者: BigP | 来源:发表于2019-02-28 15:19 被阅读0次

    需求功能详解

    单纯的编辑图片的功能,能够在界面上进行图形的绘制,线条的涂鸦,和画马赛克的绘制,并且有撤销的功能。

    画马赛克

    相对于涂鸦和画图形,马赛克的绘制可能会比较复杂,但是明白了马赛克的绘制原理之后,他与涂鸦也并无二致,下面让我们来揭开马赛克绘制的神秘面纱!

    Paint Xfermode

    在画马赛克之前,先要大概了解下Android 画笔PaintXfermode,那么什么是Xfermode,Xfermode国外有大神称之为过渡模式,这种翻译比较贴切但恐怕不易理解,大家也可以直接称之为图像混合模式,因为所谓的“过渡”其实就是图像混合的一种。查看API文档发现其果然有三个子类:AvoidXfermode, PixelXorXfermodePorterDuffXfermode,这三个子类实现的功能要比setColorFilter的三个子类复杂得多。由于AvoidXfermode, PixelXorXfermode都已经被标注为过时了,所以这次主要研究的是仍然在使用的PorterDuffXfermode

    • PorterDuffXfermode
      该类同样有且只有一个含参的构造方法PorterDuffXfermode(PorterDuff.Mode mode),虽说构造方法的签名列表里只有一个PorterDuff.Mode的参数,但是它可以实现很多酷毙的图形效果!!而PorterDuffXfermode就是图形混合模式的意思,其概念最早来自于SIGGRAPH的Tomas Proter和Tom Duff,混合图形的概念极大地推动了图形图像学的发展,延伸到计算机图形图像学像Adobe和AutoDesk公司著名的多款设计软件都可以说一定程度上受到影响,而我们PorterDuffXfermode的名字也来源于这俩人的人名组合PorterDuff,那PorterDuffXfermode能做些什么呢?我们先来看一张API DEMO里的图片:


      api图解

      这张图片从一定程度上形象地说明了图形混合的作用,两个图形一圆一方通过一定的计算产生不同的组合效果,在API中Android为我们提供了18种(比上图多了两种ADD和OVERLAY)模式。
      我们的马赛克效果,就是用这种图像混合的方式来实现的~

    实现思路

    实现的思路很简单,首先我们要获得一张基于原图的马赛克图像,然后做类似涂鸦功能的操作,最后再将图像组合起来,就能得到最终的马赛克路径了!

    • 获得马赛克位图
      如何获得马赛克位图呢,只要使用Bitmap自带的创建缩放图的API,并且使其不保真缩放,就能得到一张马赛克位图啦:
      生成马赛克图
      关键代码
    /**
     * 获取马赛克的bitmap
     */
    private Bitmap makeMosaicBitmap() {
        if (mMoasicBitmap != null) {
            return mMoasicBitmap;
        }
    
        int w = Math.round(mViewWidth / 16f);
        int h = Math.round(mViewHeight / 16f);
    
        if (mOriginBitmap != null) {
            // 先创建小图
            mMoasicBitmap = Bitmap.createScaledBitmap(mOriginBitmap, w, h, false);
            // 再把小图放大
            mMoasicBitmap = Bitmap.createScaledBitmap(mMoasicBitmap, mViewWidth, mViewHeight, false);
        }
        return mMoasicBitmap;
    }
    

    接下来,就是我们的重头戏了,使用我们上面介绍的Xfermode,将图像组合起来,就能得到如下图的效果:

    组合效果
    关键代码
    首先创建设置了Xfermode的马赛克专用画笔:
    mMosaicPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mMosaicPaint.setFilterBitmap(false);
    mMosaicPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
    

    然后根据涂鸦的路径,合并图层,就得到了马赛克效果:

    /**
     * 画马赛克内容
     */
    private void drawMosaicPath(Canvas canvas) {
        if (mMosaicPath.size() > 0 && mMoasicBitmap != null) {
            // 保存图层
            int layerCount = canvas.saveLayer(0, 0, mViewWidth, mViewHeight, null, Canvas.ALL_SAVE_FLAG);
            for (DrawPathBean mosaicPath : mMosaicPath) {
                canvas.drawPath(mosaicPath.path, mosaicPath.paint);
            }
            // 进行图层的合并
            canvas.drawBitmap(mMoasicBitmap, 0, 0, mMosaicPaint);
            canvas.restoreToCount(layerCount);
        }
    }
    

    总结

    至此,马赛克的绘制也结束了,其他操作也不再赘述,和第一篇的涂鸦功能可以说是一模一样的,除了最后在onDraw()中的绘制,多了图层的绘制合并。最后多谢看到这里的看官~

    参考

    Android Paint Xfermode 学习小结
    Android 图片编辑的原理与实现——涂鸦与马赛克

    前篇

    Android 编辑图片 Canvas画图,涂鸦,马赛克等(一)
    Android 编辑图片 Canvas画图,涂鸦,马赛克等(二)

    项目代码

    最后奉上完整的项目代码,欢迎clone和star和意见提交:
    https://github.com/wx9265661/SmallDemos2

    相关文章

      网友评论

          本文标题:Android 编辑图片 Canvas画图,涂鸦,马赛克等(三)

          本文链接:https://www.haomeiwen.com/subject/ymchuqtx.html