对比度组
叠加Overlay
此模式是正片叠底和滤色的组合,组合依据是底图的中性灰平面,如果在 [ 0 , 128 ] [0,128] [0,128]则使用正片叠底,若是在 ( 128 , 255 ] (128,255] (128,255]之间,则是实用滤色。
公式
r = O v e r L a y ( b , a ) = { M u l t i p l y ( 2 b , a ) 当 0 ≤ b ≤ 0.5 S c r e e n ( 2 ( b − 0.5 ) , a ) 当 0.5 < b ≤ 1 = { 2 b a 当 0 ≤ b ≤ 0.5 1 − 2 ( 1 − b ) ( 1 − a ) 当 0.5 < b ≤ 1 \begin{aligned}r&=OverLay(b,a)\\\\&=\left\{\begin{aligned}Multiply(2b,a)&&当 0\leq b \leq 0.5\\Screen(2(b-0.5),a)&&当 0.5< b \leq 1\\\end{aligned}\right.\\\\&=\left\{\begin{aligned}2ba&&当 0\leq b \leq 0.5\\1-2(1-b)(1-a)&&当 0.5< b \leq 1\\\end{aligned}\right.\end{aligned} r=OverLay(b,a)={Multiply(2b,a)Screen(2(b−0.5),a)当0≤b≤0.5当0.5<b≤1={2ba1−2(1−b)(1−a)当0≤b≤0.5当0.5<b≤1
和填充还有不透明度的关系,以及公式可以参考正片叠底和滤色
映射面和同图等效曲线
程序模拟该模式计算结果
// 叠加
public static BlendColor Overlay(BlendColor colorBase, BlendColor colorBlend, double fill, double opacity) {
double red = OverlayChannel(colorBase.red.get01Value(), colorBlend.red.get01Value(), fill);
double green = OverlayChannel(colorBase.green.get01Value(), colorBlend.green.get01Value(), fill);
double blue = OverlayChannel(colorBase.blue.get01Value(), colorBlend.blue.get01Value(), fill);
return ColorUtils.Opacity(colorBase, new BlendColor(red *255, green* 255, blue * 255), opacity);
}
private static double OverlayChannel(double baseValue, double blendValue, double fill) {
if (baseValue <= 0.5) {
return MulitplyChannel(baseValue, 2 * blendValue, fill);
} else {
return ScreenChannel(baseValue, 2 * (blendValue - 0.5), fill);
}
}
叠 加(Overlay) RGB[101.08, 71.34, 63.22]~ HSY[12.87, 37.86, 79.37 ]~ HSB[ 12.87, 37.45, 39.64]
验证
用途示例
1:同图混合增加图片对比度
2:和中性灰混合,达到局部提亮或者压黑
柔光SoftLight
柔光模式是最复杂的一种混合模式,也是最巧妙的一种混合模式,柔光模式的本质是伽马矫正(gama correction)。配合混合图层的像素点的通道数值,再对原图层使用伽马矫正,二者通过配合就可以得到柔光模式。
如果我们想了解柔光模式,首先必须了解什么是伽马矫正,伽马矫正,简单来说就是,将原像素通道数值通过幂次方的方式进行修改,比如平方和根号,例如我们由一个归一化之后为0.5的通道数值,我们对其进行系数为2的伽马矫正,则结果是 0. 5 1 2 = 0.5 0.5^{\dfrac{1}{2}}=\sqrt{0.5} 0.521=0.5,如果进行系数为 1 2 \dfrac{1}{2} 21的伽马矫正,则结果为 0. 5 2 0.5^2 0.52
公式
r = S o f t L i g h t ( b , a ) = { ( 2 a − 1 ) ( b 2 − b ) + b a ≤ 0.5 ( 2 a − 1 ) ( b − b ) + b a > 0.5 \begin{aligned}r&= SoftLight(b,a)\\\\&=\left\{\begin{aligned}&(2a-1)(b^2-b)+b&a\leq0.5\\&(2a-1)(\sqrt{b}-b)+b&a>0.5\end{aligned}\right.\end{aligned} r=SoftLight(b,a)={(2a−1)(b2−b)+b(2a−1)(b−b)+ba≤0.5a>0.5
伽马矫正的数学表达式 o u t p u t = i n p u t 1 g a m a output = input^{\dfrac{1}{gama}} output=inputgama1
其中 i n p u t input input代表输入信号, o u t p u t output output代表输出, g a m a gama gama代表伽马系数
系数为 2 2 2的伽马矫正
o u t p u t = i n p u t 1 2 output= input^{\dfrac{1}{2}} output=input21
系数为 1 2 \dfrac{1}{2} 21的伽马矫正
o u t p u t = i n p u t 2 output= input^{2} output=input2
于是对于系数为 1 2 \dfrac{1}{2} 21的伽马矫正,稍微变换一下表达式
r = b 2 = − ( b − b 2 ) + b r =b^2= -(b-b^2) +b r=b2=−(b−b2)+b
然后再使用 ( 2 a − 1 ) (2a-1) (2a−1)作为系数乘以差值项
r = ( 2 a − 1 ) ( b − b 2 ) + b r = (2a-1)(b-b^2) +b r=(2a−1)(b−b2)+b
于是对于系数为 2 2 2的伽马矫正,稍微变换一下表达式
r = b = ( b − b ) + b r =\sqrt{b}= (\sqrt{b}-b) +b r=b=(b−b)+b
然后再使用 ( 2 a − 1 ) (2a-1) (2a−1)作为系数乘以差值项
r = ( 2 a − 1 ) ( b − b ) + b r =(2a-1)(\sqrt{b}-b) +b r=(2a−1)(b−b)+b
再将结果合并,我们就可以得到柔光模式的表达式。
如果使用一句话概括柔光模式的数学表达式,就是“以混合图层为系数的系数为 1 2 \dfrac{1}{2} 21和 2 2 2的伽马矫正”
在 PS中伽马矫正可以在色阶工具和曝光度工具中找到👀
映射面和同图等效曲线
程序模拟该模式计算结果
// 柔光
public static BlendColor SoftLight(BlendColor colorBase, BlendColor colorBlend, double fill, double opacity) {
double red = SoftLightChannel(colorBase.red.get01Value(), colorBlend.red.get01Value(), fill);
double green = SoftLightChannel(colorBase.green.get01Value(), colorBlend.green.get01Value(), fill);
double blue = SoftLightChannel(colorBase.blue.get01Value(), colorBlend.blue.get01Value(), fill);
return ColorUtils.Opacity(colorBase, new BlendColor(red * 255, green * 255, blue * 255), opacity);
}
private static double SoftLightChannel(double baseValue, double blendValue, double fill) {
if (blendValue <= 0.5) {
return (baseValue + (2 * blendValue - 1) * (baseValue - baseValue * baseValue)) * fill
+ (1 - fill) * baseValue;
} else {
return (baseValue + (2 * blendValue - 1) * (Math.sqrt(baseValue) - baseValue)) * fill
+ (1 - fill) * baseValue;
}
}
柔 光(SoftLight) RGB[105.40, 74.06, 63.42]~ HSY[15.21, 41.98, 82.29 ]~ HSB[ 15.21, 39.83, 41.33]
验证
用途示例
1:同图混合增加图片对比度
2:配合中性灰平面,实现局部提亮和压暗(dodge and burn)
强光HardLight
此模式也是正片叠底和滤色的组合,组合的分割界限是混合图层中性灰平面,并且它和叠加模式是互逆的关系,也就是说,如果在强光模式下把基础图层和混合图层顺序调换,可以的到原顺序下叠加模式的效果
公式
r = H a r d L i g h t ( b , a ) = { M u l t i p l y ( b , 2 a ) 当 0 ≤ a ≤ 0.5 S c r e e n ( b , 2 ( a − 0.5 ) ) 当 0.5 < a ≤ 1 = { 2 b a 当 0 ≤ a ≤ 0.5 1 − 2 ( 1 − b ) ( 1 − a ) 当 0.5 < a ≤ 1 \begin{aligned}r&= HardLight(b,a)\\\\&=\left\{\begin{aligned}Multiply(b,2a)&&当 0\leq a \leq 0.5\\Screen(b,2(a-0.5))&&当 0.5< a \leq 1\\\end{aligned}\right.\\\\&=\left\{\begin{aligned}2ba&&当 0\leq a \leq 0.5\\1-2(1-b)(1-a)&&当 0.5< a \leq 1\\\end{aligned}\right.\end{aligned} r=HardLight(b,a)={Multiply(b,2a)Screen(b,2(a−0.5))当0≤a≤0.5当0.5<a≤1={2ba1−2(1−b)(1−a)当0≤a≤0.5当0.5<a≤1
映射面和同图等效曲线
程序模拟该模式计算结果
// 强光
public static BlendColor HardLight(BlendColor colorBase, BlendColor colorBlend, double fill, double opacity) {
double red = HardLightChannel(colorBase.red.get01Value(), colorBlend.red.get01Value(), fill);
double green = HardLightChannel(colorBase.green.get01Value(), colorBlend.green.get01Value(), fill);
double blue = HardLightChannel(colorBase.blue.get01Value(), colorBlend.blue.get01Value(), fill);
return ColorUtils.Opacity(colorBase, new BlendColor(red * 255, green * 255, blue * 255), opacity);
}
private static double HardLightChannel(double baseValue, double blendValue, double fill) {
if (blendValue <= 0.5) {
return MulitplyChannel(baseValue, 2 * blendValue, fill);
} else {
return ScreenChannel(baseValue, 2 * (blendValue - 0.5), fill);
}
}
强 光(HardLight) RGB[101.08, 71.34, 70.46]~ HSY[1.72, 30.61, 80.16 ]~ HSB[ 1.72, 30.29, 39.64]
验证
用途示例
1:同图混合增加图片对比度
2:配合中性灰平面,实现dodge and burn.
线性光LinearLight
线性光是线性减淡和线性加深的结合,组合的分割界限是混合图层中性灰平面,具体公式如下
公式
r = L i n e a r L i g h t ( b , a ) = { L i n e a r B u r n ( b , 2 a ) 当 0 ≤ a ≤ 0.5 L i n e a r D o d g e ( b , 2 ( a − 0.5 ) ) 当 0.5 < a ≤ 1 = { b + ( 2 a ) − 1 当 0 ≤ a ≤ 0.5 b + 2 ( a − 0.5 ) 当 0.5 < a ≤ 1 = b + 2 a − 1 \begin{aligned}r&= LinearLight(b,a)\\\\&=\left\{\begin{aligned}LinearBurn(b,2a)&&当 0\leq a \leq 0.5\\LinearDodge(b,2(a-0.5))&&当 0.5< a \leq 1\\\end{aligned}\right.\\\\&=\left\{\begin{aligned}b+(2a)-1&&当 0\leq a \leq 0.5\\b+2(a-0.5)&&当 0.5< a \leq 1\\\end{aligned}\right.=b+2a-1\end{aligned} r=LinearLight(b,a)={LinearBurn(b,2a)LinearDodge(b,2(a−0.5))当0≤a≤0.5当0.5<a≤1={b+(2a)−1b+2(a−0.5)当0≤a≤0.5当0.5<a≤1=b+2a−1
和填充结合
r = F i l l ( b , a ) = { L i n e a r B u r n ( b , 2 a × f i l l ) 当 0 ≤ a ≤ 0.5 L i n e a r D o d g e ( b , 2 ( a − 0.5 ) × f i l l ) 当 0.5 < a ≤ 1 = { b + ( 2 a ) × f i l l − 1 当 0 ≤ a ≤ 0.5 b + 2 ( a − 0.5 ) × f i l l 当 0.5 < a ≤ 1 = { b + 2 a × f i l l − 1 当 0 ≤ a ≤ 0.5 b + 2 a × f i l l − 0.5 × f i l l 当 0.5 < a ≤ 1 \begin{aligned}r&= Fill(b,a)\\\\&=\left\{\begin{aligned}LinearBurn(b,2a\times fill)&&当 0\leq a \leq 0.5\\LinearDodge(b,2(a-0.5)\times fill)&&当 0.5< a \leq 1\\\end{aligned}\right.\\\\&=\left\{\begin{aligned}b+(2a)\times fill-1&&当 0\leq a \leq 0.5\\b+2(a-0.5)\times fill&&当 0.5< a \leq 1\\\end{aligned}\right.\\\\&=\left\{\begin{aligned}b+2a\times fill-1&&当 0\leq a \leq 0.5\\b+2a\times fill-0.5\times fill&&当 0.5< a \leq 1\\\end{aligned}\right.\end{aligned} r=Fill(b,a)={LinearBurn(b,2a×fill)LinearDodge(b,2(a−0.5)×fill)当0≤a≤0.5当0.5<a≤1={b+(2a)×fill−1b+2(a−0.5)×fill当0≤a≤0.5当0.5<a≤1={b+2a×fill−1b+2a×fill−0.5×fill当0≤a≤0.5当0.5<a≤1
融合不透明度
r = O p a c i t y ( b , a ) = o p × F i l l ( b , a ) + ( 1 − o p ) × b r=Opacity(b,a)=op\times Fill(b,a)+(1-op)\times b r=Opacity(b,a)=op×Fill(b,a)+(1−op)×b
映射面和同图等效曲线
程序模拟该模式计算结果
public static BlendColor LinearLight(BlendColor colorBase, BlendColor colorBlend, double fill, double opacity) {
double red = LinearLightChannel(colorBase.red.get01Value(), colorBlend.red.get01Value(), fill);
double green = LinearLightChannel(colorBase.green.get01Value(), colorBlend.green.get01Value(), fill);
double blue = LinearLightChannel(colorBase.blue.get01Value(), colorBlend.blue.get01Value(), fill);
return ColorUtils.Opacity(colorBase, new BlendColor(red * 255, green * 255, blue * 255), opacity);
}
private static double LinearLightChannel(double baseValue, double blendValue, double fill) {
if (blendValue <= 0.5) {
return LinearBurnChannel(baseValue, 2 * blendValue, fill);
} else {
return LinearDodgeChannel(baseValue, 2 * (blendValue - 0.5), fill);
}
}
线 性 光(LinearLight) RGB[ 88.20, 52.40, 73.68]~ HSY[324.34, 35.80, 65.48]~ HSB[324.34, 40.59, 34.59]
验证
用途示例
1:组成中性灰磨皮
点光PinLight
点光是变暗模式和变亮模式的组合
公式
r = P i n L i g h t ( b , a ) = { D a r k e n ( b , 2 a ) a ≤ 0.5 L i g h t e n ( b , 2 ( a − 0.5 ) ) a > 0.5 = { M i n ( b , 2 a ) a ≤ 0.5 M a x ( b , 2 ( a − 0.5 ) ) a > 0.5 \begin{aligned}r=PinLight(b,a)&=\left\{ \begin{aligned}&Darken(b,2a)&a\leq 0.5\\&Lighten(b,2(a-0.5))&a> 0.5 \end{aligned}\right.\\&\\&=\left\{ \begin{aligned}&Min(b,2a)&a\leq 0.5\\&Max(b,2(a-0.5))&a> 0.5 \end{aligned}\right.\end{aligned} r=PinLight(b,a)={Darken(b,2a)Lighten(b,2(a−0.5))a≤0.5a>0.5={Min(b,2a)Max(b,2(a−0.5))a≤0.5a>0.5
和填充结合
r = F i l l ( b , a ) = { M i n ( b , 2 a × f i l l ) a ≤ 0.5 M a x ( b , 2 ( a − 0.5 ) × f i l l ) a > 0.5 \begin{aligned}r= Fill(b,a)&=\left\{ \begin{aligned}&Min(b,2a\times fill)&a\leq 0.5\\&Max(b,2(a-0.5)\times fill)&a> 0.5 \end{aligned}\right.&\end{aligned} r=Fill(b,a)={Min(b,2a×fill)Max(b,2(a−0.5)×fill)a≤0.5a>0.5
融合不透明度
r = O p a c i t y ( b , a ) = o p × F i l l ( b , a ) + ( 1 − o p ) × b r=Opacity(b,a)=op\times Fill(b,a)+(1-op)\times b r=Opacity(b,a)=op×Fill(b,a)+(1−op)×b
映射面和同图等效曲线
程序模拟该模式计算结果
// 点光
public static BlendColor PinLight(BlendColor colorBase, BlendColor colorBlend, double fill, double opacity) {
double red = PinLightChannel(colorBase.red.get01Value(), colorBlend.red.get01Value(), fill);
double green = PinLightChannel(colorBase.green.get01Value(), colorBlend.green.get01Value(), fill);
double blue = PinLightChannel(colorBase.blue.get01Value(), colorBlend.blue.get01Value(), fill);
return ColorUtils.Opacity(colorBase, new BlendColor(red * 255, green * 255, blue * 255), opacity);
}
private static double PinLightChannel(double baseValue, double blendValue, double fill) {
if (blendValue <= 0.5) {
return DarkenChannel(baseValue, 2 * blendValue, fill);
} else {
return LightenChannel(baseValue, 2 * (blendValue - 0.5), fill);
}
}
点 光(PinLight) RGB[111.00, 80.00, 60.00]~ HSY[23.53, 51.00, 87.10 ]~ HSB[ 23.53, 45.95, 43.53]
验证
用途示例
1:增加图片对比度
亮光VividLight
亮光模式是颜色加深和颜色减淡的组合
公式
r = V i v i d L i g h t ( b , a ) = { C o l o r B u r n ( b , 2 a ) a ≤ 0.5 C o l o r D o d g e ( b , 2 ( a − 0.5 ) ) a > 0.5 = { 1 − ( 1 − b ) 2 a a ≤ 0.5 b 1 − 2 ( a − 0.5 ) a > 0.5 \begin{aligned}r=VividLight(b,a)&=\left\{ \begin{aligned}&ColorBurn(b,2a)&a\leq 0.5\\&ColorDodge(b,2(a-0.5))&a> 0.5 \end{aligned}\right.\\&\\&=\left\{ \begin{aligned}&1-\frac{(1-b)}{2a}&a\leq 0.5\\&\frac{b}{1-2(a-0.5)}&a>0.5\end{aligned}\right.\end{aligned} r=VividLight(b,a)={ColorBurn(b,2a)ColorDodge(b,2(a−0.5))a≤0.5a>0.5=⎩ ⎨ ⎧1−2a(1−b)1−2(a−0.5)ba≤0.5a>0.5
加上fill
r = F I l l ( b , a ) = { C o l o r B u r n ( b , 2 a × f i l l ) a ≤ 0.5 C o l o r D o d g e ( b , 2 ( a − 0.5 ) × f i l l ) a > 0.5 = { 1 − ( 1 − b ) 2 a × f i l l a ≤ 0.5 b 1 − 2 ( a − 0.5 ) × f i l l a > 0.5 \begin{aligned}r=FIll(b,a)&=\left\{ \begin{aligned}&ColorBurn(b,2a\times fill)&a\leq 0.5\\&ColorDodge(b,2(a-0.5)\times fill)&a> 0.5 \end{aligned}\right.\\&\\&=\left\{ \begin{aligned}&1-\frac{(1-b)}{2a\times fill}&a\leq 0.5\\&\frac{b}{1-2(a-0.5)\times fill}&a>0.5\end{aligned}\right.\end{aligned} r=FIll(b,a)={ColorBurn(b,2a×fill)ColorDodge(b,2(a−0.5)×fill)a≤0.5a>0.5=⎩ ⎨ ⎧1−2a×fill(1−b)1−2(a−0.5)×fillba≤0.5a>0.5
融合不透明度
r = O p a c i t y ( b , a ) = o p × F i l l ( b , a ) + ( 1 − o p ) × b r=Opacity(b,a)=op\times Fill(b,a)+(1-op)\times b r=Opacity(b,a)=op×Fill(b,a)+(1−op)×b
映射面和同图等效曲线
程序模拟该模式计算结果
// 亮光
public static BlendColor VividLight(BlendColor colorBase, BlendColor colorBlend, double fill, double opacity) {
double red = VividLightChannel(colorBase.red.get01Value(), colorBlend.red.get01Value(), fill);
double green = VividLightChannel(colorBase.green.get01Value(), colorBlend.green.get01Value(), fill);
double blue = VividLightChannel(colorBase.blue.get01Value(), colorBlend.blue.get01Value(), fill);
return ColorUtils.Opacity(colorBase, new BlendColor(red * 255, green * 255, blue * 255), opacity);
}
private static double VividLightChannel(double baseValue, double blendValue, double fill) {
if (blendValue <= 0.5) {
return ColorBurnChannel(baseValue, 2 * blendValue, fill);
} else {
return ColorDodgeChannel(baseValue, 2 * (blendValue - 0.5), fill);
}
}
亮 光(VividLight) RGB[ 95.87, 56.89, 63.53]~ HSY[349.77, 38.98, 69.31]~ HSB[349.77, 40.66, 37.60]
验证
用途示例
1:同图混合增加图片对比度
2:通道抠图法,去除白边
实色混合HardMix
实色混合是一种极端的混合方式,但是如果它合填充结合,则它会产生一些意想不到的效果,并且我们还能找到它合线性光的关系
公式
r
=
H
a
r
d
M
i
x
(
b
,
a
)
=
{
1
b
+
a
≥
1
0
e
l
s
e
r=HardMix(b,a)=\left\{ \begin{aligned}&1&b+a\geq 1\\&0&else \end{aligned}\right.
r=HardMix(b,a)={10b+a≥1else
由公式我们可以看出,最后的结果只有两个,所以最后之后保留
2
3
=
8
2^3=8
23=8种颜色,也就是
(
0
,
0
,
0
)
黑
(
1
,
0
,
0
)
红
(
1
,
1
,
0
)
黄
(
1
,
1
,
1
)
白
(
0
,
1
,
0
)
绿
(
0
,
1
,
1
)
青
(
1
,
0
,
1
)
品红
(
0
,
0
,
1
)
蓝
\begin{aligned}(0,0,0)&黑\\(1,0,0)&红\\(1,1,0)&黄\\(1,1,1)&白\\(0,1,0)&绿\\(0,1,1)&青\\(1,0,1)&品红\\(0,0,1)&蓝\end{aligned}
(0,0,0)(1,0,0)(1,1,0)(1,1,1)(0,1,0)(0,1,1)(1,0,1)(0,0,1)黑红黄白绿青品红蓝
加上fill
但是如果填充介入表达式,则结果将合线性光类似
r
=
H
a
r
d
M
i
x
f
i
l
l
(
b
,
a
)
=
{
0
f
i
l
l
×
a
+
b
−
f
i
l
l
(
1
−
f
i
l
l
)
<
0
f
i
l
l
×
a
+
b
−
f
i
l
l
(
1
−
f
i
l
l
)
0
≤
f
i
l
l
×
a
+
b
−
f
i
l
l
(
1
−
f
i
l
l
)
≤
1
1
f
i
l
l
×
a
+
b
−
f
i
l
l
(
1
−
f
i
l
l
)
>
1
r=HardMix_{fill}(b,a)=\left\{ \begin{aligned}&0& \frac{fill\times a+b-fill}{(1-fill)}<0\\ &\\ &\frac{fill\times a+b-fill}{(1-fill)}&0\leq \frac{fill\times a+b-fill}{(1-fill)}\leq 1\\&\\ &1& \frac{fill\times a+b-fill}{(1-fill)}>1 \end{aligned}\right.
r=HardMixfill(b,a)=⎩
⎨
⎧0(1−fill)fill×a+b−fill1(1−fill)fill×a+b−fill<00≤(1−fill)fill×a+b−fill≤1(1−fill)fill×a+b−fill>1
如果fill的取值是
0.5
0.5
0.5则
r
=
H
a
r
d
M
i
x
f
i
l
l
(
b
,
a
)
=
{
0
0.5
×
a
+
b
−
0.5
(
1
−
0.5
)
<
0
0.5
×
a
+
b
−
0.5
(
1
−
0.5
)
0
≤
0.5
×
a
+
b
−
0.5
(
1
−
0.5
)
≤
1
1
0.5
×
a
+
b
−
0.5
(
1
−
0.5
)
>
1
=
{
0
a
+
2
b
−
1
<
0
a
+
2
b
−
1
0
≤
a
+
2
b
−
1
≤
1
1
a
+
2
b
−
1
>
1
\begin{aligned}r=HardMix_{fill}(b,a)=&\left\{ \begin{aligned}&0& \frac{0.5\times a+b-0.5}{(1-0.5)}<0\\ &\\ &\frac{0.5\times a+b-0.5}{(1-0.5)}&0\leq \frac{0.5\times a+b-0.5}{(1-0.5)}\leq 1\\ &\\&1& \frac{0.5\times a+b-0.5}{(1-0.5)}>1 \end{aligned}\right.\\&\\&=\left\{ \begin{aligned}&0& a+2b-1<0\\ &\\ &a+2b-1&0\leq a+2b-1\leq 1\\&\\ &1& a+2b-1>1 \end{aligned}\right.\end{aligned}
r=HardMixfill(b,a)=⎩
⎨
⎧0(1−0.5)0.5×a+b−0.51(1−0.5)0.5×a+b−0.5<00≤(1−0.5)0.5×a+b−0.5≤1(1−0.5)0.5×a+b−0.5>1=⎩
⎨
⎧0a+2b−11a+2b−1<00≤a+2b−1≤1a+2b−1>1
上面的结果就是线性光的表达式,也就是说此时二者等价,或者说是互逆,也就是说,实色混合其实是线性光的强化版本,可以实现线性光的功能而去变化更多。
融合不透明度
r = O p a c i t y ( b , a ) = o p × H a r d M i x f i l l ( b , a ) + ( 1 − o p ) × b r=Opacity(b,a)=op\times HardMix_{fill}(b,a)+(1-op)\times b r=Opacity(b,a)=op×HardMixfill(b,a)+(1−op)×b
映射面和同图等效曲线
由此我们可以看出,实色混合可以看作线性减淡和线性加深的组合,也可以看作是颜色减淡和颜色加深的组合,注意这里是可以看作,并不是真的。
但是由我们刚才推导出当填充等于50%的时候,他可以和线性光互逆,此时我们也可以得出结论,实色混合本质是一种特殊的线性减淡和线性加深的组合,并且线性光是实色混合的特殊形式。
线性减淡和线性加深组合方式(真的)
颜色减淡和颜色加深的组合方式(可以看作是这样)
程序模拟该模式计算结果
// 实色混合
public static BlendColor HardMix(BlendColor colorBase, BlendColor colorBlend, double fill, double opacity) {
double red = HardMixChannel(colorBase.red.get01Value(), colorBlend.red.get01Value(), fill);
double green = HardMixChannel(colorBase.green.get01Value(), colorBlend.green.get01Value(), fill);
double blue = HardMixChannel(colorBase.blue.get01Value(), colorBlend.blue.get01Value(), fill);
return ColorUtils.Opacity(colorBase, new BlendColor(red * 255, green * 255, blue * 255), opacity);
}
private static double HardMixChannel(double baseValue, double blendValue, double fill) {
if (fill == 1) {
if (baseValue + blendValue >= 0.5) {
return 1;
}
return 0;
}
return ColorUtils.round((fill * blendValue + baseValue - fill) / (1 - fill), 1, 0);
}
实色混合(HardMix) RGB[ 85.40, 38.00, 44.40]~ HSY[351.90, 47.40, 52.92]~ HSB[351.90, 55.50, 33.49]
验证
用途示例
1:同图混合增加图片对比度
2:特殊光效,可以根据fill调节
差值组
差值Difference
差值就是基础图层和混合图层好的差值的绝对值
公式
r = D i f f e r e n c e ( b , a ) = ∣ b − a ∣ r=Difference(b,a)=|b-a| r=Difference(b,a)=∣b−a∣
结合填充
r = F i l l ( b , a ) = ∣ b − a ∣ × f i l l + ( 1 − f i l l ) × b r=Fill(b,a)=|b-a|\times fill + (1-fill)\times b r=Fill(b,a)=∣b−a∣×fill+(1−fill)×b
融合不透明度
r = O p a c i t y ( b , a ) = o p × F i l l ( b , a ) + ( 1 − o p ) × b r=Opacity(b,a)=op\times Fill(b,a)+(1-op)\times b r=Opacity(b,a)=op×Fill(b,a)+(1−op)×b
映射面和同图等效曲线
程序模拟该模式计算结果
// 差值
public static BlendColor Difference(BlendColor colorBase, BlendColor colorBlend, double fill, double opacity) {
double red = DifferenceChannel(colorBase.red.get01Value(), colorBlend.red.get01Value(), fill);
double green = DifferenceChannel(colorBase.green.get01Value(), colorBlend.green.get01Value(), fill);
double blue = DifferenceChannel(colorBase.blue.get01Value(), colorBlend.blue.get01Value(), fill);
return ColorUtils.Opacity(colorBase, new BlendColor(red * 255, green * 255, blue * 255), opacity);
}
private static double DifferenceChannel(double baseValue, double blendValue, double fill) {
return ColorUtils.round(Math.abs(baseValue - blendValue * fill), 1, 0);
}
差 值(Difference) RGB[ 91.80, 63.20, 25.44]~ HSY[34.14, 66.36, 67.63 ]~ HSB[ 34.14, 72.29, 36.00]
验证
用途示例
1:对齐图片
2:颜色矫正
排除Exclusion
公式
r = E x c l u s i o n ( b , a ) = b + a − 2 b a r=Exclusion(b,a)=b+a-2ba r=Exclusion(b,a)=b+a−2ba
结合填充
r = F i l l ( b , a ) = ( b + a − 2 b a ) × f i l l + ( 1 − f i l l ) × b r=Fill(b,a)=(b+a-2ba)\times fill + (1-fill)\times b r=Fill(b,a)=(b+a−2ba)×fill+(1−fill)×b
融合不透明度
r = O p a c i t y ( b , a ) = o p × F i l l ( b , a ) + ( 1 − o p ) × b r=Opacity(b,a)=op\times Fill(b,a)+(1-op)\times b r=Opacity(b,a)=op×Fill(b,a)+(1−op)×b
如果在该模式下,混合图层是白色,黑色或者中性灰色
白色
r
=
E
x
c
l
u
s
i
o
n
(
b
,
1
)
=
b
+
1
−
2
b
×
1
=
1
−
b
r=Exclusion(b,1)=b+1-2b\times 1=1-b
r=Exclusion(b,1)=b+1−2b×1=1−b
等于负片
黑色
r
=
E
x
c
l
u
s
i
o
n
(
b
,
0
)
=
b
+
1
−
2
b
×
0
=
b
r=Exclusion(b,0)=b+1-2b\times 0=b
r=Exclusion(b,0)=b+1−2b×0=b
等于原图
中性灰
r
=
E
x
c
l
u
s
i
o
n
(
b
,
1
2
)
=
b
+
1
2
−
2
b
×
1
2
=
1
2
r=Exclusion(b,\dfrac{1}{2})=b+\dfrac{1}{2}-2b\times \dfrac{1}{2}=\dfrac{1}{2}
r=Exclusion(b,21)=b+21−2b×21=21
依然是中性灰
映射面和同图等效曲线
程序模拟该模式计算结果
// 排除
public static BlendColor Exclusion(BlendColor colorBase, BlendColor colorBlend, double fill, double opacity) {
double red = ExclusionChannel(colorBase.red.get01Value(), colorBlend.red.get01Value(), fill);
double green = ExclusionChannel(colorBase.green.get01Value(), colorBlend.green.get01Value(), fill);
double blue = ExclusionChannel(colorBase.blue.get01Value(), colorBlend.blue.get01Value(), fill);
return ColorUtils.Opacity(colorBase, new BlendColor(red *255, green* 255, blue * 255), opacity);
}
private static double ExclusionChannel(double baseValue, double blendValue, double fill) {
return ColorUtils.round((baseValue + blendValue - 2 * baseValue * blendValue) * fill + (1 - fill) * baseValue,
1, 0);
}
排 除(Exclusion) RGB[113.48, 86.26, 79.82]~ HSY[11.47, 33.66, 93.72 ]~ HSB[ 11.47, 29.66, 44.50]
验证
用途示例
制作特殊光效,比如人物肖像
减去Subtract
公式
r = S u b t r a c t ( b , a ) = b − a r=Subtract(b,a)= b-a r=Subtract(b,a)=b−a
结合填充
r = F i l l ( b , a ) = r o u n d ( b − a ) × f i l l + ( 1 − f i l l ) × b r=Fill(b,a)=round(b-a)\times fill + (1-fill)\times b r=Fill(b,a)=round(b−a)×fill+(1−fill)×b
融合不透明度
r = O p a c i t y ( b , a ) = o p × F i l l ( b , a ) + ( 1 − o p ) × b r=Opacity(b,a)=op\times Fill(b,a)+(1-op)\times b r=Opacity(b,a)=op×Fill(b,a)+(1−op)×b
映射面和同图等效曲线
程序模拟该模式计算结果
// 减去
public static BlendColor Substact(BlendColor colorBase, BlendColor colorBlend, double fill, double opacity) {
double red = SubstactChannel(colorBase.red.get01Value(), colorBlend.red.get01Value(), fill);
double green = SubstactChannel(colorBase.green.get01Value(), colorBlend.green.get01Value(), fill);
double blue = SubstactChannel(colorBase.blue.get01Value(), colorBlend.blue.get01Value(), fill);
return ColorUtils.Opacity(colorBase, new BlendColor(red *255, green* 255, blue * 255), opacity);
}
private static double SubstactChannel(double baseValue, double blendValue, double fill) {
return ColorUtils.round(ColorUtils.round((baseValue - blendValue), 1, 0) *fill + (1 - fill)* baseValue, 1, 0);
}
减 去(Substact) RGB[ 91.80, 63.20, 45.60]~ HSY[22.86, 46.20, 69.84 ]~ HSB[ 22.86, 50.33, 36.00]
验证
制作线稿效果
划分Divide
公式
r = D i v i d e ( b , a ) = b a r=Divide(b,a)= \dfrac{b}{a} r=Divide(b,a)=ab
结合填充
r = F i l l ( b , a ) = b a × f i l l + ( 1 − f i l l ) × b r=Fill(b,a)= \dfrac{b}{a}\times fill + (1-fill)\times b r=Fill(b,a)=ab×fill+(1−fill)×b
融合不透明度
r
=
O
p
a
c
i
t
y
(
b
,
a
)
=
o
p
×
F
i
l
l
(
b
,
a
)
+
(
1
−
o
p
)
×
b
r=Opacity(b,a)=op\times Fill(b,a)+(1-op)\times b
r=Opacity(b,a)=op×Fill(b,a)+(1−op)×b
划分和颜色减淡可以通过一次负片操作转换
一次负片
r = D i v i d e ( b , 1 − a ) = b 1 − a = C o l o r D o d g e ( b , a ) r=Divide(b,1-a)=\dfrac{b}{1-a}=ColorDodge(b,a) r=Divide(b,1−a)=1−ab=ColorDodge(b,a)
映射面和同图等效曲线
程序模拟该模式计算结果
// 划分
public static BlendColor Divide(BlendColor colorBase, BlendColor colorBlend, double fill, double opacity) {
double red = DivdeChannel(colorBase.red.get01Value(), colorBlend.red.get01Value(), fill);
double green = DivdeChannel(colorBase.green.get01Value(), colorBlend.green.get01Value(), fill);
double blue = DivdeChannel(colorBase.blue.get01Value(), colorBlend.blue.get01Value(), fill);
return ColorUtils.Opacity(colorBase, new BlendColor(red * 255, green * 255, blue * 255), opacity);
}
private static double DivdeChannel(double baseValue, double blendValue, double fill) {
return ColorUtils.round(Math.min(1, baseValue / blendValue) * fill + (1 - fill) * baseValue, 1, 0);
}
划 分(Divide) RGB[145.56, 122.00, 69.14]~ HSY[41.50, 76.42, 123.25 ]~ HSB[ 41.50, 52.50, 57.08]
验证
用途示例
颜色矫正
颜色组
这一组和其他都不同,这一组是基于HSY颜色空间,并且设计的计算都是方程组
转化伪代码
计算明度
L
u
m
(
C
)
=
0.3
×
C
r
e
d
+
0.59
×
C
g
r
e
e
n
+
0.11
×
C
b
l
u
e
Lum(C)=0.3\times C_{red}+0.59\times C_{green} + 0.11\times C_{blue}
Lum(C)=0.3×Cred+0.59×Cgreen+0.11×Cblue
计算饱和度
S
a
t
(
C
)
=
M
a
x
(
C
r
e
d
,
C
g
r
e
e
n
,
C
b
l
u
e
)
Sat(C)=Max(C_{red},C_{green},C_{blue})
Sat(C)=Max(Cred,Cgreen,Cblue)
这里采用了比较取巧的做法,就是只涉及饱和度和明度的改变,不涉及直接改变色相,因为改变色相相当于直接同时改变饱和度和明度。
下面是改变明度的伪代码
S
e
t
L
u
m
(
C
,
l
u
m
)
l
u
m
−
L
u
m
(
C
)
C
r
e
d
=
C
r
e
d
+
d
C
g
r
e
e
n
=
C
g
r
e
e
n
+
d
C
b
l
u
e
=
C
b
l
u
e
+
d
r
e
t
u
r
n
C
l
i
p
C
o
l
o
r
(
C
)
\begin{aligned}SetLum(C,lum)&\\& \begin{aligned}&lum - Lum(C)\\&C_{red}=C_{red}+d\\& C_{green}=C_{green}+d\\&C_{blue}=C_{blue}+d\\ &return\space ClipColor(C)\end{aligned}\end{aligned}
SetLum(C,lum)lum−Lum(C)Cred=Cred+dCgreen=Cgreen+dCblue=Cblue+dreturn ClipColor(C)
这是修改饱和度的伪代码
S
e
t
S
a
t
(
C
,
s
a
t
)
i
f
C
m
a
x
>
C
m
i
n
C
m
i
d
=
(
C
m
i
d
−
C
m
i
n
)
×
s
a
t
C
m
a
x
−
C
m
i
n
C
m
a
x
=
s
a
t
e
l
s
e
C
m
i
d
=
C
m
a
x
=
0
C
m
i
n
=
0
r
e
t
u
r
n
C
\begin{aligned}SetSat(C,sat)&\\&\begin{aligned}&if \quad C_{max}>C_{min}\\&\quad C_{mid}=\dfrac{(C_{mid}-C_{min})\times sat}{C_{max}-C_{min}}\\&\quad C_{max}=sat\\&else\\&\quad C_{mid}=C_{max}=0\\&C_{min}=0\\&return \quad C\end{aligned}\end{aligned}
SetSat(C,sat)ifCmax>CminCmid=Cmax−Cmin(Cmid−Cmin)×satCmax=satelseCmid=Cmax=0Cmin=0returnC
这是矫正误差的伪代码
C
l
i
p
C
o
l
o
r
(
C
)
l
u
m
=
L
u
m
(
c
)
m
i
n
=
M
i
n
(
C
r
e
d
,
C
g
r
e
e
n
,
C
b
l
u
e
)
m
a
x
=
M
a
x
(
C
r
e
d
,
C
g
r
e
e
n
,
C
b
l
u
e
)
i
f
m
i
n
<
0
C
r
e
d
=
l
u
m
+
(
C
r
e
d
−
l
u
m
)
×
l
u
m
l
u
m
−
m
i
n
C
g
r
e
e
n
=
l
u
m
+
(
C
g
r
e
e
n
−
l
u
m
)
×
l
u
m
l
u
m
−
m
i
n
C
b
l
u
e
=
l
u
m
+
(
C
b
l
u
e
−
l
u
m
)
×
l
u
m
l
u
m
−
m
i
n
i
f
m
a
x
>
1
C
r
e
d
=
l
u
m
+
(
C
r
e
d
−
l
u
m
)
×
(
1
−
l
u
m
)
m
a
x
−
l
u
m
C
g
r
e
e
n
=
l
u
m
+
(
C
g
r
e
e
n
−
l
u
m
)
×
(
1
−
l
u
m
)
m
a
x
−
l
u
m
C
b
l
u
e
=
l
u
m
+
(
C
b
l
u
e
−
l
u
m
)
×
(
1
−
l
u
m
)
m
a
x
−
l
u
m
r
e
t
u
r
n
C
\begin{aligned} ClipColor(C)&\\&\begin{aligned}&lum= Lum(c)\\&min = Min(C_{red},C_{green},C_{blue}) \\&max = Max(C_{red},C_{green},C_{blue})\\&if \space min<0\\&\quad C_{red}=lum+\dfrac{(C_{red}-lum)\times lum}{lum-min}\\&\quad C_{green}=lum+\dfrac{(C_{green}-lum)\times lum}{lum-min}\\&\quad C_{blue}=lum+\dfrac{(C_{blue}-lum)\times lum}{lum-min}\\&if \space max>1\\&\quad C_{red}=lum+\dfrac{(C_{red}-lum)\times (1-lum)}{max-lum}\\&\quad C_{green}=lum+\dfrac{(C_{green}-lum)\times (1-lum)}{max-lum}\\&\quad C_{blue}=lum+\dfrac{(C_{blue}-lum)\times (1-lum)}{max-lum}\\&return\space C\end{aligned}\end{aligned}
ClipColor(C)lum=Lum(c)min=Min(Cred,Cgreen,Cblue)max=Max(Cred,Cgreen,Cblue)if min<0Cred=lum+lum−min(Cred−lum)×lumCgreen=lum+lum−min(Cgreen−lum)×lumCblue=lum+lum−min(Cblue−lum)×lumif max>1Cred=lum+max−lum(Cred−lum)×(1−lum)Cgreen=lum+max−lum(Cgreen−lum)×(1−lum)Cblue=lum+max−lum(Cblue−lum)×(1−lum)return C
色相Hue
计算方法是基于这个公式
(
H
r
,
S
r
,
Y
r
)
=
H
u
e
(
(
H
a
,
S
a
,
Y
a
)
,
(
H
b
,
S
b
,
Y
b
)
)
=
(
H
a
,
S
b
,
Y
b
)
(H_r,S_r,Y_r)=Hue((H_a,S_a,Y_a),(H_b,S_b,Y_b))=(H_a,S_b,Y_b)
(Hr,Sr,Yr)=Hue((Ha,Sa,Ya),(Hb,Sb,Yb))=(Ha,Sb,Yb)
算出HSY的值之后再把HSY转化为RGB的数值
此时我们想修改基础图层的色相,但是我们只有修改饱和度和明度的公式,于是我们直接对混合图层使用设置饱和度和明度于是我们得到
H
u
e
(
C
b
,
C
a
)
=
S
e
t
L
u
m
(
S
e
t
S
a
t
(
C
a
,
S
a
t
(
C
b
)
)
,
L
u
m
(
C
b
)
)
Hue(C_b,C_a)=SetLum(SetSat(C_a,Sat(C_b)),Lum(C_b))
Hue(Cb,Ca)=SetLum(SetSat(Ca,Sat(Cb)),Lum(Cb))
结合填充
r = F i l l ( C b , C a ) = H u e ( C b , C a ) × f i l l + ( 1 − f i l l ) × C b r=Fill(C_b,C_a)= Hue(C_b,C_a) \times fill + (1-fill)\times C_b r=Fill(Cb,Ca)=Hue(Cb,Ca)×fill+(1−fill)×Cb
融合不透明度
r = O p a c i t y ( C b , C a ) = o p × F i l l ( C b , C a ) + ( 1 − o p ) × C b r=Opacity(C_b,C_a)=op\times Fill(C_b,C_a)+(1-op)\times C_b r=Opacity(Cb,Ca)=op×Fill(Cb,Ca)+(1−op)×Cb
程序模拟该模式计算结果
// 色相模式
public static BlendColor HUE(BlendColor colorBase, BlendColor colorBlend, double fill, double opacity) {
BlendColor temp = HUE_Sub(colorBase, colorBlend);
double red = temp.red.get01Value() * fill + colorBase.red.get01Value() * (1 - fill);
double green = temp.green.get01Value() * fill + colorBase.green.get01Value() * (1 - fill);
double blue = temp.blue.get01Value() * fill + colorBase.blue.get01Value() * (1 - fill);
return ColorUtils.Opacity(colorBase, new BlendColor(red * 255, green * 255, blue * 255), opacity);
}
private static BlendColor HUE_Sub(BlendColor colorBase, BlendColor colorBlend) {
return ColorUtils.setLum(ColorUtils.setSat(colorBlend, colorBase.getSat()), colorBase.getLum());
}
色 相(hue) RGB[104.91, 79.93, 76.97]~ HSY[6.36, 27.94, 87.10 ]~ HSB[ 6.36, 26.63, 41.14]
验证
用途示例
饱和度Saturation
公式
计算方法是基于这个公式
(
H
r
,
S
r
,
Y
r
)
=
S
a
t
u
r
a
t
i
o
n
(
(
H
a
,
S
a
,
Y
a
)
,
(
H
b
,
S
b
,
Y
b
)
)
=
(
H
b
,
S
a
,
Y
b
)
(H_r,S_r,Y_r)= Saturation((H_a,S_a,Y_a),(H_b,S_b,Y_b))=(H_b,S_a,Y_b)
(Hr,Sr,Yr)=Saturation((Ha,Sa,Ya),(Hb,Sb,Yb))=(Hb,Sa,Yb)
设置饱和度,就直接对基础图层使用设置饱和度
S
a
t
u
r
a
t
i
o
n
(
C
b
,
C
a
)
=
S
e
t
L
u
m
(
S
e
t
S
a
t
(
C
b
,
S
a
t
(
C
s
)
)
,
L
u
m
(
C
b
)
)
Saturation(C_b,C_a)=SetLum(SetSat(C_b,Sat(C_s)),Lum(C_b))
Saturation(Cb,Ca)=SetLum(SetSat(Cb,Sat(Cs)),Lum(Cb))
结合填充
r = F i l l ( C b , C a ) = S a t u r a t i o n ( C b , C a ) f i l l + ( 1 − f i l l ) × C b r=Fill(C_b,C_a)= Saturation(C_b,C_a) fill + (1-fill)\times C_b r=Fill(Cb,Ca)=Saturation(Cb,Ca)fill+(1−fill)×Cb
融合不透明度
r = O p a c i t y ( C b , C a ) = o p × F i l l ( C b , C a ) + ( 1 − o p ) × C b r=Opacity(C_b,C_a)=op\times Fill(C_b,C_a)+(1-op)\times C_b r=Opacity(Cb,Ca)=op×Fill(Cb,Ca)+(1−op)×Cb
程序模拟该模式计算结果
// 饱和度模式
public static BlendColor Saturation(BlendColor colorBase, BlendColor colorBlend, double fill, double opacity) {
double redbase = colorBase.red.get01Value();
double greenbase = colorBase.green.get01Value();
double bluebase = colorBase.blue.get01Value();
BlendColor temp = Saturation_Sub(colorBase, colorBlend);
double red = temp.red.get01Value() * fill + redbase * (1 - fill);
double green = temp.green.get01Value() * fill + greenbase * (1 - fill);
double blue = temp.blue.get01Value() * fill + bluebase * (1 - fill);
return ColorUtils.Opacity(new BlendColor(redbase * 255, greenbase * 255, bluebase * 255),
new BlendColor(red * 255, green * 255, blue * 255), opacity);
}
private static BlendColor Saturation_Sub(BlendColor colorBase, BlendColor colorBlend) {
double sat = colorBlend.getSat();
double lum = colorBase.getLum();
return ColorUtils.setLum(ColorUtils.setSat(colorBase, sat), lum);
}
饱 和 度(Saturation) RGB[114.94, 78.83, 55.54]~ HSY[23.53, 59.40, 87.10 ]~ HSB[ 23.53, 51.68, 45.07]
验证
用途示例
颜色匹配
颜色Color
计算方法是基于这个公式
(
H
r
,
S
r
,
Y
r
)
=
C
o
l
o
r
(
(
H
a
,
S
a
,
Y
a
)
,
(
H
b
,
S
b
,
Y
b
)
)
=
(
H
a
,
S
a
,
Y
b
)
(H_r,S_r,Y_r)= Color((H_a,S_a,Y_a),(H_b,S_b,Y_b))=(H_a,S_a,Y_b)
(Hr,Sr,Yr)=Color((Ha,Sa,Ya),(Hb,Sb,Yb))=(Ha,Sa,Yb)
直接对混合图层使用设置明度,则可以得到需要的等效结果
C
o
l
o
r
(
C
b
,
C
a
)
=
S
e
t
L
u
m
(
C
a
,
L
u
m
(
C
b
)
)
Color(C_b,C_a)=SetLum(C_a,Lum(C_b))
Color(Cb,Ca)=SetLum(Ca,Lum(Cb))
结合填充
r = F i l l ( C b , C a ) = S a t u r a t i o n ( C b , C a ) f i l l + ( 1 − f i l l ) × C b r=Fill(C_b,C_a)= Saturation(C_b,C_a) fill + (1-fill)\times C_b r=Fill(Cb,Ca)=Saturation(Cb,Ca)fill+(1−fill)×Cb
融合不透明度
r = O p a c i t y ( C b , C a ) = o p × F i l l ( C b , C a ) + ( 1 − o p ) × C b r=Opacity(C_b,C_a)=op\times Fill(C_b,C_a)+(1-op)\times C_b r=Opacity(Cb,Ca)=op×Fill(Cb,Ca)+(1−op)×Cb
程序模拟该模式计算结果
// 颜色模式
public static BlendColor BlendColor(BlendColor colorBase, BlendColor colorBlend, double fill, double opacity) {
BlendColor temp = Color_Sub(colorBase, colorBlend);
double red = temp.red.get01Value() * fill + colorBase.red.get01Value() * (1 - fill);
double green = temp.green.get01Value() * fill + colorBase.green.get01Value() * (1 - fill);
double blue = temp.blue.get01Value() * fill + colorBase.blue.get01Value() * (1 - fill);
return ColorUtils.Opacity(colorBase, new BlendColor(red * 255, green * 255, blue * 255), opacity);
}
private static BlendColor Color_Sub(BlendColor colorBase, BlendColor colorBlend) {
return ColorUtils.setLum(colorBlend, colorBase.getLum());
}
颜 色(BlendColor) RGB[104.67, 78.71, 84.15]~ HSY[347.43, 25.96, 87.10]~ HSB[347.43, 24.80, 41.05]
验证
用途示例
明度Luminosity
计算方法是基于这个公式
(
H
r
,
S
r
,
Y
r
)
=
L
u
m
i
n
o
s
i
t
y
(
(
H
a
,
S
a
,
Y
a
)
,
(
H
b
,
S
b
,
Y
b
)
)
=
(
H
b
,
S
b
,
Y
a
)
(H_r,S_r,Y_r)= Luminosity((H_a,S_a,Y_a),(H_b,S_b,Y_b))=(H_b,S_b,Y_a)
(Hr,Sr,Yr)=Luminosity((Ha,Sa,Ya),(Hb,Sb,Yb))=(Hb,Sb,Ya)
设置明度,就直接使用设置明度
L u m i n o s i t y ( C b , C a ) = S e t L u m ( C b , L u m ( C a ) ) Luminosity(C_b,C_a)=SetLum(C_b,Lum(C_a)) Luminosity(Cb,Ca)=SetLum(Cb,Lum(Ca))
结合填充
r = F i l l ( C b , C a ) = L u m i n o s i t y ( C b , C a ) f i l l + ( 1 − f i l l ) × C b r=Fill(C_b,C_a)= Luminosity(C_b,C_a) fill + (1-fill)\times C_b r=Fill(Cb,Ca)=Luminosity(Cb,Ca)fill+(1−fill)×Cb
融合不透明度
r = O p a c i t y ( C b , C a ) = o p × F i l l ( C b , C a ) + ( 1 − o p ) × C b r=Opacity(C_b,C_a)=op\times Fill(C_b,C_a)+(1-op)\times C_b r=Opacity(Cb,Ca)=op×Fill(Cb,Ca)+(1−op)×Cb
程序模拟该模式计算结果
// 明度模式
public static BlendColor Luminosity(BlendColor colorBase, BlendColor colorBlend, double fill, double opacity) {
BlendColor temp = Luminosity_Sub(colorBase, colorBlend);
double red = temp.red.get01Value() *fill + colorBase.red.get01Value()* (1 - fill);
double green = temp.green.get01Value() *fill + colorBase.green.get01Value()* (1 - fill);
double blue = temp.blue.get01Value() *fill + colorBase.blue.get01Value()* (1 - fill);
return ColorUtils.Opacity(colorBase, new BlendColor(red *255, green* 255, blue * 255), opacity);
}
private static BlendColor Luminosity_Sub(BlendColor colorBase, BlendColor colorBlend) {
return ColorUtils.setLum(colorBase, colorBlend.getLum());
}
明 度(Luminosity) RGB[109.89, 78.89, 58.89]~ HSY[23.53, 51.00, 85.99 ]~ HSB[ 23.53, 46.41, 43.09]
验证
用途示例
和黑白调整图层配合,可以实现一些特殊效果
特殊的5种模式
穿透
穿透会出现在建立分组的时候,如果选择穿透,则此时效果和不建分组一样,但是如果修改为正常或者其他模式,则会先把这一组的图层计算出结果,然后用结果作为混合图层和下方图层进行运算。
相加
相加在计算和应用图像中,此时相当于强化的线性减淡,公式为
A
d
d
(
b
,
a
)
=
b
+
a
缩放
+
补偿值
Add(b,a)= \dfrac{b+a}{缩放}+补偿值
Add(b,a)=缩放b+a+补偿值
缩放的取值范围是
[
1
,
2
]
[1,2]
[1,2]
补偿值的取值范围是
[
0
,
255
]
[0,255]
[0,255]
相减
相减在计算和应用图像中,此时相当于强化的减去,公式为
S
u
b
t
r
a
c
t
(
b
,
a
)
=
b
−
a
缩放
+
补偿值
Subtract(b,a)= \dfrac{b-a}{缩放}+补偿值
Subtract(b,a)=缩放b−a+补偿值
缩放的取值范围是
[
1
,
2
]
[1,2]
[1,2]
补偿值的取值范围是
[
0
,
255
]
[0,255]
[0,255]
背后
背后模式
简单来说就是,有像素点则笔刷或油漆桶工具不能修改,没有像素点的透明像素可以被修改。
擦除
功能相当于橡皮擦
调整图层和图层混合模式
如果调整图层和混合图层混用会发生什么
我们假设调整图层为
A
d
j
u
s
t
m
e
n
t
(
L
a
y
e
r
)
Adjustment(Layer)
Adjustment(Layer),
则对于像素点
A
d
j
u
s
t
m
e
n
t
(
p
i
x
)
Adjustment(pix)
Adjustment(pix),
对于通道
A
d
j
u
s
t
m
e
n
t
(
c
h
a
n
n
e
l
)
Adjustment(channel)
Adjustment(channel)
则结果公式可以写作
r
=
B
l
e
n
d
M
o
d
e
(
b
,
A
d
j
u
s
t
m
e
n
t
(
b
)
)
r=BlendMode(b,Adjustment(b))
r=BlendMode(b,Adjustment(b))
也就是说相当于,先使用调整图层产生基础图层调整之后的图层,再使用调整后的图层和原先的基础图层进行图层混合模式的操作。
此处我们以曲线调整图层为例
如果我们对原图层新建调整图层,并且对调整图层使用图层混合模式
如果是正常模式,则相当于原图,但是只要我们选择一个别的模式,或拉一下曲线,结果就会不同。
我们可以看到在不拉曲线的前提下,结果和直接用原图做正片叠底是一样的。
参考文档
http://www.simplefilter.de/en/basics/mixmods.html
https://printtechnologies.org/wp-content/uploads/2020/03/pdf-reference-1.6-addendum-blend-modes.pdf