双线性插值颜色方案

时间:2012-01-02 23:50:07

标签: c# colors interpolation lookup

我目前正在研究C#中的Mandelbrot分形生成器程序。对于着色方案,我使用线性插值和数组作为查找表。

线性插值的问题是我只能使用两种颜色。

我想使用至少三种颜色,我一直在寻找双线性插值编程算法,但我找不到任何好的颜色。

我想知道你们中是否有人可以解决这个问题。

这是我的线性插值代码:

private void InitColors()
{
    int range = 255;
    lookup = new Color[range];
    Color from = Color.White;
    Color to = Color.Blue;
    int red;
    int green;
    int blue;

    for (int i = 0; i < range; i++)
    {
        red = ((from.R * (range - i)) + (to.R * i)) / range;
        green = ((from.G * (range - i)) + (to.G * i)) / range;
        blue = ((from.B * (range - i)) + (to.B * i)) / range;
        lookup[i] = Color.FromArgb(red, green, blue);
    }
}

编辑:也许有一个比双线性更简单的插值来获得两种以上颜色之间的渐变。只要完成工作,我真的不在乎哪种方法: - )

2 个答案:

答案 0 :(得分:2)

你所追求的并不是真正的双线性插值。双线性意味着使用两个参数i和j在0-1范围内的二维颜色图,并使用这两个i,j值混合四种颜色 - 即

C = C_00 (1-i) (1-j) + C_10 * i * (1-j) + C_01 * (1-i) * j + C_11 * i * j

其中C_ij是角落颜色。

如果我理解你真正想要的是能够创建一个涉及多种颜色的渐变,但仍然是一维的,使用单个参数。为此,有多种方法。其中最简单的是在0-0.5范围内混合颜色A到颜色B,在0.5到1.0范围内从B到C混合。

你当然可以分成比3只更多的颜色......

执行此操作的代码如下所示:

private void InitColors( Color * colors, int n_colors)
{
    int range = 255;
    lookup = new Color[range];
    int red;
    int green;
    int blue;

    for (int i = 0; i < range; i++)
    {
        float f = float(i)/float(range);
        //Work out which interval we're in
        int interval = f*(n_colors);

        //Special case for the end point to prevent out-of-bounds access. 
        if(f>=1.0) { interval = n_colors-1; }

        //Work out how far into that interval we are
        float ff = f * (n_colors-1) - interval;

        int R = (colors[interval].R * (1-f) + colors[interval+1].R*f;
        int G = (colors[interval].G * (1-f) + colors[interval+1].G*f;
        int B = (colors[interval].B * (1-f) + colors[interval+1].B*f;

        lookup[i] = Color.FromArgb(R, G, B);
    }
}

现在有一些问题你可能不会关心,但我会提到以防万一:

  • 这不是一个非常平滑的颜色过渡。如果你想要更平滑的行为,你需要使用基于样条的方法(从技术上讲,这是最简单的版本)。我建议考虑一下Cattmul-Rom splines。

  • 颜色过渡不是很均匀或不错。我考虑在RGB以外的空间中进行计算,最后转换回RGB。为此,我考虑Lab空间(HSV是另一种选择,但是你需要担心在H方向上包裹。)

希望这有帮助。

答案 1 :(得分:1)

正如您的代码中所建议的,每个颜色都可以表示为Euclidean 3空间中的矢量。

因此,给定3个任意颜色C1,C2和C3,首先找到相关的RGB矢量v1,v2,v3,然后通过采用所有“凸组合”来构造每个矢量顶端具有顶点的三角形区域。这3个载体:

c1 * v1 + c2 * v2 + c3 * v3

其中c1,c2和c3是0和1之间的标量值,c1 + c2 + c3 = 1,并且适用矢量加法(和标量乘法)的通常欧几里德规则。

注意:这也适用于任意数量的颜色。对于N种颜色,您有N个相关向量,这些向量的“凸组合”是N-1维“单形”。它是线性的,非常容易计算。但是这种方式产生的颜色梯度可能不是美学上的最佳 - 非线性方法可能会产生更美观的结果。

编辑:几何上,如果N> 1,则具有N个顶点的“单形”实际上不是N-1维。 3,因为你的“矢量”都存在于3维的RGB空间中,因此不能全部线性独立。这意味着通常(对于N> 3)在“单形”中具有不同坐标但具有相同的明显“颜色”的许多点。