C# 双线性插值颜色方案

C# 双线性插值颜色方案,c#,colors,interpolation,lookup,C#,Colors,Interpolation,Lookup,我目前正在用C#编写一个Mandelbrot分形生成器程序。对于着色方案,我使用线性插值和数组作为查找表 线性插值的问题是我只能使用两种颜色 我想使用至少三种颜色,我一直在寻找一个双线性插值编程算法,但我没有找到任何好的 我想知道你们中是否有人能解决这个问题 这是我的线性插值代码: private void InitColors() { int range = 255; lookup = new Color[range]; Color from = Color.White

我目前正在用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);
    }
}
private void InitColors()
{
整数范围=255;
查找=新颜色[范围];
颜色来源=颜色。白色;
颜色到=颜色。蓝色;
红色;
绿色;
蓝色;
对于(int i=0;i

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

正如您的代码中所建议的,每种颜色都可以表示为欧几里德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>3,则具有N个顶点的“单纯形”实际上不会是N-1维的,因为您的“向量”都生活在三维RGB空间中,因此不可能都是线性独立的。这意味着“单纯形”中通常会有许多点(对于N>3)具有不同的坐标,但具有相同的外观“颜色”

您所追求的并不是真正意义上的双线性插值。双线性表示在0-1范围内使用两个参数i和j的2D颜色贴图,并使用这两个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);
    }
}
private void InitColors(颜色*颜色,int n_颜色)
{
整数范围=255;
查找=新颜色[范围];
红色;
绿色;
蓝色;
对于(int i=0;i=1.0){interval=n_colors-1;}
//计算出我们的时间间隔有多远
浮动ff=f*(n_颜色-1)-间隔;
int R=(颜色[interval].R*(1-f)+颜色[interval+1].R*f;
intg=(颜色[interval].G*(1-f)+颜色[interval+1].G*f;
intb=(颜色[interval].B*(1-f)+颜色[interval+1].B*f;
lookup[i]=Color.FromArgb(R,G,B);
}
}
现在有几个问题你可能不会关心,但我会提到以防万一:

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

  • 颜色转换不是很均匀或很好。我会考虑在RGB以外的空间进行计算,并在最后转换为RGB。为此,我会考虑<代码> Lab 空间(HSV是另一种选择,但是你需要担心在H方向上缠绕)。

希望这能有所帮助。

很明显,线性插值可以在两种颜色之间提供渐变。但是如果你想在三种颜色之间进行插值,那么你需要(至少)两个自由度。两个或更多的自由度是什么要用于驱动颜色选择的变量?递归深度?X坐标?与平面中任意点的距离?我不在乎使用什么方法,只要我得到两种以上颜色之间的渐变结果。但我想要一个非常简单的,如果存在的话:-P“双线性意味着两个参数I和j”这些参数意味着什么?通过一个例子阐明了这一点(希望如此)。因此它们是任意系数?你可以将i,j视为2D色块的索引,而不是OP似乎想要的,这是一个包含多种颜色的一维查找。你如何处理三角形区域?