zoukankan      html  css  js  c++  java
  • 【PS算法理论探讨一】 Photoshop中两个32位图像混合的计算公式(含不透明度和图层混合模式)。

          大家可以在网上搜索相关的主题啊,你可以搜索到一堆,不过似乎没有那一个讲的很全面,我这里抽空整理和测试一下数据,分享给大家。

          我们假定有2个32位的图层,图层BG和图层FG,其中图层BG是背景层(位于下部),图层FG是前景层(位于上部),我们摸索其混合后的颜色的计算公式。

          我们取一个点的像素做分析:

                 其中BG层某点的颜色为: B1 = 168    G1 = 99     R1= 114    A1 = 70

                 其中FG层某点的颜色为: B2= 80       G2 = 71     R2= 162    A2 = 135

    场景一:两个图层直接叠加

               即混合模式为正常,前景的不透明度为100%,如下所示:  

                                     

             得到的混合结果为  B = 97         G = 76          R = 153        A = 168

             注意这些数据的格式都是 Format32bppArgb,而非Format32bppPArgb,即没有进行预乘的ARGB数据。

             根据这些数据进行推算,得出以下规律,首先是结果色的A值计算公式如下:

                  

             其中ClampToByte函数的作用为限制括号内的数据在0和255之间,如果大于255,则取255,如果小于0,则取0值。

             按照此公式复核下上面的结果看下:

               

            结果正确。

            对于RGB各分量,计算公式要复杂很多,经过推到和测试结果如下(以B分量为例):

                 

              把数据带入核算一下:

          

             同理:

           

           公式完全正确。

          上面的计算如果要保证精度,则A值需要用浮点数保存,这样可能在某些场合下造成计算瓶颈,如果要全部用整数运算,可利用用Matlab的符号运算在做简化。

          在matlab中用如下代码做测试:

    syms B1 A1 B2 A2;
    B =( B1 * A1 + B2 * A2 - A1 * A2 / 255 * B1) / (A1 + A2 - A1 * A2 / 255);
    simplify(B)

           得到结果:

                    B1 - (255*A2*(B1 - B2))/(255*A2 - A1*(A2 - 255))

            这个结果只有一个除法,而且可以看到除法的分子和分母的数据也不会大于int32所能表达的范围。这样可借助于整数的除法实现结果。

    场景二:仅仅改变图层混合模式

            我们仅仅改变前景色图层的混合模式,而不改变其不透明度。以正片叠底模式为例,如下图所示:       

                            

            此时前述两个颜色的混合值如下所示:

                      B = 91          G = 67          R = 133        A = 168

           注意到A值并没有任何的变化。

           此时,我们定义一个函数F,表示混合模式对两种的颜色影响,F(X, Y)表示某种混合模式下两种颜色值X和Y的混合结果,对于正片叠底,F(X,Y)的计算方法为:

                         F(X,Y) = X * Y / 255;

           经过测试,这个时候的RGB分量的混合公式为:

                   

            把数据带入核算一下:

              

            G和R的值就不进行重复的核算了。

            这个计算式用Maltab去简化的话基本没有任何效果。

    场景三:仅仅改变图层的不透明度

             如下所示设置,前景层的不透明度为70%。

                                   

           此时前述两个颜色的混合值如下所示:

                           B = 108        G = 80          R = 147        A = 139

           所有的颜色都变了。

           还是先来看A值,经过测试比对,此时A值的计算公式为:

                

            其中O表示不透明度的值,有效范围是[0,100]。

            核算一下:

                

           对于A值,我们可以认为不透明度首先修改了改成的Alpha,然后再拿这个新的Alpha和底层的Alpha进行正常的混合。

           对于RGB各分量,经过推到和测试结果如下(以B分量为例):

               

            核算一下:

               

           正确无误。

     场景四:同时改变图层混合模式和不透明度

            如下所示设置,同时设置混合模式为正片叠底,不透明度为70%。

                              

              此时前述两个颜色的混合值如下所示:

                       B = 103        G = 72          R = 130        A = 139

              可以看到,A值和混合模式没啥关系,之和不透明度有关,直接用只改变不透明度时的公式:

                   

            那么RGB的变化,从前面的几个公式中可以猜测肯定是先下面这个式子了:

                 

            测试下:

               

            完全正确。

            那么在写代码的时候,我们最需要优化的就是这个情况的公式。不过用matlab测试这个公式没啥好优化的。

           上述公式里其实有些ClampToByte函数是可以不需要的。

           上传下我用于测试两个小的32位图像了供有兴趣的朋友测试。

                    

            图片非常小啊,注意仔细观察并下载。

           如果想时刻关注本人的最新文章,也可关注公众号:

                                     

  • 相关阅读:
    利用idea里面的mysql插件进行导入sql文件
    JSTL标签
    deepin20系统下配置JAVA开发环境
    deepin20安装及问题解决
    SpringBoot 在项目启之后执行自定义方法的两种方式
    Nick 的经验书
    Java 经验书
    SpringBoot 经验书
    Linux 经验书
    在MacOS中启动SSH服务
  • 原文地址:https://www.cnblogs.com/Imageshop/p/15661412.html
Copyright © 2011-2022 走看看