在绘制颜色的色彩空间中查找其他两个颜色之间的算法

发布于 2024-11-09 17:46:38 字数 738 浏览 5 评论 0原文

当混合蓝色和黄色油漆时,结果是某种绿色。

我有两种 rgb 颜色:

蓝色 = (0, 0, 255)

和黄色 = (255, 255, 0)

查找 rgb 颜色(即两种颜色混合的结果)的算法是什么,因为它们在使用时会出现画?算法生成的颜色不必非常精确。对于上面的示例,它只需看起来像某种绿色即可。

提前致谢。

编辑:这个函数是用 Go 编写的,基于 LaC 的答案,对我有用。

func paintMix(c1, c2 image.RGBAColor) image.RGBAColor { 
    r := 255 - ((255 - c1.R) + (255 - c2.R))
    g := 255 - ((255 - c1.G) + (255 - c2.G))
    b := 255 - ((255 - c1.B) + (255 - c2.B))
    return image.RGBAColor{r, g, b, 255}
}

编辑 #2 虽然这成功地混合了青色和黄色,但蓝色和黄色之间的混合变成了黑色,这看起来不太正确。我仍在寻找可行的算法。

编辑 #3 Mark Ransom 的答案非常有效,使用了 HLS 色彩空间。谢谢,马克·兰登。

编辑 #4 似乎更好的颜色混合的前进方向是使用 Kubelka-Munk 方程

When mixing blue and yellow paint, the result is some sort of green.

I have two rgb colors:

blue = (0, 0, 255)

and yellow = (255, 255, 0)

What is the algorithm for finding the rgb color that is the result of mixing the two colors, as they would appear when using paint? The resulting colors from the algorithm does not have to be terribly exact. For the example above it would only have to look like some sort of green.

Thanks in advance.

Edit: This function, written in Go, worked for me, based on the answer from LaC.

func paintMix(c1, c2 image.RGBAColor) image.RGBAColor { 
    r := 255 - ((255 - c1.R) + (255 - c2.R))
    g := 255 - ((255 - c1.G) + (255 - c2.G))
    b := 255 - ((255 - c1.B) + (255 - c2.B))
    return image.RGBAColor{r, g, b, 255}
}

Edit #2 Allthought this manages to mix cyan and yellow, the mix between blue and yellow becomes black, which doesn't seem right. I'm still looking for a working algorithm.

Edit #3 The answer from Mark Ransom worked pretty well, using the HLS colorspace. Thanks, Mark Random.

Edit #4 It seems like the way forward for even better color mixing would be to use the Kubelka-Munk equation

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

白色秋天 2024-11-16 17:46:39

你想使用减色 CMY 颜色(青色、洋红色、黄色)(正如 LaC 所做的那样,但没有使用该术语)

来回转换很简单:(C,M,Y) = (-R,-G,-B ).
所以 CMY(0,0,0) 是白色,CMY(FF,FF,FF) 是黑色。

当您添加两种 CMY 颜色时,有不同的方法来计算新值。您可以为每个颜色值取平均值、最大值或介于两者之间的值。
例如。对于滤光片,您始终使用最大值。对于您正确想要使用的油漆,接近平均值的东西。

正如 LaC 指出的,绿色不是通过混合黄色和蓝色得到的,而是通过混合黄色和青色得到的。当按最大值(例如滤光片)混合时,黄色和蓝色实际上会产生黑色。这就是为什么,您可能想要使用更接近平均值的值来进行油漆混合。

你不想使用 CMYK,除非你想打印一些东西。黑色“K”颜色主要用于打印机以节省墨水,但不需要它来表示颜色。

You wanna use subtractive CMY-colors (Cyan, Magenta, Yellow) (as LaC is doing, whithout using the term)

The conversion back and forth is simple: (C,M,Y) = (-R,-G,-B).
So CMY(0,0,0) is white and CMY(FF,FF,FF) is black.

When you add two CMY colors, there are different ways to calculate the new values. You can take the average, max or something in between for each color value.
Eg. for light-filters you always use the max value. For paint you properly want to use, something closer to the average value.

As LaC points out, you don't get green from mixing yellow and blue, but from mixing yellow and cyan. Yellow and blue actually gives black, when mixing by max value (eg. light filters). This is why, you might want to use something closer to the average value for paint mixing.

You don't wanna use CMYK, unless you want to print something. The black "K" color is primarily used in printers to save ink, but it's not needed to represent colors.

扶醉桌前 2024-11-16 17:46:39

使用 Convert::Color 生成此类输出:

mauve        is 0xE0B0FF  sRGB=[224,176,255]  HSV=[276, 31,100] 
vermilion    is 0xE34234  sRGB=[227, 66, 52]  HSV=[  5, 77, 89] 
mix          is 0xE2799A  sRGB=[226,121,154]  HSV=[341, 46, 89] 

red          is 0xFF0000  sRGB=[255,  0,  0]  HSV=[  0,100,100] 
blue         is 0x0000FF  sRGB=[  0,  0,255]  HSV=[240,100,100] 
red+blue     is 0x800080  sRGB=[128,  0,128]  HSV=[300,100, 50] 

black        is 0xFFFFFF  sRGB=[255,255,255]  HSV=[  0,  0,100] 
white        is 0x000000  sRGB=[  0,  0,  0]  HSV=[  0,  0,  0] 
grey         is 0x808080  sRGB=[128,128,128]  HSV=[  0,  0, 50] 

dark red     is 0xFF8080  sRGB=[255,128,128]  HSV=[  0, 50,100] 
light red    is 0x800000  sRGB=[128,  0,  0]  HSV=[  0,100, 50] 

pink         is 0x800080  sRGB=[128,  0,128]  HSV=[300,100, 50] 
deep purple  is 0xBF80FF  sRGB=[191,128,255]  HSV=[270, 50,100] 

运行此类时代码:

#!/usr/bin/env perl
use strict;
use warnings;

use Convert::Color;

main();
exit;

sub rgb($$) {
    my($r, $g, $b) = @_;
    return new Convert::Color:: "rgb8:$r,$g,$b";
}

sub show($) {
    my ($name, $color) = @_;
    printf "%-12s is 0x%6s", $name,  uc $color->hex;
    printf "  sRGB=[%3d,%3d,%3d] ",     $color->rgb8;

    my ($h,$s,$v) = $color->as_hsv->hsv;
    for ($s, $v) { $_ *= 100 }
    printf " HSV=[%3.0f,%3.0f,%3.0f] ",  $h, $s, $v;
    print "\n";
}

sub main {
    my $vermilion = rgb 227,  66,  52;
    my $mauve     = rgb 224, 176, 255;
    show mauve      => $mauve;
    show vermilion  => $vermilion;

    my $mix = alpha_blend $mauve $vermilion;
    show mix => $mix;
    print "\n";

    my $red   = rgb 255,   0,   0;
    my $blue  = rgb   0,   0, 255;
    show red  => $red;
    show blue => $blue;

    $mix = alpha_blend $red $blue;
    show "red+blue" => $mix;
    print "\n";

    my $black = rgb 255, 255, 255;
    my $white = rgb 0,     0,   0;
    show black => $black;
    show white => $white;

    my $grey  = alpha_blend $black $white;
    show grey  => $grey;
    print "\n";

    my $dark_red  = alpha_blend $red $black;
    my $light_red = alpha_blend $red $white;

    show "dark red"  => $dark_red;
    show "light red" => $light_red;
    print "\n";

    my $magenta = rgb 255, 0, 255;
    my $violet  = rgb 127, 0, 255;

    my $pink        = alpha_blend $magenta $white;
    my $deep_purple = alpha_blend $violet  $black;

    show pink          => $pink;
    show "deep purple" => $deep_purple;;
}

Use Convert::Color to produce this sort of output:

mauve        is 0xE0B0FF  sRGB=[224,176,255]  HSV=[276, 31,100] 
vermilion    is 0xE34234  sRGB=[227, 66, 52]  HSV=[  5, 77, 89] 
mix          is 0xE2799A  sRGB=[226,121,154]  HSV=[341, 46, 89] 

red          is 0xFF0000  sRGB=[255,  0,  0]  HSV=[  0,100,100] 
blue         is 0x0000FF  sRGB=[  0,  0,255]  HSV=[240,100,100] 
red+blue     is 0x800080  sRGB=[128,  0,128]  HSV=[300,100, 50] 

black        is 0xFFFFFF  sRGB=[255,255,255]  HSV=[  0,  0,100] 
white        is 0x000000  sRGB=[  0,  0,  0]  HSV=[  0,  0,  0] 
grey         is 0x808080  sRGB=[128,128,128]  HSV=[  0,  0, 50] 

dark red     is 0xFF8080  sRGB=[255,128,128]  HSV=[  0, 50,100] 
light red    is 0x800000  sRGB=[128,  0,  0]  HSV=[  0,100, 50] 

pink         is 0x800080  sRGB=[128,  0,128]  HSV=[300,100, 50] 
deep purple  is 0xBF80FF  sRGB=[191,128,255]  HSV=[270, 50,100] 

When running this sort of code:

#!/usr/bin/env perl
use strict;
use warnings;

use Convert::Color;

main();
exit;

sub rgb($$) {
    my($r, $g, $b) = @_;
    return new Convert::Color:: "rgb8:$r,$g,$b";
}

sub show($) {
    my ($name, $color) = @_;
    printf "%-12s is 0x%6s", $name,  uc $color->hex;
    printf "  sRGB=[%3d,%3d,%3d] ",     $color->rgb8;

    my ($h,$s,$v) = $color->as_hsv->hsv;
    for ($s, $v) { $_ *= 100 }
    printf " HSV=[%3.0f,%3.0f,%3.0f] ",  $h, $s, $v;
    print "\n";
}

sub main {
    my $vermilion = rgb 227,  66,  52;
    my $mauve     = rgb 224, 176, 255;
    show mauve      => $mauve;
    show vermilion  => $vermilion;

    my $mix = alpha_blend $mauve $vermilion;
    show mix => $mix;
    print "\n";

    my $red   = rgb 255,   0,   0;
    my $blue  = rgb   0,   0, 255;
    show red  => $red;
    show blue => $blue;

    $mix = alpha_blend $red $blue;
    show "red+blue" => $mix;
    print "\n";

    my $black = rgb 255, 255, 255;
    my $white = rgb 0,     0,   0;
    show black => $black;
    show white => $white;

    my $grey  = alpha_blend $black $white;
    show grey  => $grey;
    print "\n";

    my $dark_red  = alpha_blend $red $black;
    my $light_red = alpha_blend $red $white;

    show "dark red"  => $dark_red;
    show "light red" => $light_red;
    print "\n";

    my $magenta = rgb 255, 0, 255;
    my $violet  = rgb 127, 0, 255;

    my $pink        = alpha_blend $magenta $white;
    my $deep_purple = alpha_blend $violet  $black;

    show pink          => $pink;
    show "deep purple" => $deep_purple;;
}
十年九夏 2024-11-16 17:46:38

油漆通过吸收起作用。您从白光 (255,255,255) 开始,并将其乘以吸收系数。

蓝色油漆吸收所有照射到它的红光和绿光。

黄色油漆吸收所有照射到它的蓝光。

在完美的世界中,这意味着将黄色和蓝色油漆结合起来会产生黑色油漆,或者最多是浑浊的灰色。实际上,“蓝色”涂料偏向绿色,因此您会得到浑浊的绿色。我从未见过混合黄色和蓝色产生令人满意的绿色的例子。维基百科探讨了此过程的一些复杂性:http://en.wikipedia.org/wiki /Primary_color#Subtractive_primaries

我认为您真正要问的是如何沿着色轮插入颜色。这应该与油漆中的颜色是吸收性的还是 RGB 显示器中的发射性无关。

编辑:通过在 HSL 色彩空间中工作,您可以获得所需的结果。下面是一些用 Python 实现该算法的代码;平均色调很棘手,并且基于我之前的平均角度的答案。

from colorsys import rgb_to_hls,hls_to_rgb
from math import sin,cos,atan2,pi

def average_colors(rgb1, rgb2):
    h1, l1, s1 = rgb_to_hls(rgb1[0]/255., rgb1[1]/255., rgb1[2]/255.)
    h2, l2, s2 = rgb_to_hls(rgb2[0]/255., rgb2[1]/255., rgb2[2]/255.)
    s = 0.5 * (s1 + s2)
    l = 0.5 * (l1 + l2)
    x = cos(2*pi*h1) + cos(2*pi*h2)
    y = sin(2*pi*h1) + sin(2*pi*h2)
    if x != 0.0 or y != 0.0:
        h = atan2(y, x) / (2*pi)
    else:
        h = 0.0
        s = 0.0
    r, g, b = hls_to_rgb(h, l, s)
    return (int(r*255.), int(g*255.), int(b*255.))

>>> average_colors((255,255,0),(0,0,255))
(0, 255, 111)
>>> average_colors((255,255,0),(0,255,255))
(0, 255, 0)

请注意,由于上述原因,此答案模拟油漆混合。相反,它提供了一种直观的颜色混合,这种混合并不基于任何物理世界的现实。

Paint works by absorption. You start with white light (255,255,255) and multiply it by the absorption factors.

Blue paint absorbs all red and green light that hits it.

Yellow paint absorbs all blue light that hits it.

In a perfect world, that means that combining yellow and blue paint would result in black paint, or at best a muddy gray. In practice the "blue" paint has a bias towards green, so you get a muddy green. I've never seen an example of mixing yellow and blue that produces a satisfactory green. Wikipedia goes into some of the complexities of this process: http://en.wikipedia.org/wiki/Primary_color#Subtractive_primaries

I think what you are really asking is how to interpolate colors along a color wheel. This should be independent of whether the colors are absorptive as in paint, or emissive as in RGB displays.

Edit: By working in the HSL color space you can get the kind of results you're looking for. Here's some code in Python that implements the algorithm; averaging hues is tricky, and is based on a previous answer of mine for averaging angles.

from colorsys import rgb_to_hls,hls_to_rgb
from math import sin,cos,atan2,pi

def average_colors(rgb1, rgb2):
    h1, l1, s1 = rgb_to_hls(rgb1[0]/255., rgb1[1]/255., rgb1[2]/255.)
    h2, l2, s2 = rgb_to_hls(rgb2[0]/255., rgb2[1]/255., rgb2[2]/255.)
    s = 0.5 * (s1 + s2)
    l = 0.5 * (l1 + l2)
    x = cos(2*pi*h1) + cos(2*pi*h2)
    y = sin(2*pi*h1) + sin(2*pi*h2)
    if x != 0.0 or y != 0.0:
        h = atan2(y, x) / (2*pi)
    else:
        h = 0.0
        s = 0.0
    r, g, b = hls_to_rgb(h, l, s)
    return (int(r*255.), int(g*255.), int(b*255.))

>>> average_colors((255,255,0),(0,0,255))
(0, 255, 111)
>>> average_colors((255,255,0),(0,255,255))
(0, 255, 0)

Note that this answer does not emulate paint mixing, for the reasons stated above. Rather it gives an intuitive mixing of colors that is not grounded in any physical world reality.

乖乖公主 2024-11-16 17:46:38

实际上,通过(减法)混合黄色和青色可以得到绿色。黄色是红色 + 绿色 (255, 255, 0),青色是绿色 + 蓝色 (0, 255, 255)。现在制作它们的相反颜色:蓝色 (0, 0, 255) 和红色 (255, 0, 0)。将它们相加混合即可得到紫色 (255, 0, 255)。使其相反,你会得到绿色 (0, 255, 0)。

换句话说,您可以获得与两种颜色的相反颜色的加色混合相反的减色混合。

Actually, you get green from mixing (subtractively) yellow and cyan. Yellow is red + green (255, 255, 0), cyan is green + blue (0, 255, 255). Now make their opposite colors: blue (0, 0, 255) and red (255, 0, 0). Mix them additively and you get purple (255, 0, 255). Make its opposite and you get green (0, 255, 0).

In other words, you can get a subtractive mix as the opposite of the additive mix of the opposites of your two colors.

谜兔 2024-11-16 17:46:38

RBG 颜色空间基于光发射,染料和颜料的颜色空间基于光吸收

例如,植物看起来不是绿色的,因为它们发出绿光,而是因为它们吸收了所有其他颜色的光,只反射绿色。

基于此,您应该能够通过从 RGB 到吸收色彩空间的转换、进行“混合”然后再返回来获得非常接近的结果。

The colour space RBG is based on light emission, the colour space of dyes and pigments is based on light absorption.

e.g. Plant's don't look green because they emit green light, but because they absorb all the other colours of light, reflecting only green.

Based on this, you should be able to get pretty close by doing a conversion from RGB to an absorptive colour space, doing the "mix" and then back again.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文