双线性插值配色方案

发布于 2024-12-24 03:49:03 字数 757 浏览 2 评论 0原文

我目前正在使用 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);
    }
}

编辑:也许有比双线性插值更简单的插值来获得两种以上颜色之间的渐变。我并不关心使用哪种方法,只要它能完成工作即可:-)

I'm currently working on a Mandelbrot fractal generator program in C#. For a coloring scheme, I'm using a linear interpolation and an array as a lookup table.

The problem with linear interpolation is that I can only use two colors.

I would like to use at least three colors and I've been looking around for a bilinear interpolation programming algorithm but I haven't found any good ones.

I was wondering if any of you might have a solution to this.

Here is my linear interpolation code:

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);
    }
}

EDIT: Perhaps there is a more simple interpolation than the bilinear to get a gradient between more than two colors. I don't really care which method as long as it gets the job done :-)

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

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

发布评论

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

评论(2

清旖 2024-12-31 03:49:03

你所追求的并不是真正的双线性插值。双线性意味着使用 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);
    }
}

现在有几个您可能不会关心的问题,但我会提到以防万一:

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

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

希望这会有所帮助。

What you're after is not really called bilinear interpolation. Bilinear implies a 2D colour map using two arguments i and j in 0-1 range and blends four colors using those two i,j values - i.e.

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

where C_ij are the corner colours.

If I understand you correctly what you really want is to be able to create a gradient that involves more than one color, but is still one dimensional, using a single parameter. To do this there is a variety of methods. The simplest of these is to blend from color A to color B over the 0-0.5 range and B to C over the 0.5 to 1.0 range.

You can of course divide up into more colours than just 3...

Code to do this would look something like this:

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);
    }
}

Now there's a couple of issues with this that you probably will not care about, but I'll mention just in case:

  • This is not a very smooth color transition. If you want smoother behaviour you'll need to use a spline based approach (which technically this is the simplest version of). I'd suggest looking into Cattmul-Rom splines for this.

  • The color transitions are not very uniform or nice. I'd consider doing the calculations in a space other than RGB and converting back to RGB at the end. For this I'd consider Lab space (HSV is another option, but then you need to worry about wrapping in the H direction.)

Hope this helps.

不疑不惑不回忆 2024-12-31 03:49:03

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

As suggested in your code, every color may be represented as a vector in Euclidean 3 space.

So given 3 arbitrary colors C1, C2, and C3, first find the associated RGB vectors v1, v2, v3, and then construct the triangular region with a vertex at the tip of each vector by taking all "convex combinations" of these 3 vectors:

c1 * v1 + c2 * v2 + c3 * v3

where c1, c2, and c3 are scalar values between 0 and 1, and c1 + c2 + c3 = 1, and the usual Euclidean rules of vector addition (and scalar multiplication) apply.

NOTE: This also works for an arbitrary number of colors. For N colors you have N associated vectors, and the "convex combinations" of these vectors is an N-1 dimensional "simplex". It's all linear, and very easy to calculate. But the color gradient produced this way may not be aesthetically optimal - a non-linear method may produce a more beautiful result.

EDIT: Geometrically speaking your "simplex" with N vertices will not actually be N-1 dimensional if N > 3, because your "vectors" all live in RGB space which is 3 dimensional, and so cannot all be linearly independent. This means there will generally (for N > 3) be many points in the "simplex" with different coordinates but the same apparent "color".

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