Двухточечный линейный градиент? - PullRequest
0 голосов
/ 20 мая 2010

Я хочу создать приложение, которое может генерировать градиент от точки к точке (как это делает Photoshop). Я знаком с тем, как генерировать градиент вверх-вниз, но не указываю на точку. Как это концептуально сделано.

Спасибо

Ответы [ 3 ]

3 голосов
/ 20 мая 2010

Я не могу сказать, если это точно , как это делает Photoshop, или это самый оптимальный способ сделать это, но это должно быть основным принципом.

Думайте о двух точках как об определении вектора. Для этого вы можете найти нормальный вектор, который будет перпендикулярен исходному вектору (так как это определение нормального вектора).

Для каждой отдельной точки (пикселя) на линии рассчитайте цвет градиента, как если бы вы использовали градиент вверх-вниз (или влево-вправо) той же длины, что и ваш вектор. Затем нарисуйте линию выбранного цвета так, чтобы она проходила через текущую выбранную точку и была параллельна вектору нормали.

На самом деле это очень похоже на подход, который вы бы использовали для градиента вверх-вниз, за ​​исключением того, что он повернут.

2 голосов
/ 20 мая 2010

Опираясь на ответ Майкла Мэдсена -

Для каждой точки в области, которую вы заполняете, вычислите ближайшую точку на отрезке линии. (Вы должны будете погуглить это, но есть множество примеров.) В какой-то момент в вычислении этой ближайшей точки вычисляется значение, которое колеблется от 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))

Вы можете потерять make t / d просто t, если вы масштабируете v на 1 / d ^ 2 вместо 1 / d. Но в любом случае ... Я думаю, это тебя туда доставит. Возможно, очевидно, что первая половина «статична», поэтому вам нужно только зациклить последние четыре строки.

0 голосов
/ 30 августа 2012

Эта процедура вызывает ваш функтор для каждой точки на изображении с соответствующим значением. Используйте значение в качестве индекса в таблице соответствия цветов, и вы получите свою смесь. У 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.
    }
  }
...