点对点线性梯度?

时间:2010-05-19 22:03:48

标签: c++ c algorithm graphics gradient

我想创建一个可以生成点对点渐变的应用程序(就像Photoshop一样)。我熟悉如何生成向上渐变而不是点对点。这是如何在概念上完成的。

由于

3 个答案:

答案 0 :(得分:3)

我不能说这是完全 Photoshop是如何做到的,或者它是最佳的做法,但这应该是基本原则。

将这两点视为定义向量。你可以找到一个法向量,它将垂直于原始向量(因为这是法向量的定义)。

对于线上的每个离散点(像素),计算渐变颜色,就像使用与矢量长度相同的上下(或左右)渐变一样。然后绘制一条选定颜色的线,使其穿过当前选定的点并与法线向量平行。

它实际上非常类似于你用于上下渐变的方法,除了它被旋转。

答案 1 :(得分:2)

以Michael Madsen的回答为基础 -

对于您正在填充的区域中的每个点,计算线段上的最近点。 (你必须谷歌,但有很多例子。)在计算最近点的某个时刻,有一个计算的值,范围从起点的0到终点的1。将其插入任何渐变函数即可。

该算法的概述基本上是......

pc = # the point you are coloring now
p0 = # start point
p1 = # end point
v = p1 - p0
d = Length(v)
v = Normalize(v) # or Scale(v, 1/d)

v0 = pc - p0

t = Dot(v0, v)
t = Clamp(t/d, 0, 1)

color = (start_color * t) + (end_color * (1 - t))

如果你将v缩放1 / d ^ 2而不是1 / d,你实际上可能会失去make t / d。但无论如何......我想这会让你到那儿。也许很明显,前半部分是“静态的”所以你只需要循环过去四行。

答案 2 :(得分:0)

此例程使用适当的值调用图像中每个点的仿函数。使用该值作为颜色查找表的索引,您将获得混合。 Functor有这个原型:void(int x,int y,int value)。

/** Produce a linear gradient.

    This implementation uses float values.
*/
struct Linearf
{
  template <class Functor>
  void operator() (
    int rows,
    int cols,
    int x0, int y0,
    int x1, int y1,
    int const scale,
    Functor f)
  {
    if (x0 != x1)
    {
      // 1/m'
      float const m = float (y1 - y0) / (x0 - x1);

      for (int y = 0; y < rows; ++y)
      {
        float const p0 = m * (y - y0) + x0;
        float const p1 = m * (y - y1) + x1;
        float const d = (scale + 0.9999f) / (p1 - p0);

        for (int x = 0; x < cols; ++x)
        {
          if (x < p0)
          {
            f (x, y, 0);
          }
          else if (x >= p1)
          {
            f (x, y, scale);
          }
          else
          {
            f (x, y, d * (x - p0));
          }
        }
      }
    }
    else
    {
      // Special case for horizontal lines.
    }
  }