在图像处理应用中,将两张或者多张图片混合显示是非常常见的一种操作,应用场景包括但不限于:加水印、标签,插入画中画,遮盖等等。
最常见的图像混合模式是普通混合模式,比如加水印。对于叠加在原图上的水印图片,其中根据透明度来选择原图和水印图片像素所占的权重,从而可以形成一个半透明的水印。
除了普通混合模式外,还有多种图像混合模式,包括但不局限于:正片叠底(multiply)、滤色模式(screen)、叠加模式(overlay)、柔光模式(softlight)、强光模式(hardlight)、增加模式(add)、减去模式(subtract)等等。每一种混合模式都对应了一种函数T=F(S,D),其中,T是混合后的像素颜色,S表示用于混合的像素颜色,D表示底图的像素颜色(S,D,T的取值范围都是0~1)。
下面是各种混合模式的计算公式,这里选择最常见的12种混合模式作为例子。其它的混合模式可以类似实现。
混合模式 | 公式 | 条件、备注 |
---|---|---|
normal | T=S | |
multiply | T=S*D | |
screen | T=1-(1-S)*(1-D) | |
overlay | T=2*S*D | D<0.5 |
T=1-2*(1-S)*(1-D) | D>=0.5 | |
hardlight | T= 2*S*D | S<0.5 |
T=1-2*(1-S)*(1-D) | S>=0.5 | |
softlight | T=2*S*D+D*D*(1-2*S) | S<0.5 |
T=2*D*(1-S)+sqrt(D)*(2*S-1) | S>=0.5 | |
divide | T=D/S | D/S取0~1之间 |
add | T=D+S | D+S取0~1之间 |
subtract | T=D-S | D-S取0~1之间 |
diff | T=|D-S| | |
darken | T=MIN(D,S) | |
lighten | T=MAX(D,S) |
另外,当融合图片是半透明的时候(α值不是1),融合后的像素值T’=T*α+(1-α)*D。从中可以看出,当α为0时(全透明),T’=D,即融合图片不影响结果;当α为1时(不透明),T’=T。
具体的效果如下图所示:
底图: | 融合图: |
---|
融合结果:
底图: | 融合图: |
---|
融合结果:
看完了效果,那么,怎么在GPUImage里实现呢?这里就要实现自定义的FragmentShader了。
这里的返回值是T和S的α值,后续会有一个跟底图的α融合过程。该融合过程可以放在shader中实现,也可以让OpenGL自动实现。
1) 在render之前,设置:
这两句的含义是:让OpenGL根据α值自动融合结果;融合公式是:
T=S*α+(1-α)*D
2) glDrawArray
3) glDisable(GL_BLEND);
这样设置好之后,就可以实现原地多次增加贴图了(绘制在同一个frameBuffer上,不用两个frameBuffer来回倒腾),相当方便~
更多关于移动开发,图像处理的相关技术,请持续关注我们的公众号!
作者简介:dreamqian(钱梦仁),外号"大魔王",天天P图iOS工程师
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有