首页 文章

使用“色调”混合模式混合两种不透明的颜色

提问于
浏览
16

我想实现W3C compositing and blending spec中描述的颜色混合 . (对于解决我的问题,我真的很重要 . )


回想起来:在实现这个问题的答案期间,我意识到这可能会成为一个非常好的独立包 . 如果您有兴趣,可以grab it from npm .


到目前为止,它的效果非常好,但我想进一步采用这些算法,并增加对alpha通道的支持 . 感谢SVG compositing spec提供了不太难的所有必需的公式 .

但是现在我坚持实现W3C规范描述为non-separable的混合模式(从Photoshop中已知):色调,饱和度,颜色和亮度 .

遗憾的是,这些算法在SVG规范中不可用,我不知道如何使用它们 . 我想有the formulas provided by the W3C的修改版本用于处理我缺少的alpha通道 .

为了使我的问题更具视觉效果,我将展示Photoshop为色调混合两种颜色的方式:

Photoshop hue blending example of two opaque colors

这也是我能够使用上述W3C规范中的非alpha算法重现的 .

我无法重现的是当我在源和背景颜色上放置较低的alpha时Photoshop给我的结果:

Photoshop hue blending example of two colors with 60% opacity each

有谁知道如何以编程方式实现该结果?

更新1:更改插图(添加HSVA和RGBA代码)以阐明使用的颜色 .

更新2:要检查可能的解决方案,我将附加另外两个Photoshop生成的混合示例:

Photoshop hue blending example of two colors with different opacity combinations

Photoshop hue blending example of two colors with different opacity combinations

更新3:事实证明,除了没有关于颜色混合的线索之外,我也是messed up my Photoshop settings,使任务更难以解决我的问题 . 修复了可能的未来路人的示例图像 .

2 回答

  • 11

    您在第二个图像上使用的Hue alpha不代表alpha颜色组合公式,但它反映了Porter Duff alpha composition这里定义的9.1.4. Source Over并使用以下公式:

    Source Over Formula

    如果你想实现那种不适合Hue混合的混合,你可以在javascript中使用以下公式:

    PDso = { // Ported Duff Source Over
        r: ((S.r * S.a) + (B.r * B.a) * (1 - S.a)) / aR,
        g: ((S.g * S.a) + (B.g * B.a) * (1 - S.a)) / aR,
        b: ((S.b * S.a) + (B.b * B.a) * (1 - S.a)) / aR,
    };
    
    // where
    // S : the source rgb
    // B : the backdrop rgb
    // aR : the union alpha (as + ab * (1 - as))
    

    Hue Blending Mode with Alpha Channel

    以下是使用我在Photoshop中创建的Alpha颜色合成公式的背景上的确切色调混合源的屏幕截图:

    Photoshop Hue Blend Mode

    带有绿色突出显示字母的中间正方形是正确的混合表示 . 下面是CSS Hue混合与背景颜色中的源颜色混合,使用新的CSS mix-blend-mode (运行代码片段):

    .blends div {
        width:140px;
        height:140px;
    }
    
    .source {
        mix-blend-mode: hue;
    }
    
    .backdrop.alpha {
        background-color: rgba(141, 214, 214, .6);
        isolation: isolate;
    }
    
    .source.alpha {
        background-color: rgba(255, 213, 0, .6);
    }
    
    <div id="main">
     
     <div class="blends alpha">
      <div class="backdrop alpha">
       <div class="source alpha"></div>
      </div>
     </div>
    
    </div>
    

    如果您使用颜色选择器,您将获得几乎相同的值( 211, 214, 140 <> 210, 214, 140 ) . 这可能是由于略有不同的算法或不同的舍入方法,但它并不重要 . 事实是,当将alpha颜色与色调混合模式混合时,这是正确的结果 .

    因此,现在我们需要公式为应用于我们的色调混合模式的alpha颜色合成具有适当的颜色值 . 我搜索了一下,我发现了Adobe Document management - Portable document format - Part 1: PDF 1.7中的所有内容 . 我们可以在混合模式后的页面 328 找到颜色组成公式:

    11.3.6 Alpha的解释颜色合成公式

    这是我设法通过alpha通道为Hue混合模式获得正确且更接近Photoshop匹配的公式 . 我在javascript中这样写了:

    var
    
    Union = function(ab, as) {
        return as + ab * (1 - as);
    },
    
    colourCompositingFormula = function(as, ab, ar, Cs, Cb, Bbs) {
        return (1 - (as / ar)) * Cb + (as / ar) * Math.floor((1 - ab) * Cs + ab * Bbs);
    },
    
    aR = Union(B.a, S.a), //αr = Union(αb, αs) // Adobe PDF Format Part 1 - page 331
    
    Ca = {
        // Adobe PDF Format Part 1 - page 328
        r: colourCompositingFormula(S.a, B.a, aR, S.r, B.r, C.r),
        g: colourCompositingFormula(S.a, B.a, aR, S.g, B.g, C.g),
        b: colourCompositingFormula(S.a, B.a, aR, S.b, B.b, C.b)
    }
    
    // where
    // C : the hue blend mode result rgb
    // S : the source rgb
    // B : the backdrop rgb
    // aR : the union alpha (as + ab * (1 - as))
    // Ca : the final result
    
    body {
      padding:0;
      margin:0;
    }
    
    iframe {
      width: 100%;
      height: 200px;
      border:0;
      padding:0;
      margin:0;
    }
    
    <iframe src="http://zikro.gr/dbg/html/blending-modes/"></iframe>
    

    我的测试示例可以在here找到 . 在 2.5 With Alpha (Hue Blending Algorithm Computed) ,你可以看到最终的色调混合模式结果与alpha . 它的值与Photoshop结果略有不同,但我在Fireworks中获得了完全相同的结果( 202, 205, 118 ),色调混合了源和背景颜色:

    Fireworks same result

    所有应用程序都有自己略有不同的算法,也许我使用的公式相当陈旧,也许有最新版本 .

  • 2

    从这里开始

    色调混合使用源颜色的色调以及背景颜色的饱和度和亮度创建颜色 .

    我可以想出一些公式,但它们可能是垃圾,尽管它们完全重现了发布的原始数字:

    h :hSource deltaH (1 - aSrouce) aBackdrop * 0.41666666 = 50; 63

    s :sBackdrop * 0.9 deltaS (1 - aBackdrop) aSource * 0.20833333 = 45; 47.5

    l :lBackdrop * 0.957142857 deltaL (1 - aBackdrop) aSource * 0.77 = 67; 63.3

    a: 1 - (1 - aSource)^2 始终匹配

相关问题