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

news2024/11/27 10:06:03

对比度组

叠加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(b0.5),a)0b0.50.5<b1={2ba12(1b)(1a)0b0.50.5<b1

和填充还有不透明度的关系,以及公式可以参考正片叠底和滤色

映射面和同图等效曲线

Image

程序模拟该模式计算结果

// 叠加
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]

验证

Image

用途示例

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)={(2a1)(b2b)+b(2a1)(b b)+ba0.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

Image

于是对于系数为 1 2 \dfrac{1}{2} 21的伽马矫正,稍微变换一下表达式

r = b 2 = − ( b − b 2 ) + b r =b^2= -(b-b^2) +b r=b2=(bb2)+b

然后再使用 ( 2 a − 1 ) (2a-1) (2a1)作为系数乘以差值项

r = ( 2 a − 1 ) ( b − b 2 ) + b r = (2a-1)(b-b^2) +b r=(2a1)(bb2)+b

Image

于是对于系数为 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) (2a1)作为系数乘以差值项

r = ( 2 a − 1 ) ( b − b ) + b r =(2a-1)(\sqrt{b}-b) +b r=(2a1)(b b)+b

再将结果合并,我们就可以得到柔光模式的表达式。

如果使用一句话概括柔光模式的数学表达式,就是“以混合图层为系数的系数为 1 2 \dfrac{1}{2} 21 2 2 2的伽马矫正”

在 PS中伽马矫正可以在色阶工具和曝光度工具中找到👀

映射面和同图等效曲线

Image

程序模拟该模式计算结果

    // 柔光
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]

验证

Image

用途示例

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(a0.5))0a0.50.5<a1={2ba12(1b)(1a)0a0.50.5<a1

映射面和同图等效曲线

Image

程序模拟该模式计算结果

    // 强光
    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]

验证

Image

用途示例

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(a0.5))0a0.50.5<a1={b+(2a)1b+2(a0.5)0a0.50.5<a1=b+2a1

和填充结合

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(a0.5)×fill)0a0.50.5<a1={b+(2a)×fill1b+2(a0.5)×fill0a0.50.5<a1={b+2a×fill1b+2a×fill0.5×fill0a0.50.5<a1

融合不透明度

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)+(1op)×b

映射面和同图等效曲线

Image

程序模拟该模式计算结果

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]

验证

Image

用途示例

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(a0.5))a0.5a>0.5={Min(b,2a)Max(b,2(a0.5))a0.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(a0.5)×fill)a0.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)+(1op)×b

映射面和同图等效曲线

Image

程序模拟该模式计算结果

    // 点光
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]

验证

Image

用途示例

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(a0.5))a0.5a>0.5= 12a(1b)12(a0.5)ba0.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(a0.5)×fill)a0.5a>0.5= 12a×fill(1b)12(a0.5)×fillba0.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)+(1op)×b

映射面和同图等效曲线

Image

程序模拟该模式计算结果

    // 亮光
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]

验证

Image

用途示例

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+a1else
由公式我们可以看出,最后的结果只有两个,所以最后之后保留 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(1fill)fill×a+bfill1(1fill)fill×a+bfill<00(1fill)fill×a+bfill1(1fill)fill×a+bfill>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(10.5)0.5×a+b0.51(10.5)0.5×a+b0.5<00(10.5)0.5×a+b0.51(10.5)0.5×a+b0.5>1= 0a+2b11a+2b1<00a+2b11a+2b1>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)+(1op)×b

映射面和同图等效曲线

由此我们可以看出,实色混合可以看作线性减淡和线性加深的组合,也可以看作是颜色减淡和颜色加深的组合,注意这里是可以看作,并不是真的。
但是由我们刚才推导出当填充等于50%的时候,他可以和线性光互逆,此时我们也可以得出结论,实色混合本质是一种特殊的线性减淡和线性加深的组合,并且线性光是实色混合的特殊形式。
Image
线性减淡和线性加深组合方式(真的)
Image
颜色减淡和颜色加深的组合方式(可以看作是这样)

程序模拟该模式计算结果

    // 实色混合
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]

验证

Image

用途示例

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)=ba

结合填充

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)=ba×fill+(1fill)×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)+(1op)×b

映射面和同图等效曲线

Image

程序模拟该模式计算结果

    // 差值
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]

验证

Image

用途示例

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+a2ba

结合填充

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+a2ba)×fill+(1fill)×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)+(1op)×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+12b×1=1b
等于负片

黑色

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+12b×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+212b×21=21
依然是中性灰

映射面和同图等效曲线

Image

程序模拟该模式计算结果

// 排除
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]

验证

Image

用途示例

制作特殊光效,比如人物肖像

减去Subtract

公式

r = S u b t r a c t ( b , a ) = b − a r=Subtract(b,a)= b-a r=Subtract(b,a)=ba

结合填充

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(ba)×fill+(1fill)×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)+(1op)×b

映射面和同图等效曲线

Image

程序模拟该模式计算结果

// 减去
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]

验证

Image

制作线稿效果

划分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+(1fill)×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)+(1op)×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,1a)=1ab=ColorDodge(b,a)

映射面和同图等效曲线

Image

程序模拟该模式计算结果

    // 划分
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]

验证

Image

用途示例

颜色矫正

颜色组

这一组和其他都不同,这一组是基于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)lumLum(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=CmaxCmin(CmidCmin)×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+lummin(Credlum)×lumCgreen=lum+lummin(Cgreenlum)×lumCblue=lum+lummin(Cbluelum)×lumif max>1Cred=lum+maxlum(Credlum)×(1lum)Cgreen=lum+maxlum(Cgreenlum)×(1lum)Cblue=lum+maxlum(Cbluelum)×(1lum)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+(1fill)×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)+(1op)×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]

验证

Image

用途示例

饱和度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+(1fill)×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)+(1op)×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]

验证

Image

用途示例

颜色匹配

颜色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+(1fill)×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)+(1op)×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]

验证

Image

用途示例

明度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+(1fill)×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)+(1op)×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]

验证

Image

用途示例

和黑白调整图层配合,可以实现一些特殊效果

特殊的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)=缩放ba+补偿值
缩放的取值范围是 [ 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))
也就是说相当于,先使用调整图层产生基础图层调整之后的图层,再使用调整后的图层和原先的基础图层进行图层混合模式的操作。
此处我们以曲线调整图层为例
如果我们对原图层新建调整图层,并且对调整图层使用图层混合模式

Image
如果是正常模式,则相当于原图,但是只要我们选择一个别的模式,或拉一下曲线,结果就会不同。
Image
我们可以看到在不拉曲线的前提下,结果和直接用原图做正片叠底是一样的。
Image

参考文档

http://www.simplefilter.de/en/basics/mixmods.html
https://printtechnologies.org/wp-content/uploads/2020/03/pdf-reference-1.6-addendum-blend-modes.pdf

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/761259.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

专项练习29

目录 一、选择题 1、如果修改obj里面的name属性时会发生什么&#xff1f; 2、以下代码执行后&#xff0c;a.x 和 b.x 的结果分别为&#xff08;&#xff09; 3、在ECMAScript6 中,Promise的状态有&#xff08;&#xff09; 4、下面哪些方式在同一个窗口下能够检测一个js对象是…

解决:eclipse无法查看源代码

eclipse的jdk没有配置对应的src&#xff0c;需要手动去添加jdk的源代码附件。 步骤如下&#xff1a; 1、找到以下路径&#xff1a;windows(窗口)–>Preferences(首选项)–>Java–>Installed JRES(已安装的JRE)&#xff0c;出现如下图所示的图片后&#xff0c;选中点…

15 - 信号处理设计模式

---- 整理自狄泰软件唐佐林老师课程 查看所有文章链接&#xff1a;&#xff08;更新中&#xff09;Linux系统编程训练营 - 目录 文章目录 1. Linux应用程序安全性讨论1.1 问题1.2 不同场景1.2.1 场景一&#xff1a;不需要处理信号1.2.2 场景二&#xff1a;需要处理信号 2. 场景…

SQLmap使用指南(包含使用SQLmap获取shell)

文章标题 一&#xff1a;SQLmap基础知识二&#xff1a;SQLmap各大模块中的常用命令&#xff08;一&#xff09; 基础命令&#xff08;二&#xff09; target模块&#xff08;三&#xff09; Emuneration模块&#xff08;四&#xff09;其他命令 三&#xff1a;SQLmap应用示例&a…

数据结构_进阶(2):二叉树的OJ练习题

目录 1. 二叉树创建字符串。OJ链接 2. 二叉树的分层遍历1。OJ链接 3. 二叉树的分层遍历2。OJ链接 4. 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先 。OJ链接 5. 二叉树搜索树转换成排序双向链表。OJ链接 6. 根据一棵树的前序遍历与中序遍历构造二叉树。 OJ链接…

2023年NOC决赛-加码未来编程赛项决赛模拟题-Python模拟题--卷4

第一题、计算 1+2+3+⋯+(n−1)+n 的值,其中正整数 n 不大于 100。由于你没有高斯聪明,所以你不被允许使用等差数列求和公式直接求出答案。 输入格式 输入一个正整数 n。 输出格式 输出一个正整数,表示最后求和的答案。 输入输出样例 输入 #1 100 输出 #1 5050 第二…

手撕自定义类型:结构体,枚举,联合——【C语言】

在开始学习之前我们先来欣赏一下五岳之一华山的风景&#xff0c;来营造一个好心情&#xff0c;只有一个好心情我们才能更好的学习 目录 结构体 1 结构体的声明 1.1 结构的基础知识 1.2 结构的声明 1.3 特殊的声明 1.4 结构的自引用 1.5 结构体变量的定义和初始化 1.6 …

Go语言之重要数组类型切片(slice)make,append函数

切片是一个动态数组&#xff0c;因为数组的长度是固定的&#xff0c;所以操作起来很不方便&#xff0c;比如一个names数组&#xff0c;我想增加一个学生姓名都没有办法&#xff0c;十分不灵活。所以在开发中数组并不常用&#xff0c;切片类型才是大量使用的。 切片基本操作 切片…

Linux系统文件编程及文件读、写操作

Linux 系统编程Day01 文章目录 Linux 系统编程Day011.文件编程概述1.1 文件的打开及创建1.1.1 参数说明1.1.2 文件写入操作示例1.1.3 文件的权限 2.文件操作2.1 写入文件2.2 文件读取操作2.3 文件的光标移动操作 3.文件操作原理简述3.1文件描述符3.2 Linux文件操作流程 1.文件编…

【数据结构】二叉树的前中后序遍历(C语言)

文章目录 什么是二叉树树相关的概念树的表示形式特殊的二叉树如何创造出一棵二叉树二叉树的遍历先序遍历(前序遍历)中序遍历后序遍历 总结 什么是二叉树 [二叉树] 顾名思义就是有两个分支节点的树&#xff0c;不仅如此&#xff0c;除了叶子外的所有节点都具有两个分支节点&…

单个电源模块给多个负载使用,并且电源后还经过了磁珠-二级电源直流压降仿真

单个电源模块给多个负载使用,并且电源后还经过了磁珠-二级电源直流压降仿真 下面介绍单个电源模块给多个负载使用,并且电源后还经过了磁珠-二级电源直流压降仿真,常见于二级压降仿真,以下图为例

备战秋招 | 笔试强训5

目录 一、选择题 二、编程题 三、选择题题解 四、编程题题解 一、选择题 1、在上下文和头文件均正常情况下&#xff0c;以下程序的输出结果是&#xff08;&#xff09; int x 1; do {printf("%2d\n",x); }while(x--); A. 1 B. 无任何输出 C. 2 D. 陷入死循环 …

三种智能算法优化PID参数软件,MATLABAPP开发

今天的主题是&#xff1a;三种智能算法优化常见传递函数的PID参数&#xff0c;采用MATLAB APP Designer 开发。提供代码源程序&#xff0c;可以自行修改源代码&#xff08;不是封装软件&#xff09; 这个软件基本涵盖了所有的传递函数类型&#xff0c;传递函数的参数简单易改。…

【Java反射机制详解】—— 每天一点小知识

&#x1f4a7; J a v a 反射机制详解 \color{#FF1493}{Java反射机制详解} Java反射机制详解&#x1f4a7; &#x1f337; 仰望天空&#xff0c;妳我亦是行人.✨ &#x1f984; 个人主页——微风撞见云的博客&#x1f390; &#x1f433; 《数据结构与算法》专栏的文章…

pytest 参数化进阶

目录 前言&#xff1a; 语法 参数化误区 实践 简要回顾 前言&#xff1a; pytest是一个功能强大的Python测试框架&#xff0c;它提供了参数化功能&#xff0c;可以帮助简化测试用例的编写和管理。 语法 本文就赶紧聊一聊 pytest 的参数化是怎么玩的。 pytest.mark.par…

week27

这周是磨难的一周不知道NT装了多少次系统&#xff0c;删除了多少数据好消息是把BIOS和ubuntu安装地很熟练了&#xff0c;而且经过爱上了心仪的Ubuntu23.04&#xff0c;就是她了坏消息是一个学期做的笔记全都没了&#xff0c;以后不好回忆了&#xff0c;好消息是不用考试了&…

总结929

今日做了一篇阅读题&#xff0c;差点全军覆没&#xff0c;通过这篇阅读&#xff0c;主要说明了两大问题&#xff0c;一个是单词&#xff0c;背的还不够牢固&#xff0c;其二&#xff0c;语法功底还不够扎实。但说实话&#xff0c;在语法方面&#xff0c;还是下了一番功夫&#…

linux 内网批量快速传输大文件 nc

使用nc工具 传输内网宽带拉满先运行接收端 开始监听使用 ansible 拷贝脚本到其它接收端服务器批量运行接收端脚本查看nc是否运行运行发送端运行发送端脚本开始传输文件 传输内网宽带拉满 先运行接收端 开始监听 接收端脚本 re.sh #!/bin/bash #Revision: 1.0 #Author:…

动态规划(一) —— 从背包系列问题看DP

前言 动态规划可以算是算法初学者的噩梦哈哈&#xff0c;这段时间荔枝在持续学习Java后端的同时也没有忘记刷题嘿嘿嘿&#xff0c;总算把代码随想录上给出的有关动态规划的题目刷完了。接下来的几篇文章荔枝将会对于刷过的动态规划问题做出总结并给出相应的个人体会和理解。在本…

compose之沉浸式(侵入式)状态栏(隐藏状态栏)

沉浸式(侵入式)状态栏 效果图&#xff1a; 1、代码加入&#xff1a;WindowCompat.setDecorFitsSystemWindows(window, false) ComposeTestTheme {WindowCompat.setDecorFitsSystemWindows(window, false)Greeting("Android")} 2、沉浸式(侵入式)主题&#xff1a; …