从一种颜色到另一种颜色的插值

use*_*679 10 c++ openframeworks

我试图将一种颜色插入到另一种相同颜色的阴影中.(例如:天蓝色至深蓝色然后返回).

我偶然发现了一些代码,如果范围是0-255或0-1,可以使用.但是,就我而言,我有Color1和Color2的RGB代码,并希望进行旋转.

颜色1:151,206,255
颜色2:114,127,157

任何想法如何去做?

Car*_*los 19

我知道这有点旧,但如果有人在寻找它,那是值得的.

首先,你可以在任何颜色空间中进行插值,包括RGB,在我看来,这是最简单的颜色之一.

假设变化将由0和1之间的分数值(例如0.3)控制,其中0表示全色1,1表示全色2.

理论:

Result = (color2 - color1) * fraction + color1
Run Code Online (Sandbox Code Playgroud)

应用:

由于RGB有3个通道(红色,绿色和蓝色),我们必须为每个通道执行此数学运算.

使用您的示例颜色:

color1: 151,206,255
color2: 114,127,157

R =  (114-151) * fraction + 151
G =  (127-206) * fraction + 206
B =  (157-255) * fraction + 255
Run Code Online (Sandbox Code Playgroud)

很简单!


Syn*_*xis 10

将RGB颜色转换为HSV,然后插入每个组件(不仅是颜色,请参阅答案结束),之后您可以转换回RGB.

您可以进行RGB插值,但HSV的结果更好,因为在此空间中颜色与亮度和饱和度分开(维基百科关于HSV的文章).HSV插值比RGB插值更"逻辑",因为后者可以在插值时获得额外的颜色.

插值的一些代码:

template<typename F>
ColorRGB interpolate(ColorRGB a, ColorRGB b, float t, F interpolator)
{
    // 0.0 <= t <= 1.0
    ColorHSV ca = convertRGB2HSV(a);
    ColorHSV cb = convertRGB2HSV(b);
    ColorHSV final;

    final.h = interpolator(ca.h, cb.h, t);
    final.s = interpolator(ca.s, cb.s, t);
    final.v = interpolator(ca.v, cb.v, t);

    return convertHSV2RGB(final);
}

int linear(int a, int b, float t)
{
    return a * (1 - t) + b * t;
}

// use: result = interpolate(color1,color2,ratio,&linear);
Run Code Online (Sandbox Code Playgroud)

  • 为了扩展“你可以获得额外的颜色”......例如,在 RGB 中,从蓝色到黄色的线性插值不直观地穿过中性灰色;HSV 要么穿过绿色,要么穿过洋红色、红色、橙色。因此,无论哪种方式,您都会获得额外的颜色。事实上,显示的 `linear()` HSV 插值有时会添加一系列色调,因为它没有考虑到色调是周期性的。从红色(0 度)到紫色(300 度)会产生橙色、黄色、绿色、蓝色——几乎是整个光谱——当你可能想要标准化并通过紫色走更短的路线时。 (2认同)

hyd*_*yde 9

我建议你将RGB转换为HSV,然后调整其组件,然后转换回RGB.

维基百科有一篇关于它的文章,之前已经讨论过:

HSL到RGB颜色转换

将RGB转换为HSV和HSV转换为RGB的算法,范围为0-255

许多框架也有转换函数,例如Qt有QColor类.


但问题是关于实际插值...这里是一个简单的插值函数:

// 0 <= stepNumber <= lastStepNumber
int interpolate(int startValue, int endValue, int stepNumber, int lastStepNumber)
{
    return (endValue - startValue) * stepNumber / lastStepNumber + startValue;
}
Run Code Online (Sandbox Code Playgroud)

因此,在循环中调用您想要插入的所有颜色分量.使用RBG插值,您需要插入每个组件,在其他一些颜色空间中,您可能只需插入一个.


Mik*_*e M 6

用于视觉效果的最佳色彩空间是HCL。这是一个专门为在遍历其维度时看起来不错而创建的空间,其中“看起来不错”与光或墨水的任何物理属性无关,分别如 RGB 和 CMYK。

使用 HCL 是昂贵的,所以最好的办法是在这个空间中创建一些中间值,然后在原生的 RGB 中进行插值。这就是我在我的动画引擎中所做的。

这是它的一个片段,在 Swift 4.0 中

extension UIColor {
    typealias Components = (CGFloat, CGFloat, CGFloat, CGFloat)
    enum Space: String {
        case RGB = "RGB"
        case HSB = "HSB"
        case HCL = "HCL"
    }
    func components(in space: UIColor.Space) -> Components {
        switch space {
        case .RGB: return self.rgba // var defined in HandyUIKit's extension
        case .HSB: return self.hsba // var defined in HandyUIKit's extension
        case .HCL: return self.hlca // var defined in HandyUIKit's extension
        }
    }
    func spectrum(to tcol: UIColor, for space: UIColor.Space) -> [UIColor] {
        var spectrum = [UIColor]()
        spectrum.append(self)
        let fcomps  = self.components(in: space)
        let tcomps  = tcol.components(in: space)
        for i in 0 ... 5 {
            let factor  = CGFloat(i) / 5.0
            let comps   = (1.0 - factor) * fcomps + factor * tcomps
            let color   = UIColor(with: comps, in: space)
            spectrum.append(color)
        }
        spectrum.append(tcol)
        return spectrum
    }
    convenience init(with components: Components, in space: Space) {
        switch space {
        case .RGB: self.init(red: components.0, green: components.1, blue: components.2, alpha: components.3)
        case .HSB: self.init(hue: components.0, saturation: components.1, brightness: components.2, alpha: components.3)
        case .HCL: self.init(hue: components.0, luminance: components.1, chroma: components.2, alpha: components.3)
        }
    }
}
func *(lhs:CGFloat, rhs:UIColor.Components) -> UIColor.Components {
    return (lhs * rhs.0, lhs * rhs.1, lhs * rhs.2, lhs * rhs.3)
}
func +(lhs:UIColor.Components, rhs:UIColor.Components) -> UIColor.Components {
    return (lhs.0 + rhs.0, lhs.1 + rhs.1, lhs.2 + rhs.2, lhs.3 + rhs.3)
}
Run Code Online (Sandbox Code Playgroud)

引擎和上面的示例都使用HandyUIKit进行空间之间的转换,因此请将此项目添加到您正在构建的任何内容中,以使上述代码工作。

我写了一篇关于它的文章