美文网首页
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