ps的图层混合模式该怎么理解?

发布时间:
2023-08-24 12:34
阅读量:
17

关于图层混合模式方面,我写了一篇文章,希望对你有所帮助

原文地址,大家去那里支持一下,后续更新会在那里

PS图层混合模式超详细解答-图层混合模式的原理 - 王先生的副业的文章 - 知乎 zhuanlan.zhihu.com/p/64

并且,其中的实色混合,我专门写了一个文章,绝对让你意想不到

最多变的混合模式-实色混合HardMix - 王先生的副业的文章 - 知乎 zhuanlan.zhihu.com/p/64

还有其他理论

PS中的阈值调整图层


PS 中的反相调整图层


PS中的色调分离调整图层


通道混合器的基本原理


黑白调整图层背后的原理


PS中可选颜色的数学原理


PS中混合颜色带的原理(RGB空间下)


PS中的柔光模式的来历


最多变的混合模式-实色混合HardMix


PS图层混合模式超详细解答-图层混合模式的原理

前言

本教程非常详细,请用心看完

本教程如果有如何问题,欢迎评论区留言讨论

本教程为了避免冗余,一些不必要的截图就省略了

本教程只讨论8bit的情形下的混合

未经许可,不可转载

饮茶

在一切开始之前,我们先泡一杯茶 泡一杯茶需要一杯开水,一袋茶叶,如果太苦我们还需要一些水来兑一下






好的我们来温习一下泡茶的过程

1:我们准备一壶开水 2:我们准备一包茶叶,放多少取决于个人口味 3:我们把茶叶放到开水杯子中,在这个过程中可以静置或者搅拌也可以煮一下,等待茶叶和热水充分融合 4:我们想喝茶就把茶从茶壶中倒到一个杯子中,如果感觉苦了就加一点开水 5:最后我们会得到一杯符合我们口味的茶

一般我们泡茶就是这几个步骤,你会泡茶吗,如果你会,那么恭喜你,你已经掌握了图层混合模式。

一壶开水相当于基础图层 一包茶叶相当于混合图层,它将和一壶开水组成一个新的饮品-茶 茶叶放了多少就是填充,可以是一包,半包,也可以不放,放的越多,得到的那壶茶就越浓郁 静置或者搅拌也可以煮一下就是混合模式,这里的方式多种多样 喝茶的时候倒到杯子里面,茶水会和开水混合,茶水占据的比例就是不透明度 一杯符合我们口味的茶就是结果图层

图层混合模式在PS中一共有种,对分组来说还有一种叫做穿透,另外在其他一些菜单中还有一些不常见的,比如笔刷菜单中的背后和清除,以及计算工具中的相加和相减。 由此,我们便可以得出,PS中一共有种图层混合模式。







接下来,我们将会对每一种模式进行详细解读。

什么是图层混合模式

图层混合模式究竟是什么,他的本质代表什么?

图层混合模式的本质就是对像素的运算,就像是泡茶的过程中的搅拌

比如

一种图层混合模式,就代表一种运算方式,这种运算方式会把像素点和像素点融合成为像素点







在本教程中,对公式本身进行讨论,一些所谓的衍生概念我们尽量不提,因为会造成冗余,比如增色减色等衍生概念,我们只对本质问题讨论。如果某些过程在公式当中已经包含了,我们就不再截图了,因为不想冗余,比如图层混合模式之间的相互转换。

前置概念

像素点

像素点事PS可以处理的最小单元,为了方便我们使用或者来表示

图层

像素点可以组合形成图层也就是由点到面,图层我们使用来表示 那么一个的图层和像素的关系可以表示为

Layer=\left\{ \begin{aligned}&Pix_{(1,1)} &&\cdots&&Pix_{(1,n)}\\&\vdots &&&&\vdots\\  &Pix_{(i,1)} &&\cdots&&Pix_{(i,n)}\\&\vdots && &&\vdots\\  &Pix_{(m,1)} &&\cdots&&Pix_{(m,n)}\\\end{aligned}\right\}

图层混合模式 一共涉及三个图层分别是 1、基础图层或者叫做底图就是下方的图层 我们使用英文单词below的开头字母B来表示,符号是 2、混合图层或者叫做调整图层绘画图层混合图层或者叫绘画图层,就是上方的图层 我们使用英文单词above的开头字母A来表示,符号是 3、结果图层就是以何种方式处理之后的结果,他是通过的结合来表示。

Image


图层大小

PS新建的过程中,我们可以看到一些图片属性,其中就有图片大小 这里我们讨论的图层大小都默认是,也就是高度是宽度是的图层大小

色彩空间

在图层混合模式中,涉及到的色彩空间一共有两种 ,第一是RGB,也就是红绿蓝三通道,第二是HSY,也就是色相,饱和度,明度。 如果是RGB空间则使用来表示像素点,如果是HSY空间则使用来表示像素点。

RGB

如果使用RGB来表示一个像素点那么像素点可以表示为

为了便于和后面的简称区分开,我们使用颜色Red、Green、Blue和通道的英文字母channel的开头字母来表示各个通道。于是上面的公式也可以表示为

在8bit的图像中,使用8个字节来表示一个像素,于是可以表示个数字,也就是这个区间内的数字。如果数字越大那么这个通道就越亮。

几个典型的颜色

红色,黑色,白色,中性灰色。 如果我们对每个通道都用归一化操作,

那我们可以得到

那么以上的四种颜色就可以表示为 红色,黑色,白色,中性灰色

一些运算规则

如果一个像素需要扩大或者缩小

通道级别

通道数值乘以

像素级别

如果一个像素点则表示其中所有通道数值都乘 也就是说

图层级别

如果是图层则表示所有像素点都乘 也就是说

\begin{aligned}   Layer\times x&=\left\{ \begin{aligned}     &Pix_{(1,1)}\times x&&\cdots&&Pix_{(1,n)}\times x\\&\vdots && &&\vdots\\  &Pix_{(1,n)}\times x &&\cdots&&Pix_{(i,n)}\times x\\&\vdots && &&\vdots\\  &Pix_{(m,1)}\times x &&\cdots&&Pix_{(m,n)}\times x\\  \end{aligned}\right\}\\\\&=\left\{ \begin{aligned}     &(RC_{(1,1)}\times x,GC_{(1,1)}\times x,BC_{(1,1)}\times x)&&\cdots&&(RC_{(1,n)}\times x,GC_{(1,n)}\times x,BC_{(1,n)}\times x)\\&\vdots && &&\vdots\\  &(RC_{(1,n)}\times x,GC_{(1,n)}\times x,BC_{(1,n)}\times x) &&\cdots&&(RC_{(i,n)}\times x,GC_{(i,n)}\times x,BC_{(i,n)}\times x)\\&\vdots && &&\vdots\\  &(RC_{(m,1)}\times x,GC_{(m,1)}\times x,BC_{(m,1)}\times x) &&\cdots&&(RC_{(m,n)}\times x,GC_{(m,n)}\times x,BC_{(m,n)}\times x)\\  \end{aligned}\right\}\end{aligned}

辅助计算程序

为了辅助我们计算并且验证这些理论公式和PS中实际运行的结果是否一致,我们借助java代码来实现具体的计算过程,手动计算可以,但是浪费时间,我们有更简单的方式。 我们定义一个java类BlendColor,这个类用RGB作为基础,每次计算都以RGB存储,如果需要其他表达式,则我们通过RGB转换。

public class BlendColor { public ColorItem red; public ColorItem green; public ColorItem blue; public List<ColorItem> orderColorList; public BlendColor(double redv, double greenv, double bluev) { ColorItem red = new ColorItem("red", redv); ColorItem green = new ColorItem("green", greenv); ColorItem blue = new ColorItem("blue", bluev); this.orderColorList = new ArrayList<ColorItem>(); this.red = red; this.green = green; this.blue = blue; this.orderColorList.add(red); this.orderColorList.add(green); this.orderColorList.add(blue); // 排序 Collections.sort(this.orderColorList); } ... }

HSY

如果使用HSY来表示一个像素点

为了方便统一表述,在涉及到HSY时,如果我们需要表达RGB数值,我们使用$$$$ Hue也就是色相,取值范围是,决定是什么颜色

Stratuation饱和度,取值范围是,决定这种颜色鲜艳程度或者换一种说法-颜色有多少

Luminosity明度,取值范围是,决定这种颜色有多亮

上述两种色彩空间的转换关系如下:

Hue = \left\{ \begin{aligned}&0& 若\space  max = min \\&60^{\circ}\times \dfrac{gc-bc}{max-min} & 若\space rc=max\space且\space gc \geq bc\\&60^{\circ}\times \dfrac{gc-bc}{max-min} +360^{\circ}& 若\space rc=max\space且\space gc<bc\\&60^{\circ}\times \dfrac{bc-rc}{max-min} +120^{\circ}& 若 \space gc=max\\&60^{\circ}\times \dfrac{rc-gc}{max-min} +240^{\circ}& 若 \space bc=max\\\end{aligned}\right.

代码实现如下

public double getHue() { ColorItem max = this.getMax(); ColorItem mid = this.getMid(); ColorItem min = this.getMin(); if (Double.doubleToLongBits(max.value) == Double.doubleToLongBits(min.value)) { return 0; } double hueAbs = (mid.value - min.value) / (max.value - min.value); if (max.name == "red") { if (this.green.value > this.blue.value) { return 60 *hueAbs; } else { return -60* hueAbs + 360; } } if (max.name == "green") { return 60 *hueAbs + 120; } if (max.name == "blue") { return 60* hueAbs + 240; } return 0; } public double getLum() { double lum = 0.3 * this.red.value + 0.59 * this.green.value + 0.11 * this.blue.value; return lum; } public double getSat() { double max = this.getMax().value; double min = this.getMin().value; return max - min; }

不透明度和填充

不透明度的英文单词是,填充的英文单词是 两者在图层混合模式中有时相同有时不同。具体我们会在后面说明。 简单描述二者的区别,就是,不透明度就是将基础图层B和基础图层A,使用Opacity比例进行混合,公式如下:

其中代表不透明度

代码实现

public static BlendColor Opacity(BlendColor colorBase, BlendColor colorResult, double opacity) { double redOpacity = colorResult.red.value *opacity + colorBase.red.value* (1 - opacity); double greenOpacity = colorResult.green.value *opacity + colorBase.green.value* (1 - opacity); double blueOpacity = colorResult.blue.value *opacity + colorBase.blue.value* (1 - opacity); return new BlendColor(redOpacity, greenOpacity, blueOpacity); }

如果是

这只是一个原则公式,具体情况要视具体模式确定,每一种计算方式都有细微区别。我们在此处不给出具体的公式和代码,但是我们在每一种中,我们会具体实现。 填充的计算方式有八个和其他的不同,并且此时和不透明度的计算方法不一样。除了这八个,不透明度和填充变化的结果是相同的。 他们分别是

  • 线性加深
  • 颜色加深
  • 线性减淡
  • 颜色减淡
  • 线性光(线性减淡+线性加深)
  • 亮光(颜色减淡+颜色加深)
  • 实色混合(线性减淡+线性加深 或者 颜色减淡+颜色加深)
  • 差值

并且,填充的优先级高于不透明度,如果让两者一起产生效果则公式为:

如果使用一句话概括这二者的区别就是:

填充会让当前混合模式的效果弱化,弱化的程度取决于的大小。不透明度决定了当前混合模式结果图层和基础图层混合的比例,opacity越大,结果图层占比越大。结合前面的例子,填充越大放的茶叶就越多,不透明度越大,最后添加的水就越少

混合模式的组合

一般来说,混合模式的组合会以基础图层B或者混合图层A的中性灰分割线为界,组合两种不同的混合模式。

例如,强光模式,它是由正片叠底和滤色两种模式以混合图层的中性灰分割线为界完成组合 正片叠底

滤色

强光

则是二者的结合

映射面

对于任意的一个混合模式,如果我们将它产生的所有基础图层和混合图层的结果,都在一个三维坐标中标记出来,则我们就会得到一个由个点组成的平面,换句话说,不管什么混合模式,基础图层和混合图层是什么值,在8bit的模式下,都只有种可能结果。

这个面就是映射面。 下图是我们将每一种图层混合模式表达式输入之后为我们呈现的结果,轴为基础图层,轴为混合图层,轴为结果图层,我们可以看到越大的带你则越白,最白,越小的点越黑, 最黑。于是我们就可以通过黑白程度来判断结果大小。

映射面示例


Image

映射面和原图面的对比

Image

使用混合模式后的映射面和原图映射面的对比

由上图可以得知,这是一种变暗模式并且在混合图层和基础图层中选择了比较小的作为结果,因为可以明显看到一部分平面在原平面(图中的蓝色平面)的下方

同图平面

如果我们把基础图层和混合图层取值相同的点都标记出来,我们会得到一个对角平面,这个平面就是我们所说的同图平面

同图平面以及其和映射面相交的图像

Image

图中绿色的平面就是同图平面,他和映射面的交线就是我们可以使用曲线工具模拟的曲线。

同图混合曲线

此时相当于带入到某个图层混合模式的表达式中, 我们此处以线性加深为例 线性加深原本的表达式是

则表达式可以写成

\begin{aligned}  r&=(b,b)\\&=b-(1-b)\\&=b+b-1\\&=2b-1\end{aligned}


Image

此时,在坐标系中画出该图像就如同上图所示。

这时候我们只要打开曲线工具,然后拉一条曲线,和上图相同,就可以得到和这种混合模式在基础图层和混合图层相同的情况下的到结果图层相同的效果。

Image

同图平面和映射面的交线就是可以使用曲线工具模拟这种混合模式时画出的曲线。 同图平面有时候也可以作为分割平面,比如在实色混合模式的时候。

中性灰平面

如果我们把基础图层或者绘画图层中128中性灰的点都标记出来,我们会得到一个中性灰平面 这个平面一般作为结合两种混合模式的分割面

基础图层的中性灰平面

如果两种混合模式是以基础图层的取值作为分界依据的时候,使用此平面作为分割和结合依据。

Image


混合图层的中性灰平面

如果两种混合模式是以混合图层的取值作为分界依据的时候,使用此平面作为分割和结合依据。 同图平面,中性灰平面(基础中性灰平面,混图层中性灰平面)都是结合两种混合模式的依据。

Image


关系总揽

为了方便大家理解,我们在此给出27中图层混合模式的总览

Image


  • 可转换:代表两种混合模式可以在一定条件下等效另外一种
  • 可交换:底图和绘画图层交换,两种混合模式产生的结果相同,也就是互逆
  • 组成:一种混合模式可以由另外一种组成

特殊关系

从总览那幅图我们可以得出一些有趣的结论

就是有的混合模式在结合一些操作之后,结果等价于另外一种

有的图层混合模式和另外一种是互逆的关系

有些可以组合,有些对黑色无效,有些对白色无效,有些对中性灰无效

总之,他们的一切都蕴含在了公式中,如果你想搞清楚,就仔细研究一下。

可转换

可转换可能有些在实际操作中有偏差,因为在计算过程中可能出现大于1或者小于0的情况,导致被取舍。以下都是理论存在的情况。

  • 变亮变暗(三次负片)
  • 滤色正片叠底(三次负片)
  • 线性减淡线性加深(三次负片)
  • 颜色减淡颜色加深(三次负片)
  • 浅色深色(三次负片)
  • 线性加深减去(一次负片)
  • 颜色减淡划分(一次负片)
  • 颜色加深划分(两次负片)

互逆(可交换)

  • 叠加强光
  • 颜色明度
  • 实色混合线性光(当实色混合填充设置为0.5也就是50%)

组成

  • 叠加 正片叠底滤色
  • 强光 正片叠底滤色
  • 线性光 线性加深线性减淡
  • 实色混合 线性加深线性减淡
  • 亮光 颜色加深颜色减淡
  • 点光 变亮变暗
  • 柔光系数2的伽马矫正 系数为0.5的伽马矫正

另外五种

  • 穿透
  • 背后
  • 擦除
  • 相加
  • 相减

图层混合模式的种类

色彩空间分类

分类方法有很多,如果按照色彩空间,可以分成两类,RGB和HSY

RGB

  • 除颜色组

HSY

  • 颜色组

是否产生新的数值

如果根据运算方式,可以分成两类,一类是替换式,一类是融合式

替换式

包括:

  • 正常组(正常,溶解)
  • 变暗组(变暗,深色)
  • 变亮组(变亮,浅色)
  • 颜色组(色相,饱和度,颜色,明度) 这种式的特点是,不会产生新的东西,只会复用之前的东西







比如正常组,正常就是直接使用混合图层作为结果 变暗组的变暗是使用基础图层和混合图层中通道较小的值组成新的像素,深色则是比较基础图层和混合图层通道值的和取小的作为结果 颜色组,则是根据HSY色彩空间,直接替换 HSY的数值,并且再转换为RGB,本质也是没有新的东西产生。

融合式

包括:

  • 变暗组(正片叠底,颜色加深,线性加深)
  • 变亮组(滤色,颜色减淡,线性减淡)
  • 对比度组(叠加,柔光,强光,亮光,线性光,点光,实色混合)
  • 差值组(差值,排除,减去,划分)

虽然点光是变暗和变亮的混合,但是混合过程中做了处理,所以此处我们也按照融合式对待 此类的特点是,会产生新的数值。

融合式就是产生了新的数值,比如正片叠底,结果图层的数值由基础图层和混合图层的乘积得到,他是不同于基础图层和混合图层的值。

是否顺序相关

如果根据是否受到图层顺序影响 如果$$BlendMode(b,a)=BlendMode(a,b)$$ 则说明结果不受图层顺序影响,前提是不调节

顺序无关

  • 变暗组 (变暗,线性加深,正片叠底,深色)
  • 变亮组 (变亮,线性减淡,滤色,浅色)
  • 对比度组 (实色混合)
  • 差值组(差值,排除)

顺序相关

  • 正常组 (正常,溶解)
  • 变暗组(颜色加深)
  • 变亮组(颜色减淡)
  • 对比度组(叠加,柔光,强光,亮光,线性光,点光)
  • 差值组(减去,划分)
  • 颜色组(色相,饱和度,颜色,明度)

是否fill和Opacity不同

也就是说,调节填充的百分比,和不透明度的百分比,即使数值相同,结果也有可能不同。

fill和Opacity产生不同影响

  • 变暗组(线性加深,颜色加深)
  • 变亮组(线性减淡,颜色减淡)
  • 对比度组(亮光,线性光,实色混合)
  • 差值组(差值)

fill和Opacity产生相同影响

  • 正常组 (正常,溶解)
  • 变暗组(变暗,正片叠底,深色)
  • 变亮组(变亮,滤色,浅色)
  • 对比度组(叠加,柔光,强光,点光)
  • 差值组(排除,减去,划分)
  • 颜色组(色相,饱和度,颜色,明度)

混合模式相关符号

图层混合模式我们使用来表示,这里是一个泛指,如果涉及到具体的混合模式,有专门的表示符号,比如正常模式使用 使用矩阵我们有:

LayerA=\left\{ \begin{aligned}     &PixA_{(1,1)}&&\cdots&&PixA_{(1,n)}\\&\vdots && &&\vdots\\  &PixA_{(i,1)} &&\cdots&&PixA_{(i,n)}\\&\vdots && &&\vdots\\  &PixA_{(m,1)} &&\cdots&&PixA_{(m,n)}\\  \end{aligned}\right\}

LayerB=\left\{ \begin{aligned}     &PixB_{(1,1)}&&\cdots&&PixB_{(1,n)}\\&\vdots && &&\vdots\\  &PixB_{(i,1)} &&\cdots&&PixB_{(i,n)}\\&\vdots && &&\vdots\\  &PixB_{(m,1)} &&\cdots&&PixB_{(m,n)}\\ \end{aligned}\right\}

LayerR=\left\{ \begin{aligned}     &PixR_{(1,1)}&&\cdots&&PixR_{(1,n)}\\&\vdots && &&\vdots\\  &PixR_{(i,1)} &&\cdots&&PixR_{(i,n)}\\&\vdots && &&\vdots\\  &PixR_{(m,1)} &&\cdots&&PixR_{(m,n)}\\ \end{aligned}\right\}

再结合上面的三者关系公式$$LayerR=BlendMode(LayerB,LayerA)$$ 我们得到

LayerR=\left\{ \begin{aligned}   &BlendMode(PixB_{(1,1)},PixA_{(1,1)})&&\cdots&&BlendMode(PixB_{(1,n)},PixA_{(1,n)})\\&\vdots && &&\vdots\\&BlendMode(PixB_{(i,1)},PixA_{(i,1)})&&\cdots&&BlendMode(PixB_{(i,n)},PixA_{(i,n)})\\&\vdots && &&\vdots\\&BlendMode(PixB_{(m,1)},PixA_{(m,1)})&&\cdots&&BlendMode(PixB_{(m,n)},PixA_{(m,n)})\\\end{aligned}\right\}

对于其中任意项

如果这种混合模式基于RGB色彩空间则 上述表达式可以写为

或者未归一化形式

如果这种混合模式基于HSY色彩空间

在下面的所有组中,如果不特别说明基于RGB色彩空间的混合模式都是使用归一化后的数值进行计算。

并且,为了方便大家验证计算的正确性,这里提供一个java程序的链接给各位,GitHub的地址如下,输入你要混合的像素的数值,就可以得到对应混合模式混合的结果数值。

普通组

正常Normal

正常模式是一切的基础,也是我们理解和掌握混合模式的基础, 正常模式可以看作是基于RGB颜色空间,也可以看作是基于HSY色彩空间

公式(泡茶的方式,比如搅拌、静置)

对于像素维度公式

正常模式通道维度初始公式

融合填充(放多少茶叶)

融合不透明度(太苦了,最后加点水)

对于整个像素

后面的混合模式我们不再讨论整个像素的公式,我们只讨论某个通道的结果。

整个像素融合填充

这里不同的混合模式公式不一定相同。

\begin{aligned}(r_{rc},r_{gc},r_{bc})&=Fill((b_{rc},b_{gc},b_{bc}),(a_{rc},a_{gc},a_{bc}))\\&=\left((fill\times a_{rc} + (1-fill)\times b_{rc}),(fill\times a_{gc} + (1-fill)\times b_{gc}),(fill\times a_{bc} + (1-fill)\times b_{bc})\right)\end{aligned}

整个像素融合不透明度

\begin{aligned}(r_{rc},r_{gc},r_{bc})&= Opacity((b_{rc},b_{gc},b_{bc}),(a_{rc},a_{gc},a_{bc}))\\&=\left((op\times Fill(a_{rc},b_{rc}) + (1-fill)\times b_{rc}),(op\times Fill(a_{gc},b_{gc} + (1-op)\times b_{gc}),(op\times Fill(a_{bc},b_{bc} + (1-op)\times b_{bc})\right)\end{aligned}

映射面和相关拓展


Image


程序模拟该模式计算结果

// 正常模式 public static BlendColor Normal(BlendColor colorBase, BlendColor colorBlend, double fill, double opacity) { double red = colorBlend.red.get01Value() *fill + colorBase.red.get01Value()* (1 - fill); double green = colorBlend.green.get01Value() *fill + colorBase.green.get01Value()* (1 - fill); double blue = colorBlend.blue.get01Value() *fill + colorBase.blue.get01Value()* (1 - fill); return ColorUtils.Opacity(colorBase, new BlendColor(red *255, green* 255, blue * 255), opacity); }

借助正常模式 我们可以看到不透明度和填充的关系 后面的模式讨论我们都不再说明像素级别的公式,因为没有必要,我们只讨论通道级别的公式。 我们设定

基础图层 RGB[111.00, 80.00, 60.00]~ HSY[23.53, 51.00, 87.10 ]~ HSB[ 23.53, 45.95, 43.53] 混合图层 RGB[ 80.00, 70.00, 156.00]~ HSY[246.98, 86.00, 82.46]~ HSB[246.98, 55.13, 61.18] ========================正常组=================================== 正 常(Normal) RGB[103.56, 77.60, 83.04]~ HSY[347.43, 25.96, 85.99]~ HSB[347.43, 25.07, 40.61]

我们在PS中使用这两种颜色进行验证,发现符合我们的算法。

Image


用途示例

该模式是默认模式,在不调节填充和不透明度的情况下,就是上方像素点覆盖下方的像素点。 结合不透明度或者填充,可以实现和下方图层的简单混色。

溶解Dissolve

溶解模式初始公式

如果融合了填充

不透明度对溶解模式是无效的。 的值越大,则下层像素暴露的可能性越小

程序模拟该模式计算结果

// 溶解模式 public static BlendColor Dissovle(BlendColor colorBase, BlendColor colorBlend, double fill, double opacity) { double rand = Math.random(); // 产生随机数 if (rand < fill) { return colorBlend; } else { return colorBase; } } 溶 解(Dissolve) RGB[111.00, 80.00, 60.00]~ HSY[23.53, 51.00, 87.10 ]~ HSB[ 23.53, 45.95, 43.53]

验证

溶解模式是根据概率来实现决定显示下方像素还是上方像素

于是取样点不同,则结果可以是上方的像素也可以是下方的像素

Image


用途示例

可以通过该模式实现一下粒子效果

变暗组

这一组是基于RGB色彩空间,RGB三个通道的数值取值范围是,归一化之后取值范围是。这一组就是利用一系列运算让基础图层的三个通道的数值或者他们的和小于等于原值。这也是变暗组的本质。 和下面的变亮组一样,变暗组有两种方式将通道值或者通道值的和变小,那就是替换运算,替换包括变暗和深色,运算包括其他三种。

变暗模式

如果将基础图层每个像素每个通道的数值都变小,最简单的方式就是选择原图图层像素通道值和混合图层像素通道值中比较小的那个作为结果图层像素通道值,这样的图层中每个像素点的通道值都小于等于原值,图像自然就会变暗。

公式

融合填充

融合不透明度

映射面和同图等效曲线


Image


同图曲线表达式

这里我们简单认为fill和opacity都是100,因为我们日常使用中几乎用不到改变这两个值并且需要模拟同图曲线的情况,使用这里只讨论最简单的类型。但是其他类型可以通过我们提供的公式自行推导,但是这里没有必要写出来。下同。

程序模拟该模式计算结果

// 变暗 public static BlendColor Darken(BlendColor colorBase, BlendColor colorBlend, double fill, double opacity) { double red = DarkenChannel(colorBase.red.get01Value(), colorBlend.red.get01Value(), fill); double green = DarkenChannel(colorBase.green.get01Value(), colorBlend.green.get01Value(), fill); double blue = DarkenChannel(colorBase.blue.get01Value(), colorBlend.blue.get01Value(), fill); return ColorUtils.Opacity(colorBase, new BlendColor(red *255, green* 255, blue * 255), opacity); } private static double DarkenChannel(double base, double blend, double fill) { return Math.min(base, blend) * fill + (1 - fill) * base; } 变 暗(Darken) RGB[103.56, 77.60, 60.00]~ HSY[24.24, 43.56, 83.45 ]~ HSB[ 24.24, 42.06, 40.61]

验证


Image


用途示例

1:组合成为对比度组的点光Pinlight模式 2:此处是深色模式的简化版本,但是我们还是可以通过它来实现一些溶图操作

正片叠底Multiply

如果将混合图层像素的通道数值和原图像素通道数值相乘,则因为归一化之后的数值都是小于等于1的所以,原值乘一个小于1的数值一定小于等于原来的值。所以图像会变暗。

公式

融合填充

融合不透明度

映射面和同图等效曲线

正片叠底的映射面,同图面,同图曲线和中性灰平面

Image


同图曲线表达式

程序模拟该模式计算结果

// 正片叠底 public static BlendColor Mulitply(BlendColor colorBase, BlendColor colorBlend, double fill, double opacity) { double red = MulitplyChannel(colorBase.red.get01Value(), colorBlend.red.get01Value(), fill); double green = MulitplyChannel(colorBase.green.get01Value(), colorBlend.green.get01Value(), fill); double blue = MulitplyChannel(colorBase.blue.get01Value(), colorBlend.blue.get01Value(), fill); return ColorUtils.Opacity(colorBase, new BlendColor(red * 255, green * 255, blue * 255), opacity); } private static double MulitplyChannel(double base, double blend, double fill) { return ColorUtils.round((base * blend) * fill + (1 - fill) * (base), 1, 0); } 正片叠底(Mulitply) RGB[ 92.72, 66.07, 54.41]~ HSY[18.26, 38.31, 72.78 ]~ HSB[ 18.26, 41.32, 36.36]

验证


Image


用途示例

1:和滤色模式组合成强光和叠加模式 2:给比较亮的图片添加纹理 3:扣除白色背景

线性加深LinearBurn

此模式本质是减法,就是使用混合图层像素通道数值的补也就是附片和原图相减,如果大于1则取1小于0则取0,并且此模式需要对填充特殊处理。线性加深可以通过划分和颜色加深转化。

公式

融合填充

融合不透明度

映射面和同图等效曲线

线性加深的映射面,同图面,同图曲线和中性灰平面

Image


同图曲线表达式

程序模拟该模式计算结果

// 线性加深 public static BlendColor LinearBurn(BlendColor colorBase, BlendColor colorBlend, double fill, double opacity) { double red = LinearBurnChannel(colorBase.red.get01Value(), colorBlend.red.get01Value(), fill); double green = LinearBurnChannel(colorBase.green.get01Value(), colorBlend.green.get01Value(), fill); double blue = LinearBurnChannel(colorBase.blue.get01Value(), colorBlend.blue.get01Value(), fill); return ColorUtils.Opacity(colorBase, new BlendColor(red *255, green* 255, blue * 255), opacity); } private static double LinearBurnChannel(double base, double blend, double fill) { return ColorUtils.round(base - (1 - blend) * fill, 1, 0); } 线性加深(LinearBurn) RGB[ 69.00, 35.60, 36.24]~ HSY[358.85, 33.40, 45.69]~ HSB[358.85, 48.41, 27.06]

验证


Image


用途示例

1:组成线性光 2:添加光效可做滤镜

颜色加深ColorBurn

此模式的本质是线性加深和混合图层相除,由此可以得知他可以和线性加深通过正片叠底转化。

公式

\begin{aligned}&r=ColorBurn(b,a)\\&=1-\dfrac{1-b}{1-(1-a)}\end{aligned}

这里之所以这么写,是因为后面要加入fill,也就是填充。







推导一下

\begin{aligned}&r=ColorBurn(b,a)\\&=1-\dfrac{1-b}{1-(1-a)}=\dfrac{1-(1-a)-(1-b)}{1-(1-a)}\\&\\&=\dfrac{b-(1-a)}{1-(1-a)}\\&\\&=\dfrac{LinearBurn(b,a)}{1-(1-a)}=\dfrac{LinearBurn(b,a)}{a}\end{aligned}

从这里可以看出,线性加深可以和颜色加深相互转换,通过划分和正片叠底。但是这里涉及到其他的混合模式,而非单纯负片,所以不把他们放到可以互相转化的分类中







融合填充

融合不透明度

映射面和同图等效曲线

颜色加深的映射面,同图面,同图曲线和中性灰平面

Image


同图曲线表达式

两次负片转划分

\begin{aligned}&r=1-ColorBurn(1-b,a)\\&=1-(1-\dfrac{1-(1-b)}{a})\\&=\dfrac{b}{a}\end{aligned}

程序模拟该模式计算结果

// 颜色加深 public static BlendColor ColorBurn(BlendColor colorBase, BlendColor colorBlend, double fill, double opacity) { double red = ColorBurnChannel(colorBase.red.get01Value(), colorBlend.red.get01Value(), fill); double green = ColorBurnChannel(colorBase.green.get01Value(), colorBlend.green.get01Value(), fill); double blue = ColorBurnChannel(colorBase.blue.get01Value(), colorBlend.blue.get01Value(), fill); return ColorUtils.Opacity(colorBase, new BlendColor(red * 255, green * 255, blue * 255), opacity); } private static double ColorBurnChannel(double base, double blend, double fill) { return ColorUtils.round(1 - Math.min(1, (1 - base) / ((1 - (1 - blend) * fill))), 1, 0); } 颜色加深(ColorBurn) RGB[ 78.31, 37.07, 38.49]~ HSY[357.94, 41.24, 49.60]~ HSB[357.94, 52.66, 30.71]

验证


Image


用途示例

1:组合成为亮光模式 2:完成特殊光影效果,例如给太阳添加一些颜色或光晕,并且保留亮部细节,该模式的特点也是相对线性加深,可以保留底图的亮部细节。

深色Darker

深色模式可以理解为变暗模式的加强变暗模式,或者是粗略的变暗模式,因为其不产生新的像素,就像溶解模式一样。 计算细节简单来说就是求和,比较大小,小的留下了,若求和的结果一样,就计算明度,明度小的留下了。

公式

\begin{aligned}Pix_r &=Darker(Pix_b,Pix_a)\\&=\left\{\begin{aligned}&Pix_a && Sum(Pix_a)<Sum(Pix_b)\\&Pix_b&&  Sum(Pix_a)>Sum(Pix_b)\\&Pix_b&&  Sum(Pix_a)=Sum(Pix_b)且Lum(Pix_b)<Lum(Pix_a)\\&Pix_a&&  Sum(Pix_a)=Sum(Pix_b)且Lum(Pix_b)>Lum(Pix_a)\end{aligned}\right.\end{aligned}

融合填充

融合不透明度

映射面和同图等效曲线

程序模拟该模式计算结果

// 深色 public static BlendColor Darker(BlendColor colorBase, BlendColor colorBlend, double fill, double opacity) { double sumBase = colorBase.red.value + colorBase.green.value + colorBase.blue.value; double sumBlend = (colorBlend.red.value + colorBlend.green.value + colorBlend.blue.value) * fill; if (sumBase == sumBlend) { if (colorBase.getLum() < colorBlend.getLum()) { double red = colorBase.red.get01Value(); double green = colorBase.green.get01Value(); double blue = colorBase.blue.get01Value(); return ColorUtils.Opacity(colorBase, new BlendColor(red * 255, green * 255, blue * 255), opacity); } else { double red = colorBase.red.get01Value() * (1 - fill) + colorBlend.red.get01Value() * fill; double green = colorBase.green.get01Value() * (1 - fill) + colorBlend.green.get01Value() * fill; double blue = colorBase.blue.get01Value() * (1 - fill) + colorBlend.blue.get01Value() * fill; return ColorUtils.Opacity(colorBase, new BlendColor(red * 255, green * 255, blue * 255), opacity); } } if (sumBase < sumBlend) { double red = colorBase.red.get01Value(); double green = colorBase.green.get01Value(); double blue = colorBase.blue.get01Value(); return ColorUtils.Opacity(colorBase, new BlendColor(red * 255, green * 255, blue * 255), opacity); } double red = colorBase.red.get01Value() * (1 - fill) + colorBlend.red.get01Value() * fill; double green = colorBase.green.get01Value() * (1 - fill) + colorBlend.green.get01Value() * fill; double blue = colorBase.blue.get01Value() * (1 - fill) + colorBlend.blue.get01Value() * fill; return ColorUtils.Opacity(colorBase, new BlendColor(red * 255, green * 255, blue * 255), opacity); } 深 色(Darker) RGB[103.56, 77.60, 83.04]~ HSY[347.43, 25.96, 85.99]~ HSB[347.43, 25.07, 40.61]

验证


Image


用途示例

用于替换图中某些像素点,一般用于两张十分相似的图片的融合,比如连拍,延时摄影的一组照片融合成一张图。

变亮组

变亮组是变暗组的相反模式,并且都可以通过负片操作来实现相互转换 变亮组的本质就是以混合图层的像素为参数,对原图层像素的数值进行增大,数值增大了,图片就变亮了。如果混合图层中像素点的通道值时0,则此时该通道的计算结果和原图一致。

变亮Lighten

变亮模式和变暗模式相反,变暗时取最小值,变亮就是取最大值,具体做法就是取原图层和混合图层像素点中三个通道各自的最大值,保留最大值组成的像素作为结果像素。

公式

融合填充

融合不透明度

可以写作

三次负片操作相互转换

\begin{aligned} r&=Lighten(b,a)\\&=1-Min(1-b,1-a)\\&= 1-Darken(1-b,1-a)\end{aligned}

也就是说,三次负片操作可以实现变暗模式和变亮模式的相互转换

映射面和同图等效曲线


Image


程序模拟该模式计算结果

// 变亮模式 public static BlendColor Lighten(BlendColor colorBase, BlendColor colorBlend, double fill, double opacity) { double red = LightenChannel(colorBase.red.get01Value(), colorBlend.red.get01Value(), fill); double green = LightenChannel(colorBase.green.get01Value(), colorBlend.green.get01Value(), fill); double blue = LightenChannel(colorBase.blue.get01Value(), colorBlend.blue.get01Value(), fill); return ColorUtils.Opacity(colorBase, new BlendColor(red * 255, green * 255, blue * 255), opacity); } private static double LightenChannel(double base, double blend, double fill) { return Math.max(base, blend * fill) * fill + (1 - fill) * base; } 变 亮(Lighten) RGB[111.00, 80.00, 83.04]~ HSY[354.12, 31.00, 89.63]~ HSB[354.12, 27.93, 43.53

验证


Image


用途示例

1:组成叠加和强光 2:保留通道中较大的值,并且组成新的像素,可用于将背景较暗或相似但是部分不相同的图片融合。相当于做了一个复杂的通道蒙版,并且这个蒙版非常精确,精确到通道。

滤色Screen

滤色时正片叠底的一种负片组合,和变暗变亮一样可以通过三次负片操作相互转换。

公式

融合填充

融合不透明度

三次负片操作相互转换

\begin{aligned} r&=Screen(b,a)\\&=1-(1-b)(1-a)\\&= 1- Multipy(1-b,1-a)\end{aligned}

映射面和同图等效曲线


Image


程序模拟该模

END