在javascript中“自然地”混合两种颜色

IT技术 javascript math colors color-scheme
2021-03-13 12:59:44

问题:我想在javascript中混合两种颜色,并获得结果颜色。SO上有很多类似的问题,但是我没有发现任何实际工作正常的问题。我知道混合两种不同颜色的颜料(颜料)和灯光会产生非常不同的结果(http://en.wikipedia.org/wiki/Color_mixing)。

以下是我已经看到并尝试实施的问题和建议的解决方案:

1: 混合两个RGB颜色向量得到结果
所以,在RGB中混合颜色。我实现了它,在某些情况下它起作用,在某些情况下它不起作用。

工作示例:redyellow->混合orange伟大的!
http://jsbin.com/afoim/1/edit

不工作的例子:blueyellow->混合gray不太好!:) http://jsbin.com/afomim/5/edit
我知道,在RGB混合blue使用yellow不会让green的,我明白为什么。

我们不会在这里找到答案,让我们继续前进。

2: 像油漆一样将颜色(颜色)加在一起(蓝色+黄色=绿色等)

让我们尝试使用本讨论中建议的 CMYK 值。混合cyanyellow给出green
http://jsbin.com/igaveg/1/edit
但混合blue使用yellow的结果black
http://jsbin.com/igaveg/2/edit -> 不工作!

3: 如何用C#“自然地”混合颜色?
一个非常相似的问题。最受好评的答案建议将颜色转换为 LAB,这个解决方案似乎很有希望。
所以我将我的颜色转换为 LAB。转换算法是正确的,我测试过了!

http://jsbin.com/oxefox/1/edit

现在我在 LAB 中有两种颜色,但是如何混合它们呢?

注:我知道,可能我不会找到一个算法中混合了blueyellow和将会给完美的green,但我希望我能够生成类似于绿色的东西:)

6个回答

我花了 3-4 天的时间来回答这个问题。这是一个非常复杂的问题。

如果您想“自然地”混合两种颜色,您可以这样做:

  1. CMYK 混合:这不是完美的解决方案,但如果您现在需要一个解决方案,并且您不想花费数月时间学习该主题、实验和编码,您可以查看:https : //github.com/ AndreasSoiron/Color_mixer

  2. 实施 Kubelka-Munk 理论。我花了很多时间阅读它,并试图理解它。如果您想要专业的解决方案,这应该是可行的方法,但对于您想要混合的每种颜色,它需要 6 个参数(如反射率、吸收率等)。有 R、G、B 是不够的。实施该理论并不难,但获取有关每种颜色所需的参数似乎是缺失的部分。如果你知道怎么做,请告诉我:)

  3. 实验性:你可以做一些 ipad 应用程序的开发者所做的事情:Paper所做的。他们手动选择了 100 对流行的颜色,并用眼球测试了它们应该如何混合。在此处了解更多信息

我个人将暂时实施 CMYK 混合,也许以后,如果我有时间,我会尝试制作像 Fiftythree 那样的东西。等着瞧 :)

感谢您分享您的结果!
2021-05-08 12:59:44

RYB颜色模型可能是混色计算一个合适的选择。根据维基百科,它主要用于艺术和设计教育,尤其是绘画。

要混合 2 种颜色,将两种颜色从 RGB 转换为 RYB,通过添加每个颜色分量来混合颜色,然后将生成的颜色从 RYB 转换回 RGB。

我已经使用Online Color Mixing Tool尝试过这个,结果是

  • 0000FF(蓝色)与#FFFF00(黄色)混合得到#008000(深绿色),

  • FF0000(红色)与#FFFF00(黄色)混合得到#FFA000(橙色)。

所以这个方法产生的结果正是你所期望的。

不幸的是,我无法找到带有“即用型”公式的参考,以将 RGB 转换为 RYB,然后再转换回 RGB。

论文 Paint Inspired Color Mixing and Compositing for Visualization - Gossett and Chen 在“2 ACHIEVING INTUITIVE COLOR MIXING”一节中描述了 RYB 颜色模型的一般思想。

根据那篇论文,从 RYB 到 RGB 的转换是通过三线性插值完成的

难点是RGB到RYB的转换,因为它需要三线性插值的反演。有关 更多信息,请参阅RGB 和 RYB 颜色空间之间的转换

即使这个答案没有提供完整的计算公式,我希望它给出一些如何进行的想法。

@TamasPap:我只使用Online Color Mixing Tool做到了这一点据我了解:RYB 中的蓝色是 (1.0, 0.0, 0.0),RYB 中的黄色是 (0.0, 1.0, 0.0)。如果你在 RYB 中添加它,你会得到 (1.0, 1.0, 0.0)。现在您必须将此值转换回 RGB,这应该会显示一些深绿色。- 在我看来,“在线颜色混合工具”使用的转换与 Gossett 和 Chen 的论文中的值略有不同。该工具使用 JavaScript,因此可以对其进行检查。
2021-05-01 12:59:44
我仍处于学习和试验阶段,但我将返回结果。:)
2021-05-02 12:59:44
谢谢你的详细回答。这是非常有帮助的。我尝试了很多东西,并在 HSL 和 LAB 空间中取得了一些成功,但我仍在寻找更好的解决方案。明天我将检查 RYB 模型,并将返回我的结果。
2021-05-03 12:59:44
我现在可以将 ryb 转换为 rgb,并且我正在将 rgb 转换为 ryb。在你的第一个例子中:#0000FF (blue) mixed with #FFFF00 (yellow) gives #008000 (dark green),你能解释一下 00800 是如何通过添加 0000FF 和 FFFF00 产生的。因为如果我简单地添加组件,我会得到 FFFFFF,如果我计算它们的平均值,我会得到 7A7A7A。那么,在 RYB 中拥有 2 种颜色后,我应该如何“混合”它们?我希望我们能弄清楚:)
2021-05-16 12:59:44

在尝试将 2 种 RGB 颜色混合在一起时,我实际上遇到了同样的问题。这两个功能对我有用:

//colorChannelA and colorChannelB are ints ranging from 0 to 255
function colorChannelMixer(colorChannelA, colorChannelB, amountToMix){
    var channelA = colorChannelA*amountToMix;
    var channelB = colorChannelB*(1-amountToMix);
    return parseInt(channelA+channelB);
}
//rgbA and rgbB are arrays, amountToMix ranges from 0.0 to 1.0
//example (red): rgbA = [255,0,0]
function colorMixer(rgbA, rgbB, amountToMix){
    var r = colorChannelMixer(rgbA[0],rgbB[0],amountToMix);
    var g = colorChannelMixer(rgbA[1],rgbB[1],amountToMix);
    var b = colorChannelMixer(rgbA[2],rgbB[2],amountToMix);
    return "rgb("+r+","+g+","+b+")";
}

要将红色 ( [255,0,0] ) 与蓝色 ( [0,0,255] ) 均匀混合,您可以调用

colorMixer([255,0,0], [0,0,255], 0.5);//returns "rgb(127,0,127)" (purple)

这可能会有所帮助,但您必须先将每个颜色值转换为数组。如果您使用 Fabric.js 来处理画布元素,这将变得非常简单。打电话就行

var rgbA = new fabric.Color(yourColor);
var rgbB = new fabric.Color(yourSecondColor);

然后打电话

colorMixer(rgbA.getSource(),rgbB.getSource(),0.5);

希望这些功能有所帮助。

这个真的很有帮助。谢谢!
2021-04-26 12:59:44

使用 CIELAB 颜色,您在 LAB 颜色空间中的两种颜色中的每一种都有三个坐标。(顺便说一句,在这方面做得很好)。对您来说效果最好且最容易实现的方法是找到连接 LAB 空间中两点的假想线段的三维中点。您可以通过对两种颜色的每个分量求平均值来轻松完成此操作:平均值L、平均值a和平均值b然后通过反转转换将此颜色转换回 RGB 空间(确保您的照明空间在两种方式下都保持相同)。

您的新颜色可能在 RGB 颜色空间之外。在这种情况下,您可以决定剪裁到最近的可见颜色。(蓝调特别容易受到这种影响)。

现在就试一试,结果会回来的!谢谢!
2021-04-23 12:59:44
Jsbin 关闭了,所以我在 codepen 上实现了它:codepen.io/anon/pen/pscJr,但没有给出预期的结果:( 还有其他想法吗?:)
2021-05-07 12:59:44

现在您拥有 LAB(或 L*a*b*)格式的两种颜色,您可以将它们平均在一起。

L(result) = L(first color) + L(second color) / 2
A(result) = A(first color) + A(second color) / 2
B(result) = B(first color) + B(second color) / 2

你已经知道了,对吧?因为这是您使用原始 RGB 颜色对它们进行平均的操作。

正在努力实现!谢谢!
2021-04-22 12:59:44
这是一个旧线程,但我从一个不同的 SO 问题中找到了它。一个问题:不是 LAB 和加色空间,而油漆(和 CMYK)是减色空间吗?我不希望黄色 + 蓝色在任何加色模型中产生绿色。
2021-05-06 12:59:44