具有角度和强度的线性梯度
Linear Gradient with Angle & Strength
我想在 C++/RealBasic 中实现一个函数,通过参数创建颜色渐变:
- 图片的宽度和高度
- 2 种颜色的渐变
- 渐变的角度(方向)
- 渐变强度
以下链接显示了所需输出图像的一些示例:
http://www.artima.com/articles/linear_gradients_in_flex_4.html, http://i.stack.imgur.com/4ssfj.png
我找到了多个示例,但它们只给我垂直和水平渐变,而我也想指定角度和强度。
有人可以帮我吗?
P.S.: 我对几何学一窍不通!! :(
你的问题很广泛,事实上,这是一个非常复杂的练习,有很多代码,包括图像渲染、图像格式处理、将文件写入磁盘等。这些不是单个函数的问题.因此,我专注于制作 2 种颜色的任意线性颜色渐变。
线性颜色渐变
您可以通过 linear interpolation between 2 colors. However simple linear interpolation makes really harsh-looking transitions. For visually more appealing results I recommend to use some kind of S-shaped interpolation curve like the Hermite interpolation based smoothstep 创建线性颜色 "gradient"。
关于角度,可以通过颜色渐变的起点(p0
)和终点(p1
)定义一条线段。我们称它们之间的距离为 d01
,因此为 d01 = distance(p0, p1)
。然后对于图像的每个像素点 p
,您必须计算该段上的最近点 p2
。 Here is an example 怎么做。然后计算t = distance(p0, p2) / d01
。这将是范围 [0, 1] 中的 lerp 参数 t
。
通过此 t
在 2 个渐变颜色之间进行插值,您得到了给定点 p
.
的颜色
这可以通过多种方式实现。您可以使用 OpenGL 渲染图像,然后将像素缓冲区读回 RAM。如果您不熟悉 OpenGL 或渲染过程,您可以编写一个函数,它接受一个点(像素的二维坐标)和 returns RGB 颜色 - 这样您就可以计算图像的所有像素。最后,您可以使用图像格式将图像写入磁盘,但那是另一回事了。
以下是上述一些函数的示例 C++14 实现。
简单线性插值:
template <typename T, typename U>
T lerp(const T &a, const T &b, const U &t)
{
return (U(1) - t)*a + t*b;
}
,其中 a
和 b
是您要在其间插值的两个值(本例中为颜色),t
是 [0, 1]代表a
和b
之间的过渡。
当然,上面的函数需要一个支持标量乘法的类型T
。为此,您可以简单地使用任何 3D 矢量类型,因为颜色实际上是颜色 space.
中的坐标
两个二维点之间的距离:
#include <cmath>
auto length(const Point2 &p)
{
return std::sqrt(p.x*p.x + p.y*p.y);
}
auto distance(const Point2 &a, const Point2 &b)
{
Point delta = b - a;
return length(delta);
}
图片来自https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient
我想在 C++/RealBasic 中实现一个函数,通过参数创建颜色渐变:
- 图片的宽度和高度
- 2 种颜色的渐变
- 渐变的角度(方向)
- 渐变强度
以下链接显示了所需输出图像的一些示例: http://www.artima.com/articles/linear_gradients_in_flex_4.html, http://i.stack.imgur.com/4ssfj.png
我找到了多个示例,但它们只给我垂直和水平渐变,而我也想指定角度和强度。
有人可以帮我吗?
P.S.: 我对几何学一窍不通!! :(
你的问题很广泛,事实上,这是一个非常复杂的练习,有很多代码,包括图像渲染、图像格式处理、将文件写入磁盘等。这些不是单个函数的问题.因此,我专注于制作 2 种颜色的任意线性颜色渐变。
线性颜色渐变
您可以通过 linear interpolation between 2 colors. However simple linear interpolation makes really harsh-looking transitions. For visually more appealing results I recommend to use some kind of S-shaped interpolation curve like the Hermite interpolation based smoothstep 创建线性颜色 "gradient"。
关于角度,可以通过颜色渐变的起点(p0
)和终点(p1
)定义一条线段。我们称它们之间的距离为 d01
,因此为 d01 = distance(p0, p1)
。然后对于图像的每个像素点 p
,您必须计算该段上的最近点 p2
。 Here is an example 怎么做。然后计算t = distance(p0, p2) / d01
。这将是范围 [0, 1] 中的 lerp 参数 t
。
通过此 t
在 2 个渐变颜色之间进行插值,您得到了给定点 p
.
这可以通过多种方式实现。您可以使用 OpenGL 渲染图像,然后将像素缓冲区读回 RAM。如果您不熟悉 OpenGL 或渲染过程,您可以编写一个函数,它接受一个点(像素的二维坐标)和 returns RGB 颜色 - 这样您就可以计算图像的所有像素。最后,您可以使用图像格式将图像写入磁盘,但那是另一回事了。
以下是上述一些函数的示例 C++14 实现。
简单线性插值:
template <typename T, typename U>
T lerp(const T &a, const T &b, const U &t)
{
return (U(1) - t)*a + t*b;
}
,其中 a
和 b
是您要在其间插值的两个值(本例中为颜色),t
是 [0, 1]代表a
和b
之间的过渡。
当然,上面的函数需要一个支持标量乘法的类型T
。为此,您可以简单地使用任何 3D 矢量类型,因为颜色实际上是颜色 space.
两个二维点之间的距离:
#include <cmath>
auto length(const Point2 &p)
{
return std::sqrt(p.x*p.x + p.y*p.y);
}
auto distance(const Point2 &a, const Point2 &b)
{
Point delta = b - a;
return length(delta);
}
图片来自https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient