点对点线性渐变?

发布于 2024-09-02 04:22:54 字数 98 浏览 9 评论 0原文

我想制作一个可以生成点对点渐变的应用程序(就像 Photoshop 那样)。我熟悉如何生成从上到下的渐变,但不熟悉如何生成点到点的渐变。这在概念上是如何完成的。

谢谢

I want to make an application that can generate point to point gradient (like Photoshop does). I'm familiar with how to generate an up to down gradient but not point to point. How is this conceptually done.

Thanks

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

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

发布评论

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

评论(3

太阳哥哥 2024-09-09 04:22:54

我不能说这是否正是 Photoshop 的做法,或者说这是最佳的做法,但这应该是基本原则。

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

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

它实际上与用于上下渐变的方法非常相似,只是它是旋转的。

I can't say if this is exactly how Photoshop does it, or that it's the most optimal way of doing it, but this should be the basic principle.

Think of the two points as defining a vector. You can find a normal vector for this, which will be perpendicular to the original vector (since that's the definition of a normal vector).

For each discrete point (pixel) on the line, calculate the gradient color as you would for an up-down (or left-right) gradient of the same length as your vector. Then draw a line of the selected color, such that it passes through the currently chosen point and is parallel with the normal vector.

It's actually very similar to the approach you'd use for an up-down gradient, except it's rotated.

橘亓 2024-09-09 04:22:54

基于迈克尔·马德森的答案 -

对于您要填充的区域中的每个点,计算线段上最近的点。 (你必须用 google 搜索一下,但有很多例子。)在计算最近点的某个时刻,计算出的值范围从起点处的 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 只是 t。但无论如何...我想这会让你到达那里。也许显然,前半部分是“静态的”,因此您只需要循环最后四行。

Building on Michael Madsen's answer-

For every point in the region you're filling, compute the closest point on the line segment. (You'll have to google that, but there are plenty of examples.) At some point in the computation of that closest point, there's a value computed that ranges from 0 at the start point to 1 at the end point. Plug that into whatever your gradient function is.

The overview of the algorithm is basically...

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

You can actually lose the make t/d just t if you scale v by 1/d^2 instead of 1/d. But anyway... I think this'll get you there. Perhaps obviously, the first half is "static" so you only need to loop over the last four lines.

苏佲洛 2024-09-09 04:22:54

此例程使用适当的值调用图像中每个点的函子。使用该值作为颜色查找表的索引,您将获得混合效果。 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.
    }
  }

This routine calls your functor for each point in the image, with the appropriate value. Use the value as an index into a colour lookup table and you'll have your blend. Functor has this prototype: 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.
    }
  }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文