在2D数组中创建线性渐变

时间:2009-02-06 18:15:58

标签: c++ algorithm graphics

我有一个类似2D位图的数组,比方说500 * 500的值。我正在尝试在数组上创建线性渐变,因此生成的位图看起来像这样(灰度): Example gradient
(来源:showandtell-graphics.com

输入将是要填充的数组,两个点(如Photoshop / GIMP中渐变工具的起点和终点)以及将使用的值范围。

我目前最好的结果是:

alt text http://img222.imageshack.us/img222/1733/gradientfe3.png

......这远远不是我想要实现的目标。它看起来更像是径向渐变。

创建这样一个渐变的最简单方法是什么?我将用C ++实现它,但我想要一些通用的算法。

4 个答案:

答案 0 :(得分:14)

这实际上是一个数学问题,所以它是否真的“属于”Stack Overflow可能是有争议的,但无论如何:你需要将图像中每个点的坐标投影到渐变的轴上并使用该坐标确定颜色。

数学上,我的意思是:

  1. 说你的起点是(x1,y1),结束点是(x2,y2)
  2. 计算A = (x2 - x1)B = (y2 - y1)
  3. 计算C1 = A * x1 + B * y1作为起点,C2 = A * x2 + B * y2表示结束点(C2应大于C1
  4. 对于图像中的每个点,计算C = A * x + B * y
  5. 如果C <= C1,请使用起始颜色;如果C >= C2,请使用结束颜色;否则,使用加权平均值:

    (start_color * (C2 - C) + end_color * (C - C1))/(C2 - C1)

  6. 我做了一些快速测试,检查这基本上是否有效。

答案 1 :(得分:3)

在示例图像中,看起来您有一个径向渐变。这是我对你需要的步骤的impromtu数学解释。对于数学,对不起,其他答案在实施方面更好。

  1. 定义一个线性函数(如y = x + 1),其中域(即x)从您想要开始的颜色到您想要结束的颜色。您可以根据Ox0到OxFFFFFF(24位颜色)的范围来考虑这个问题。如果你想处理像亮度这样的事情,你将不得不对范围(即y值)做一些技巧。
  2. 接下来,您需要在您拥有的矩阵上映射一个矢量,因为它定义了颜色将改变的方向。此外,线性函数定义的颜色值将在矢量的每个点上指定。向量的起点和终点也定义了1中域的最小值和最大值。您可以将向量视为渐变的一条线。
  3. 对于矩阵中的每个单元格,可以从向量中为颜色指定颜色,其中来自单元格的垂直线与向量相交。请参见下图,其中c是单元格的位置。是交叉点。如果你假装的颜色。是红色,然后你将分配给细胞。
  4.              |
                 c
                 |
                 |
        Vect:____.______________
                 |
                 |
    
    

答案 2 :(得分:1)

我会发布我的解决方案。

int ColourAt( int x, int y )
{
  float imageX = (float)x / (float)BUFFER_WIDTH;
  float imageY = (float)y / (float)BUFFER_WIDTH;

  float xS = xStart / (float)BUFFER_WIDTH;
  float yS = yStart / (float)BUFFER_WIDTH;
  float xE = xEnd / (float)BUFFER_WIDTH;
  float yE = yEnd / (float)BUFFER_WIDTH;
  float xD = xE - xS;
  float yD = yE - yS;

  float mod = 1.0f / ( xD * xD + yD * yD );

  float gradPos = ( ( imageX - xS ) * xD + ( imageY - yS ) * yD ) * mod;

  float mag = gradPos > 0 ? gradPos < 1.0f ? gradPos : 1.0f : 0.0f;

  int colour = (int)( 255 * mag );
  colour |= ( colour << 16 ) + ( colour << 8 );
  return colour;
}

对于加速,缓存派生的“方向”值(提示:由mag预乘)。

答案 3 :(得分:0)

这个问题有两个部分。

  1. 给定两种颜色A和B以及一些百分比p,确定从A到B的p'百分比是什么颜色。

  2. 给定平面上的一个点,找到该点在给定直线上的正交投影。

  3. 第2部分中的给定行是您的渐变线。给定任何点P,将其投影到梯度线上。假设它的投影是R.然后计算R距离渐变线段起点的距离,作为渐变线段长度的百分比。在上面第1部分的函数中使用此百分比。这就是P的颜色。

    请注意,与其他人所说的相反,您不能只在第1部分的功能中将您的颜色视为常规数字。这几乎肯定不会达到您想要的效果。你做什么取决于你使用的色彩空间。如果您想要RGB渐变,则必须分别查看红色,绿色和蓝色组件。

    例如,如果你想要一个颜色“中间的”纯红色和蓝色,那么你用的是十六进制表示法

    ff 00 00

    <00> 00 00 ff

    你想要的颜色可能就像

    80 00 80

    这是一种漂亮的紫色。您必须分别平均每个颜色组件。如果你试图直接平均十六进制数0xff0000和0x0000ff,你得到0x7F807F,这是一个中灰色。我猜这至少解释了上面你的照片的部分问题。

    或者,如果您在HSV色彩空间中,您可能只想调整色调组件,并保留其他组件。