RGB值加法颜色混合algorithm
我正在寻找一种algorithm来为RGB值进行加色混合。
是一样简单的RGB值加在一起,最多256?
(r1, g1, b1) + (r2, g2, b2) = (min(r1+r2, 256), min(g1+g2, 256), min(b1+b2, 256))
这取决于你想要什么,它可以帮助看看结果是不同的方法。
如果你想
红+黑=红 红+绿=黄 红+绿+蓝=白 红+白=白 黑+白=白
然后添加一个钳位工作(例如min(r1 + r2, 255)
)这更像您所提到的光照模型。
如果你想
红+黑=深红 红+绿=深黄 红+绿+蓝=深灰 红+白=粉红 黑+白=灰
那么你需要平均值(例如(r1 + r2) / 2
)这对于减轻/加深颜色和创build渐变效果更好。
要使用Alpha通道进行混合,可以使用以下公式:
r = new Color(); rA = 1 - (1 - fg.A) * (1 - bg.A); if (rA < 1.0e-6) return r; // Fully transparent -- R,G,B not important rR = fg.R * fg.A / rA + bg.R * bg.A * (1 - fg.A) / rA; rG = fg.G * fg.A / rA + bg.G * bg.A * (1 - fg.A) / rA; rB = fg.B * fg.A / rA + bg.B * bg.A * (1 - fg.A) / rA;
fg
是油漆的颜色。 bg
是背景。 r
是最终的颜色。 1.0e-6
只是一个非常小的数字,以弥补舍入误差。
注意:这里使用的所有variables都在[0.0,1.0]的范围内。 如果要使用范围[0,255]中的值,则必须除以255。
例如,50%绿色的50%红色:
// background, 50% green var bg = new Color { R = 0.00, G = 1.00, B = 0.00, A = 0.50 }; // paint, 50% red var fg = new Color { R = 1.00, G = 0.00, B = 0.00, A = 0.50 }; // The result var r = new Color(); rA = 1 - (1 - fg.A) * (1 - bg.A); // 0.75 rR = fg.R * fg.A / rA + bg.R * bg.A * (1 - fg.A) / rA; // 0.67 rG = fg.G * fg.A / rA + bg.G * bg.A * (1 - fg.A) / rA; // 0.33 rB = fg.B * fg.A / rA + bg.B * bg.A * (1 - fg.A) / rA; // 0.00
产生的颜色是: (0.67, 0.33, 0.00, 0.75)
或75%棕色(或深橙色)。
你也可以反转这些公式:
var bg = new Color(); if (1 - fg.A <= 1.0e-6) return null; // No result -- 'fg' is fully opaque if (rA - fg.A < -1.0e-6) return null; // No result -- 'fg' can't make the result more transparent if (rA - fg.A < 1.0e-6) return bg; // Fully transparent -- R,G,B not important bg.A = 1 - (1 - rA) / (1 - fg.A); bg.R = (rR * rA - fg.R * fg.A) / (bg.A * (1 - fg.A)); bg.G = (rG * rA - fg.G * fg.A) / (bg.A * (1 - fg.A)); bg.B = (rB * rA - fg.B * fg.A) / (bg.A * (1 - fg.A));
要么
var fg = new Color(); if (1 - bg.A <= 1.0e-6) return null; // No result -- 'bg' is fully opaque if (rA - bg.A < -1.0e-6) return null; // No result -- 'bg' can't make the result more transparent if (rA - bg.A < 1.0e-6) return bg; // Fully transparent -- R,G,B not important fg.A = 1 - (1 - rA) / (1 - bg.A); fg.R = (rR * rA - bg.R * bg.A * (1 - fg.A)) / fg.A; fg.G = (rG * rA - bg.G * bg.A * (1 - fg.A)) / fg.A; fg.B = (rB * rA - bg.B * bg.A * (1 - fg.A)) / fg.A;
公式会计算出背景或油漆的颜色必须是产生给定的结果颜色。
如果你的背景不透明,结果也是不透明的。 然后,前景颜色可以取不同的alpha值的一系列值。 对于每个通道(红色,绿色和蓝色),您必须检查哪个范围的alpha结果为有效值(0 – 1)。
有趣的事实:计算机的RGB值是从光子通量的平方根衍生出来的。 所以作为一个普通的function,你的math应该考虑到这一点。 给定频道的一般function是:
blendColorValue(a, b, t) return sqrt((1 - t) * a^2 + t * b^2)
其中,a和b是要混合的颜色,t是从0到1的数字,表示在a和b之间要混合的点。
Alpha通道是不同的; 它不代表光子强度,只是应该显示的背景的百分比; 所以在混合alpha值时,线性平均就足够了:
blendAlphaValue(a, b, t) return (1-t)*a + t*b;
所以,要处理混合两种颜色,使用这两个函数,下面的伪代码应该对你有好处:
blendColors(c1, c2, t) ret [r, g, b].each n -> ret[n] = blendColorValue(c1[n], c2[n], t) ret.alpha = blendAlphaValue(c1.alpha, c2.alpha, t) return ret
顺便说一下,我渴望一种编程语言和键盘,它们都允许干净地表示(或更多)math(联合Unicode字符不适用于上标,符号和大量其他字符)并正确解释math。 sqrt((1-t)* pow(a,2)+ t * pow(b,2))只是不读为干净的。
几点:
- 我想你想用min而不是max
- 我想你想用255而不是256
这会给:
(r1,g1,b1)+(r2,g2,b2)=(min(r1 + r2,255),min(g1 + g2,255),min(b1 + b2,255))
然而,混合颜色的“自然”方式是使用平均值,然后你不需要min:
(r1,g1,b1)+(r2,g2,b2)=((r1 + r2)/ 2,(g1 + g2)/ 2,(b1 + b2)/ 2)
Javascript函数来混合rgba颜色
c1,c2和结果 – JSON类似于c1 = {r:0.5,g:1,b:0,a:0.33}
var rgbaSum = function(c1, c2){ var a = c1.a + c2.a*(1-c1.a); return { r: (c1.r * c1.a + c2.r * c2.a * (1 - c1.a)) / a, g: (c1.g * c1.a + c2.g * c2.a * (1 - c1.a)) / a, b: (c1.b * c1.a + c2.b * c2.a * (1 - c1.a)) / a, a: a } }
是的,就这么简单。 另一种select是find平均值(用于创build渐变)。
这实际上取决于你想达到的效果。
但是,当Alpha被添加时,它变得复杂。 有一些不同的方法来使用alpha进行混合。
一个简单的alpha混合的例子: http : //en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending
通过添加 CMYK 空间中的 PYTHON 色彩 混合
一种可能的方法是首先将颜色转换为CMYK格式,将它们添加到那里,然后重新转换为RGB。
以下是Python中的一个示例代码:
rgb_scale = 255 cmyk_scale = 100 def rgb_to_cmyk(self,r,g,b): if (r == 0) and (g == 0) and (b == 0): # black return 0, 0, 0, cmyk_scale # rgb [0,255] -> cmy [0,1] c = 1 - r / float(rgb_scale) m = 1 - g / float(rgb_scale) y = 1 - b / float(rgb_scale) # extract out k [0,1] min_cmy = min(c, m, y) c = (c - min_cmy) m = (m - min_cmy) y = (y - min_cmy) k = min_cmy # rescale to the range [0,cmyk_scale] return c*cmyk_scale, m*cmyk_scale, y*cmyk_scale, k*cmyk_scale def cmyk_to_rgb(self,c,m,y,k): """ """ r = rgb_scale*(1.0-(c+k)/float(cmyk_scale)) g = rgb_scale*(1.0-(m+k)/float(cmyk_scale)) b = rgb_scale*(1.0-(y+k)/float(cmyk_scale)) return r,g,b def ink_add_for_rgb(self,list_of_colours): """input: list of rgb, opacity (r,g,b,o) colours to be added, o acts as weights. output (r,g,b) """ C = 0 M = 0 Y = 0 K = 0 for (r,g,b,o) in list_of_colours: c,m,y,k = rgb_to_cmyk(r, g, b) C+= o*c M+=o*m Y+=o*y K+=o*k return cmyk_to_rgb(C, M, Y, K)
结果你的问题将是(假设你的两种颜色的一半的混合物:
r_mix, g_mix, b_mix = ink_add_for_rgb([(r1,g1,b1,0.5),(r2,g2,b2,0.5)])
那里的0.5是在那里说我们混合50%的第一个颜色和50%的第二个颜色。
这里有一个高度优化的独立c ++类,公共领域,带有浮点和两个不同优化的8位混合机制,包括函数和macros的格式,以及关于手头上的问题以及如何和重要性的技术讨论的,这个问题的优化: