【问题标题】:Mix two non-opaque colors with "hue" blend mode使用“色调”混合模式混合两种不透明的颜色
【发布时间】:2017-04-09 08:59:13
【问题描述】:

我想实现W3C compositing and blending spec 中描述的颜色混合。 (我在 JavaScript 中执行此操作,但该语言对于解决我的问题并不重要。)


回想起来:在执行这个问题的答案时,我意识到这可能会成为一个非常好的独立包。有兴趣的可以grab it from npm


到目前为止效果还不错,但我想将这些算法更进一步,并添加对 Alpha 通道的支持。感谢SVG compositing spec 提供了所有需要的公式,而且并不难。

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

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

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

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

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

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

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

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

更新 3: 所以事实证明,除了对颜色混合一无所知之外,我还 messed up my Photoshop settings,这使得解决我的问题的任务变得更加困难。为可能的未来路人修复了示例图像。

【问题讨论】:

  • 我在 1997 年花了很长时间对所有 Photoshop 混合模式进行逆向工程,包括 alpha 的效果。不幸的是,这都是我多年未工作过的公司的财产。
  • Photoshop 的混合模式使用与实际指定的 HSL 或 HSV 不同的颜色空间(尽管名称相同)。这些操作使用色域映射并且通常是不可逆的。这方面的详细信息看起来很少(专有),但您可以在此处阅读更多信息:en.wikipedia.org/wiki/…
  • @SpecialSauce 是的,已经读过,不过感谢您指出。但是,仍然可以使用“常规”色彩空间来模仿 Photoshop 的行为(上面的 Mark Ransom 的评论也暗示了这一点)。
  • 不可以举几个例子,从结果中猜出方程式吗?数学上我假设我们有一个函数,它接受 8 个参数(4 个源和 4 个背景)并返回 4 个变量,对吗?
  • @MarkRansom 哇,看来我对我的图像太粗心了......我会修复那个。当然,您可以回答这个问题,但我不确定 Christos Lytras 的回答还没有说它会包含什么。不过我会附上另一个例子。

标签: algorithm colors blending


【解决方案1】:

第二张图像中的色调 alpha 代表 alpha 颜色合成公式,而是反映了 Porter Duff alpha composition Source Over 此处定义的 @987654322 @ 它使用以下公式:

如果你想实现那种混合,这不是正确的色调混合,你可以在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 通道的色调混合模式

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

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

.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 &lt;&gt; 210, 214, 140)。这可能是由于算法略有不同或舍入方法不同,但这并不重要。事实上,这是将 alpha 颜色与色调混合模式混合时的正确结果。

所以,现在我们需要公式来为我们的色调混合模式应用 alpha 颜色组合的正确颜色值。我搜索了一下,发现了 Adob​​e Document management - Portable document format - Part 1: PDF 1.7 中的所有内容。我们可以在Blend Modes之后的页面328找到色彩合成公式

11.3.6 Alpha 的解释

颜色合成公式

这是我设法为带有 Alpha 通道的色调混合模式获得正确且更接近 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;
}
&lt;iframe src="https://zikro.gr/dbg/html/blending-modes/"&gt;&lt;/iframe&gt;

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

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

【讨论】:

  • 哇。我对这个答案所付出的巨大努力印象深刻。我用不同的颜色和不透明度测试了你的算法,你的结果的准确性在任何地方都大致相同。我必须承认,与 Photoshop 的偏差(正如您解释的 CSS 也创建的那样,我在发布我的问题之前也已经检查过)有点烦人。但是,在赏金的宽限期内还有几个小时,如果没有更准确的答案,您肯定会赢得。
  • @Loilo 我知道一些关于颜色的事情。我曾经在一些 C++ 应用程序上工作过,过去管理和混合颜色值。事实上,我真的很喜欢这里的 Q/A!我已经很长时间把所有这些颜色的东西弄乱了。顺便说一句,我看到你对赏金的运作方式知之甚少。如果宽限期到期并且没有接受的答案,则 >= 3 upvotes 的答案将获得一半的赏金。如果没有 >= 3 票的答案,那么所有的赏金都会丢失!请在此处阅读stackoverflow.com/help/bounty。如果这个 A 是你要找的,那么请接受它。
  • 是的,我知道那些赏金的事情。我只看了一眼赏金常见问题解答,这就是为什么我没有得到 100% 正确(关于如果没有给出答案的赏金退款)。经过一番思考,缺乏退款当然是完全有道理的。关于你的答案 - 我只是等待一个可能更准确的算法,但由于赏金已经在宽限期内,我想直接接受你的答案是公平的。
  • @Loilo 谢谢。我会检查一个更准确的公式,我印象深刻的是,Adobe Fireworks 生成的值与 Photoshop 略有不同(甚至是 +-1 R)!你想要我的 Hue blendingColor Hsl/Rgb 的 javascript 文件吗?当然,您可以从我的源链接中获取它们,但如果您愿意,我什至可以使用链接或完整代码更新答案。
  • 我已经检查了源代码并得到了我需要的东西,谢谢。 (我希望通过进一步阅读它和 Adob​​e 规范,我可以推导出 saturationluminosity 的类似算法。)既然你提到了 Fireworks:我只是在 Adobe Illustrator 瞧——结果完全反映了您的算法结果(rgba(202, 205, 119, 0.84),我猜是舍入±1)。我不确定这是否实际上是 Photoshop 中的算法差异(这两个应用程序对我来说都是 CS6 版本)或者是否有任何其他因素在起作用。
【解决方案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 始终匹配

【讨论】:

  • 我很感激你的努力,但你的公式真的只解决了一个特殊情况,对一般问题没有任何用处。但无论如何,将另一个 Photoshop 生成的混合示例添加到问题中以检查可能的结果是一个好主意。此外,您的公式至少有一个错误,因为色相和亮度增量的计算有点扭曲(deltaH = hBackdrop - hSource 但 deltaL = lSource - lBackdrop)。
  • 这与增量在逻辑上是一致的。色相以光源为基础,而亮度和饱和度以背景为基础,因此它是相反的。
猜你喜欢
  • 2017-09-23
  • 2011-04-09
  • 2012-05-10
  • 2012-10-20
  • 1970-01-01
  • 1970-01-01
  • 2020-12-25
  • 2021-02-18
  • 2012-06-02
相关资源
最近更新 更多