algorithm - 使用 "hue"混合模式混合两种非不透明颜色

标签 algorithm colors blending

我想按照 W3C compositing and blending spec 中的描述实现颜色混合. (我正在用 JavaScript 执行此操作,但语言对于解决我的问题应该无关紧要。)


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


到目前为止效果还不错,但我想更进一步地使用这些算法并添加对 alpha channel 的支持。感谢SVG compositing spec提供并不太难的所有需要​​的公式。

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

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

为了让我的问题更直观一些,我将展示 Photoshop 为 hue 混合两种颜色提供的功能:

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 ,使解决我的问题的任务更加困难。修复了 future 可能的路人的示例图像。

最佳答案

第二张图片中的 Hue alpha 代表 alpha 颜色合成公式,但它反射(reflect)了 Porter Duff alpha composition Source Over 定义为此处 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 rgba
// B : the backdrop rgba
// aR : the union alpha (as + ab * (1 - as))

带 Alpha channel 的色调混合模式

这是使用我在 Photoshop 中创建的 alpha 颜色合成公式在背景上精确混合源的屏幕截图:

Photoshop Hue Blend Mode

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

.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 颜色合成提供正确的颜色值。我搜索了一下,在 Adob​​e Document management - Portable document format - Part 1: PDF 1.7 中找到了所有内容.我们可以在 Blend Modes 之后的 328 页面找到颜色合成公式:

11.3.6 Interpretation of Alpha

The colour compositing formula

Colour Compositing Formula

这是我设法为带 alpha channel 的色相混合模式获得正确且更接近 Photoshop 匹配的公式。我在 javascript 中是这样写的:

function Union(ab, as) {
    return as + ab * (1 - as);
}

function colourCompositingFormula(as, ab, ar, Cs, Cb, Bbs) {
    return (1 - (as / ar)) * Cb + (as / ar) * Math.floor((1 - ab) * Cs + ab * Bbs);
}

var aR = Union(B.a, S.a); // αr = Union(αb, αs) // Adobe PDF Format Part 1 - page 331

var 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 rgba
// B : the backdrop rgba
// 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="https://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

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

关于algorithm - 使用 "hue"混合模式混合两种非不透明颜色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40796852/

相关文章:

java - 以这种方式找到排列的复杂性是什么?

安卓进度条 : how to set secondary color programmatically

c++ - cv::detail::MultiBandBlender 照片末尾出现奇怪的白色条纹

processing - P5.js : manually calculate additive blendmode with pixels[]

python - 棕褐色过滤器反转

c++ - 如果有两个 "greatest"索引,我如何找到 vector 中最大值的索引,默认为更大的索引?

c - 合并排序错误: Segmentation Fault

ios - 核心剧情: grid lines background color

css - 在 CSS 中更改颜色会更改布局尺寸

c - 在 OpenGL 中与黑暗背景上的明亮图形混合不好(没有吸引力)