zoukankan      html  css  js  c++  java
  • 图像混合模式算法

    《转自》 http://blog.sina.com.cn/s/blog_62493c180100q8y0.html

    那么,先让我们先来弄清楚什么是混合模式。帮助文档解释为“图层的混合模式确定了其像素如何与图像中的下层像素进行混合。”我们知道,计算机操作的只是一系列用以存储颜色信息的二进制数据,简而言之,所谓混合模式就是一系列算法(algorithm),使用这些算法对像素自身的颜色值,下层像素的颜色值进行计算,生成新的数据,也就有了我们运用混合模式后产生的新图像。另外需要注意的是,这种操作是针对单个通道的灰度图数据(即level值)进行的,单个通道取值通过各种限制方法实现取值在0255之内,最后通过RGB模式表现为我们最终所见的颜色。明白了这些,如果你玩过Flash并且会写as代码,那么恭喜你,你完全有能力写出很多你自己的混合模式!听起来酷吧~~~

    一、 正常(normal

      public function normal(topPixel:uint, bottomPixel:uint):uint {

                           return topPixel;//返回topPixel 的值

                          }

       该模式下,下层图像像素值(bottomPixel)并不对图像产生影响,直接返回图像的值(topPixel).

    二、   溶解(Dissolve

       该模式随机的选取图像中的像素值进行删除,然后用下一图层对应位置的像素值填充。这种随机选取是跟透明度绑定的,你甚至可以把“删除”理解为将不透明度设置为0,随着透明度的增大,被删除的点(或不透明度被设置为0的像素点会不断增多!)。(南园参考的英文文章直译过来并非这样解释,但是根据实验,个人认为这样理解更合适。属个人理解,并不一定正确。)

        画笔工具栏里同样有溶解模式,我们选择较虚的笔触绘画时,溶解效果较明显,笔触的虚化运用了透明度调节,边缘透明度的变化使得溶解效果增强,它们的内在机制是一样的。

       注意:有必要拿正常模式和溶解模式进行比较,二者有很大的相似性。在图层不透明度都为100时,两者并无区别。但是当我们降低不透明度时便会发现二者的区别:正常模式是通过图层的原理实现两者的融合过渡,而溶解则是通过“随机删除对应填充”进行融合过渡的。

        请原谅在这里没有给出as代码,毕竟此处是在整理PS中的混合模式,而非Flash 中 AS语言操控的混合模式(两者实质上是一样的),AS也没有直接提供该模式,需要我们自己通过一些方法自己实现。可能的话,南园会在后续文章中整理AS语言对这些效果的操作,你会发现它棒极了。

    ***********************分界线*******************************

    三、 变暗(Darken

                     public function darken(topPixel:uint, bottomPixel:uint):uint {

                          return Math.min(topPixel, bottomPixel);//返回数值较小的像素值

                      }

           聪明的你一定知道return是返回的意思,也可能会猜到Math.min(topPixel, bottomPixel)是在对图像像素值(topPixel)和下层像素值(bottomPixel)进行数学比较,min 的意思是较小的,那么该函数会对两个像素值进行比较然后返回数值较小的作为计算后的结果,有显示色彩的基本原理知道,较小的值,会导致图像变暗(随着介绍的增多,南园的描述会逐渐变得简单,望读者体谅,不懂之处可以留言)。

    四、 正片叠加(Multiply

            public function multiply(topPixel:uint, bottomPixel:uint):uint {

                                  return (bottomPixel * topPixel)/255;

                             }

          下面我们把这个公式稍加变形:topPixel*(bottomPixel/255),就是这么简单!明白了吧,由于bottomPixel永远大于等于0小于等于255,topPixel永远乘以一个0到1之间的数值,始终小于等于原来的值,所以该效果同样是使图像变暗,现在我们再去考虑0和255两个边界值,你会发现我们常说的用纯黑和纯白色去影响图像原来是这么好理解!在使用时好好研究一下这个公式你会有收获的。  

    五、 颜色加深(Color Burn

         该模式南园并未发现信服的算法,在网上找到一个,推导了N久终于发现无法理解。呃(崇拜一下Adobe的开发团队)!限于各种原因,也没有在AS中用代码去试验,如果将来有可能的话会为大家补上来,毕竟现在的目标是集中注意力解决主要问题。该模式同前两种同属一组,效果相似。只是该模式增强了颜色的对比度。只要明确了这一点其它的未必需要掌握。

    六、 线性加深(Liner Burn

          public function multiply(topPixel:uint, bottomPixel:uint):uint {

                                  return  topPixel+bottomPixel-255;

                             }  

         到这里,大家可能已经能看出我的理解方式了。对,公式变形topPixel+(bottomPixel-255),实际上是用topPixel减去一个数值。最后的结果当然是变暗。

          该算法,是从网络上找到,最初形式并不是这样的,为了讲解的统一南园将它做了推导翻译(值得提出的是它提出的算法有很多,表述上更像是数学家程序员的思维方式,很难懂!有兴趣的朋友可以研究一下,其实南园并没有读懂其中的和颜色加深模式(造诣不深需要不断修行!),在理解方式上它的表述让南园很头痛,南园一切的讲解试图以RGB色彩呈现为理论基础。)   

    七、 深色(Darken Color  

         南园属于新用户,不知道Darken Color模式是什么时候加入的,网络上也未找到很好的解释。从英文上我们发现Darken Color 模式比Darken 模式仅仅是多了一个Color,经过试验发现二者效果很类似,只是Darken Color得出的结果比Darken的出的结果某些区域会亮一些(这跟南园翻译理解的英文解释不同,但愿是翻译理解错了,希望有人能解释一下它,南园也会在不断加深理解的基础上修正这一块。)

     ************************分界线********************************* ********如果你善于观察就会发现很多效果正好相反,这在数学公式上表现的就更明显了,但大多数PS用户更注重效果,所以PS将他们放在一块。讲解时南园也将他们放到了一块。****************************

    八、 变亮(lighten

          public function lighten(topPixel:uint, bottomPixel:uint):uint {

                         return Math.max(topPixel, bottomPixel);

                  }

        经过前面的讲述,想必南园不必啰嗦了。同变暗(Darken)正好相反。进行数学比较取较大的值作为计算结果,使得图像变亮。试想一下,你加入一个纯白或纯黑会是怎样?如果是一个灰度图像呢?对于曝光不足的图片你可以做点啥(当然在ps中对于曝光不足它不是很好的选择方案)?哈哈,明白了吧!

    九、 滤色(Screen

           public function screen(topPixel:uint, bottomPixel:uint):uint {

                         return (255 - ((255 - topPixel) * (255 - bottomPixel))/255);

                  }

       复杂吧,分析后就明白了!首先我们需要明白255前去一个值是求通道的“负值”(由于非专业,本人对这个名称的叫法可能很欠妥,但希望读者会意。想想负片效果。)。

       公式可以估算为255-(255-topPixel)*m其中m=(255-bottomPixel)/255<=1.经过观察我们发现255-topPixel是原始像素值的“负值”,乘以一个小于1的数必然变小,再用255减去该数,得到的值显然大于原先的值。

    十、颜色减淡(Color Dodge

        同颜色加深“相似”都动了颜色对比度,只是它的效果是使整个图像变亮。南园的理解就这些,以后尽力会补充。

    十一、 线性减淡(也称“添加” 英文名字Add

       public function add(topPixel:uint, bottomPixel:uint):uint {

                         return Math.min(255, bottomPixel + topPixel);

                  }

          大家知道通道值在0到255之间,其实该模式就是用图像像素值(topPixel)加上下层像素值(bottomPixel),但是这样很容易超过255,那么就出现了公式中的数学比较,当超过时我们取上限值255.

       至于图像会变亮的原因,以及灰度图像的使用就不必再提示了。

    十二、   浅色 lighten Color

       与深色效果相反,同变亮区别很微小。(待完善)

    **************************分界线*************************

      下面让我们进入加强对比度的混合模式组。

    十三、   强光HardLight

                 public function hardlight(topPixel:uint, bottomPixel:uint):uint {

                         var color:uint;

                         if (topPixel > 127.5) {

                                color = screen(bottomPixel, 2 * topPixel - 255);

                         } else {

                                color = multiply(bottomPixel, 2 * topPixel);

                         }

                         return color;

                  }

          非常抱歉这里给了这么多As代码,不过南园会在这里为大家详细讲解。不过相信认识基本英语单词的读者便会很容易猜到它的含义。语句中添加了判断条件。如果图像的像素值大于127.5(应该对这个数值很明感吧:对它就是中灰255/2),那么我们对像素进行滤色操作,或许你会困惑2*topPixel-255代表什么,南园也不明白,就当是大师们的伟大之处吧,不过这并不重要我们只需要把它当做一个整体,就是我们需要操作的两个数据值中的一个。如果图像像素值小于127.5,那么对两个像素值进行正片叠加效果。大家应该没忘,滤色会使像素值变亮,而正片叠加会使图像变暗。这样就可以说强光模式使“图像中亮的地方更亮,暗的地方更暗”,也就增加了图像的对比度。

    十四、   叠加(Overlay

           如果强光模式你能理解,那么叠加模式便能很容易的立理解,还记得我们在强光模式下是用图像像素值与127.5进行比较,现在我们把图像像素值换成下层像素值就行了。

     public function hardlight(topPixel:uint, bottomPixel:uint):uint {

                         var color:uint;

                         if (bottomPixel> 127.5) {

                                color = screen(bottomPixel, 2 * topPixel - 255);

                         } else {

                                color = multiply(bottomPixel, 2 * topPixel);

                         }

                         return color;

                  }

           为了照顾那些Flash 代码书写者在这里有一个小提示:我们可以用更简单的方式实现:

               public function overlay(topPixel:uint, bottomPixel:uint):uint {

                              return hardlight(bottomPixel, topPixel);

                        }

    十五、  柔光(Soft Light

         在网上找到了算法,但是确信给南园一天的时间去推导,也不会有啥突破,数学计算相对复杂。也相信很少用到,如果在以后用到了,南园会补上。对于这个模式大家只需要记住他同样属于增强对比度,只是这种增强非常柔和。很矛盾吧,呵呵,有时候矛盾也是一种美!

    十六、 亮光(Vivid light

         同样是一个难以理解的算法,看了公式我决定放弃对它的讲解,相信一般我们不会用到它。只需要记住它在暗处使用颜色加深(Color Burn),明亮的地方使用颜色颜色减淡(Color Doge)。

    十七、 线性光(Liner Light

          该模式网上淘来的算法,虽然看上去很简单,但是南园觉得她可能不够精确(再次强调南园是初学者,没有太多经验,只是凭感觉做的判断,一家之言,也会在随后完善。)但是在国外一本英文教程上找到了对它的描述,觉得很美,也在向我暗示着ps中混合模式的某种规律(只是感觉,还没来得及找到算法证明,用词语形容就是“组合”“对称”)。翻译如下:线性光模式结合了线性加深和线性减淡以及亮光算法,使暗的地方变暗,又不像线性加深那样暗,明亮的地方变亮,又不像线性减淡那样亮。个人猜测所谓的“又不像”就是因为兼具了线性算法和柔光算法的优点。

    十八、 点光 Pin Light

         

        该模式的解释我一直较喜欢的那本英文教程也使我失望了,通过比较我选择了这样一种解释:“结果就是导致中间调几乎是不变的下层,但是两边是Darken和Lighten模式的组合。”记住改组是增强对比度(暗的更暗明的更明),所以不需要再解释是如何组合的了吧。

           对于该模式,南园也不想把那些自己也懒得研究的数学公式呈现给你,个人认为增强对比这组可以算的上是前面两组的组合提高,很好的理解前面那些基础的模式,就能指导我们的使用。当然有一天你成为了大师,想用像AS那样的程序语言写自己的模式,还是有必要研究的!不过现在我们是入门者。

    十九、  实色混合(Hard Mix

         更喜欢英文对混合模式的命名,能更清楚的表达意思,而且是那种只可意会难以言传的感觉。

    简单的描述就是它通过算法使得图像色彩丢失诸多细节,实现了对比度的增强。作为改组的最后一个南园很想为你揭开她神秘的面纱。

    public function hardMix (topPixel:uint, bottomPixel:uint):uint {

                      var color:uint;

           if(topPixel+bottomPixel<255){

               color=0;

             }else{

                color=255;

             }

                  }

        算法通过将两个像素值进行相加运算,如果小于255那么计算结果就是0,否则计算结果就是255.还记得开始处提到的吗?这些计算都是针对单个通道值进行的。也就是说每个通道只会输出两个值0和255,三个通道的组合你想到了什么?六中颜色?RGB和CMY,以及纯黑纯白?对,在这种模式下你只会得到,黑色白色以及六中基本颜色。是不是很“Hard”,很奇妙!

    **********************分界线*********************************

    下面进入差值模式组,他们的共同点是根据像素的差异进行操作。

    二十、   差值(Difference

           

            该模式很好理解。

            public function difference(topPixel:uint, bottomPixel:uint):uint {

                         return Math.abs(topPixel - bottomPixel);

                  }

           求取差值的绝对值作为计算结果。Math.abs()求取数学绝对值的公式。

    二十一、        排除(Exclusion

           

         曾犹豫是否将它的算法呈现出来,有心的读者可以去推导一下,带入几个特殊的值还是能发现规律的,如果用数学函数绘图将很容易显示其规律,可惜本人数学不好。觉得也没必要,只要记住:白色会使另一个图像呈现负片效果,中灰使得图像变灰在这个过程中图像渐变成灰色,中灰到黑色的过渡使得图像由灰色过渡到原图(不受影响)。

             

              public function exclusion(topPixel:uint, bottomPixel:uint):uint {

                         return  topPixel+bottomPixel-2*topPixel*bottomPixel/255;

                  }

    二十二、 减去(Subtract

        public function subtract(topPixel:uint, bottomPixel:uint):uint {

                         return Math.max(0, bottomPixel - topPixel);

                  }

       与Add模式相反。用下层像素值减去图像像素值,小于0的等于0.

      

    二十三、        划分(Divide

             

        很遗憾该模式没能找到算法,甚至是合适的解说。通过灰度值,南园对其进行了简单的实验,发现当图像像素值为255时,不对下层图像构成影响,当图像像素值为0时,下层图像几乎都变成白色。把灰度图放在下层会发现,当灰度值为0时,整个图像为黑色,当下层灰度值为255时,图像为白色,中灰有补色的感觉。于是大胆猜测:该模式的代码为:

            return Math.max(255-topPixel,bottomPixel)

         南园确信这个公式是不可能完善的,随着理解的深入会努力去完善它。但是还是确信南园在此提供的研究方法是可以参考的。

         *************************分界线***********************

    下面进入颜色模式组

    二十四、 色相(Hue

           

    对于该模式用言语表述同样简洁易懂,也省去了对符号含义的解释。“利用图像的色相,下层像素的饱和度和亮度“。简单吧,效果却很酷,只是简单的摆弄一下便发现,无论是做偏色效果,还是提取黑白照片。南园会在以后的使用中不断总结经验。

    二十五、 饱和度(Saturation

            

    你猜对了,图像饱和度,下层像素的色相和明度。

    二十六、  明度(Luminosity

          同理,图像的明度,下层像素的色相和饱和度。

    二十七、 颜色(Color

         

          该模式使用图像的饱和度和色相,下层像素的明度值生成新的像素值。

  • 相关阅读:
    Unity Shader _Time 的单位
    egg-sequelize 实现 增删改查
    Eggjs 联表查询
    Eggjs 菜单权限管理
    Eggjs 角色管理 -- 对角色树进行 增删改查
    Egg.js 实现一维的对象数组转化为树形数组
    Egg.js 中 Session 的设置和获取
    Egg.js 中 Cookie 的设置和获取
    Egg 安全机制 CSRF 的防范
    Egg middleware 中间件
  • 原文地址:https://www.cnblogs.com/zzugyl/p/2849839.html
Copyright © 2011-2022 走看看