前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iOS多边形马赛克的实现(下)

iOS多边形马赛克的实现(下)

作者头像
天天P图攻城狮
发布2018-02-02 16:11:02
1.6K2
发布2018-02-02 16:11:02
举报
文章被收录于专栏:天天P图攻城狮天天P图攻城狮

上一篇里我们详述了多边形马赛克的实现步骤,末尾提出了一个思考:如何在涂抹时让马赛克逐块显示呢?

再回顾一下多边形马赛克的实现。首先进行图片预处理,将原图转成bitmap后生成铺满马赛克的全图。手指移动的时候从touch回调里获取坐标点,在这些点之间进行插值,然后以插值之后的路径点为圆心将马赛克图层里对应的区域贴过去,这样就完成了对图像的特定区域打码的处理。

试想一下,如果上述步骤不变,要想让多边形马赛克一块一块的显示出来,首先得计算手指移动时经过了哪些马赛克块。具体来说,也就是在每一次touchMove的回调都需要计算若干个圆形与哪些多边形马赛克相交。多边形相交的运算是十分复杂的,考虑到我们的马赛克模块还是在cpu上计算,如何让整个过程的复杂度降低成为必须要考虑的问题。

第一步:计算手指移动所覆盖到的马赛克单元

为了解决这个问题,我给每一个马赛克素材图片加入“重心”的概念。所谓的重心,指的是图片有效区域的中心,而不是整张图的中心点。以拼图马赛克为例

给左图设置的重心是(0.25, 0.5),右图的重心是(0.75, 0.5)。考虑到素材会缩放以调整单位马赛克大小,这里的x, y分别以素材的宽高为基准。

在这样的定义下,我们可以将前面的问题简化为:找到手指移动过的区域包含了哪些马赛克块的重心,然后将这些马赛克显示出来。具体来说,则是遍历插值之后的坐标点,找到距离该点在特定半径之内的马赛克重心,然后绘制这些马赛克块。这里的半径是根据用户所选笔触大小计算出的一个数值,笔触越粗则半径越大,手指移动绘制出的马赛克块也更多一些。比如下图范围内的4块马赛克应该显示出来。

之前预处理的时候,我们需要根据马赛克素材的各种规则定义生成铺满马赛克的全图。而现在我们是将马赛克逐块绘制,显而易见生成全图已经没必要了。这里我们需要初始化马赛克行数、列数、横向间距、纵向间距等参数,以便手指移动的时候计算经过了哪些马赛克块。初始化的代码如下

在这样的设定下,我们将多边形相交的运算简化为点与点之间的距离计算,复杂度大大降低。

第二步:绘制

前面详述了如何找出手指移动区域所覆盖的马赛克块,那么如何给这些马赛克块上色呢?上一篇里我们讲到,通过遍历maskImage对应的有效颜色区域,求出该区域的rgb平均值即可。试想一下,在大多数机型上touch事件的回调频率可高达60Hz。也就是说,在1/60秒的时间里,我们需要完成插值、找到马赛克块、以及绘制马赛克块等步骤,如果在绘制的时候还需要计算平均rgb值,有可能会因为计算量太大而造成UI卡顿。因此这里我们将求平均rgb值改为直接取该马赛克区域重心的颜色,以简化整个绘制的过程。以正方形马赛克为例,下面两图分别是取平均值和重心(正方形的中心点)颜色所生成的全图马赛克效果。

可以看到取中心点生成的马赛克图片似乎更鲜活一些。当然如果一定要取马赛克区域的平均rgb值也是可以的,在预处理的时候事先计算好每个马赛克块的平均颜色即可。

代码语言:javascript
复制

现在看看我们用新方案实现的涂抹绘制多边形马赛克效果吧。

大功告成!看起来可还行?事实上在实现过程中也是遇到了各种坑,接下来说一下主要遇到的问题。

边界问题

以六边形马赛克为例,放大图片的边缘区域如下。

可以看到,由于列间距只有单元格高度的0.5倍,因此我们在计算单元格行数和列数的时候最好是在首尾各预留一行/列以免边缘地方出现遮盖不到的情况(考虑一下行/列间距如果小于0.5是否会有问题?)

另外在计算马赛克重心的时候,可以看到边缘地方的马赛克块重心很有可能不在图片范围内。所以这里一定要做好预防,否则涂抹到边缘时候很有可能crash(CLAMP函数第二、三个参数分别对应最小、最大值)。

叠加顺序问题

我们来看一下这种类型的马赛克。

这是一种正方形内嵌圆形的马赛克,其素材由4个角以及中间的圆形一共5张图构成。

设计师期望的是,在手指移动过程中,这种素材能以正方形单元格为整体一起显示出来。而且他们的叠加顺序也是固定的:先绘制4个角,最后再绘制中间的圆形以免圆形区域被遮挡。对于这样的素材,我给它额外添加了一个subType来做区分处理。在手指移动时用前面的方法判断移动区域是否包含该单元格中心,如包含,将该单元格的马赛克块按顺序依次绘制出来即可。

实现出来的效果如下图所示。

总结

回顾上下两篇iOS多边形马赛克实现,主要研究和探讨了以下几个问题:针对各种形状的多边形找到通用平铺规则;手指移动时判断经过了哪些马赛克块;计算颜色及绘制;消除锯齿问题、边界问题以及叠加顺序问题。有兴趣的朋友可以试用一下天天P图的马赛克模块哦~


作者简介:jennysluo(罗爽),天天P图iOS工程师

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-01-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 天天P图攻城狮 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第一步:计算手指移动所覆盖到的马赛克单元
  • 第二步:绘制
  • 边界问题
  • 叠加顺序问题
  • 总结
相关产品与服务
图像处理
图像处理基于腾讯云深度学习等人工智能技术,提供综合性的图像优化处理服务,包括图像质量评估、图像清晰度增强、图像智能裁剪等。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档