C# 颜色渐变控件






4.54/5 (22投票s)
C# 颜色渐变控制的实现,以及一个应用于程序化地形生成的用例。
引言
在我之前已经接触过的程序化纹理生成中 这里,以及我参与的 这里,拥有一个管理颜色渐变的工具可能会很有用。在网上搜索后,我没有找到一个 C# 控件来实现我所需要的。我决定自己动手。
背景
我遇到了两个可能有用到的颜色控制渐变的情况,第一个是在 gdi+ .net 库中 (这里),第二个在纹理生成中。在第二种情况下,你从一个噪声函数开始生成一个高度图,然后你可能希望将一个高度值与一个颜色相关联;在这里,颜色渐变就派上用场了。
让我们假设我们生成以下噪声
应用一个像这样的颜色渐变:
我们得到以下的 (类似景观的) 位图
从相同的起始噪声应用不同的颜色渐变,我们可以得到一个 (天空) 位图,像这样
使用代码
在设计中使用控件.
要在设计时添加控件 ColGradCtr
,将其拖到你的表单上并调整它的大小。它包含两个默认颜色白色(开始)和黑色(结束)。
然后你可以在控件的 load 事件(或表单的 load 事件)中重置两个起始颜色。同时你也可以添加其他颜色。
private void colGradCtr1_Load_1(object sender, EventArgs e)
{
colGradCtr1.reset(Color.Blue, Color.White); //redefine start and end color
colGradCtr1.addColor(Color.FromArgb(0, 128, 128), 0.06f); //put a color in position 0.06
colGradCtr1.addColor(Color.FromArgb(0, 0, 159), 0.60f);
colGradCtr1.addColor(Color.FromArgb(6, 20, 203), 0.70f);
colGradCtr1.addColor(Color.FromArgb(146, 96, 53), 0.75f);
colGradCtr1.addColor(Color.FromArgb(0, 100, 0), 0.80f);
colGradCtr1.addColor(Color.FromArgb(64, 0, 0), 0.90f);
}
控件至少需要两种颜色(开始和结束),分别位于位置 0 和 1。所有其他颜色都在位置 >0 和 <1。
从 ColGradCtr
获取样本颜色。如果你提供一个 float 输入 >=0 和 <=1,你将得到相应的颜色。
让我们看看景观生成例程
//paints Picturebox pct according to heightmap and ColGradCtr col
private void reColor(PictureBox pct, ColGradCtr col){
Bitmap b2 = new Bitmap(pct.Width, pct.Height);
for (int i = 0; i < pct.Width; i++)
for (int j = 0; j < pct.Height; j++)
{
b2.SetPixel(i, j, col.getColor(heightMap[i, j]));
}
pct.Image = b2;
}
其中 heightMap
是一个 float 矩阵,包含 0 到 1 之间的样本(高度)。
gdi+ 方法。如果你需要线性渐变,你可以从 ColGradCtr
以这种方式获得它:
LinearGradientBrush br = new LinearGradientBrush(this.pictureBox1.ClientRectangle, Color.Black
, Color.Black,LinearGradientMode.BackwardDiagonal);
ColorBlend cb = BackGradCtr.getColorBlend();//here i get the blend from ctrl
br.InterpolationColors = cb;
offScreenDC.FillRectangle(br, this.pictureBox1.ClientRectangle);
在运行时使用控件。在手柄上按鼠标左键,你可以移动它,改变颜色位置。如果你将手柄拖出控件(到右边),你将擦除该颜色。在手柄附近按鼠标右键可以修改颜色值,在空白处按鼠标右键可以添加新颜色。起始颜色和结束颜色不能移动或擦除,但你可以更改它们。
事件管理:我实现了两个事件,ColorChanged
和 ColorChanging
。第一个事件在你移动颜色时触发,第二个事件在你释放鼠标按钮并提交更改(修改颜色、添加颜色、擦除颜色)时触发。以下是我在示例应用程序中如何使用 ColorChanged 事件的示例
private void colGradCtr1_ColorChanged(object sender, EventArgs e)
{
reColor(pictureBox2, colGradCtr1);
}
示例应用程序:
点击 "generate new noise" 测试带有新噪声的渐变。
点击 gdi+ 示例获取第二个示例表单:
关注点
ColGradCtr 并不是 gdi+ ColrBlend 的 "包装器",它是我创建的类的 "包装器"
class Wgrad<T>
我创建的; 它是一个“有序”的对象列表
public class gradObj<T>
{
public T ele { get; set; }
public float w {get;set;}
public gradObj(T e, float p)
{
ele = e;
//clamp
if (p > 1f)
p = 1f;
if (p < 0f)
p = 0f;
w = p;
}
}
其中 T 在本例中是 Color,w 是在 0..1 范围内的位置。
以下是颜色渐变背后数据结构的解释
类 Wgrad<T>
管理一个对象 T(在本例中为 Color)的 List,根据一个介于 0 和 1 之间的 float 值保持它们排序。
Wgrad<T>
的一些方法
public voidaddEle
(Tele
, floatp
) //Adds a Color in position p (0..1) public gradObj<T>delNearest
(floatp
) //Deletes the nearest Color to p (0..1) public gradObj<T>[]getEle
(floatp
) //Gets the 2 colors before and after p (0..1)
最后,noiseGen 是我开发的用于管理噪声函数的类。它包含 2d Perlin 噪声的 C# 实现。
历史
添加了 Wgrad<T> 解释。