用 C# 创建自定义颜色映射






3.39/5 (12投票s)
2007年3月26日
7分钟阅读

115002

2293
本文展示了如何创建各种自定义颜色映射。
引言
在 C# 中,有一个默认的 ColorMap 类,定义在 System.Drawing.Imaging 命名空间中。该类定义了现有颜色与它们将被转换成的新颜色之间的映射。应用该映射时,任何旧颜色的像素都会被转换为新颜色。这个类对于图像处理应用程序很有用。
然而,在某些图形和图表应用程序中,您可能需要自定义颜色映射来实现特定的视觉效果。这些颜色映射本质上是按照某种期望的格式组织的颜色表或颜色列表。表面、补丁和图像对象可以与自定义颜色映射关联。本文将介绍如何创建这样的自定义颜色映射。
背景
要在 C# 中创建自定义颜色映射,您需要使用一个 m x 4 的颜色映射矩阵来构建。该矩阵的每一行代表 ARGB 值。行索引可以代表 2D 图表的 y 数据,或者 3D 表面图的高度(z 数据)。对于给定的具有 m 行的颜色映射矩阵,颜色数据值可以线性地缩放到颜色映射。
例如,如果您想使用颜色映射来表示 2D 图形对象的 y 坐标,您可以使用 YMin 和 YMax 将 y 数据值线性地转换为索引,每个索引标识颜色映射矩阵中的一行 ARGB 值(即一种颜色)。颜色索引值的数学变换由以下公式描述:

这里 y 是 Y 数据的单个值,m 是颜色映射矩阵的长度。这允许您在绘制的数据中使用颜色映射中的整个颜色范围。对于 3D 图形对象和 3D 表面图,y 数据应替换为 z 数据。
现在我们可以实现 colormap 矩阵类。让我们以一个名为“Spring”的自定义颜色映射为例,来说明创建自定义颜色映射的简单性。
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace Example1_8
{
public class ColorMap
{
private int colormapLength = 64;
private int alphaValue = 255;
public ColorMap()
{
}
public ColorMap(int colorLength)
{
colormapLength = colorLength;
}
public ColorMap(int colorLength, int alpha)
{
colormapLength = colorLength;
alphaValue = alpha;
}
public int[,] Spring()
{
int[,] cmap = new int[colormapLength, 4];
float[] spring = new float[colormapLength];
for (int i = 0; i < colormapLength; i++)
{
spring[i] = 1.0f * i / (colormapLength - 1);
cmap[i, 0] = alphaValue;
cmap[i, 1] = 255;
cmap[i, 2] = (int)(255 * spring[i]);
cmap[i, 3] = 255 - cmap[i, 1];
}
return cmap;
}
......
}
}
在此类中,有三个构造函数。如果您使用
ColorMap cm = new ColorMap();
来创建一个新的 ColorMap 对象,将使用默认参数 colormapLength = 64 和 alphaValue = 255。这里 colormapLength 是颜色映射矩阵的长度,alphaValue 是颜色透明度参数。默认的 alphaValue 255 表示不透明颜色。以下构造函数
ColorMap cm = new ColorMap(32);
用输入参数 32 覆盖 colormapLength,alphaValue 保持默认值 255。您可以通过调用 ColorMap 类及其以下代码片段来覆盖两个参数
COlorMap cm = new ColorMap(32, 100);
这将设置 colormapLength = 32 和 alphaValue = 100。
我在 ColorMap 类中添加了八个常用的自定义颜色映射。您可以按照此处描述的步骤轻松添加更多自定义颜色映射。
<h2>使用代码</h2>ColorMap 类可以在您的 C# 应用程序中使用。以下 Form1 类演示了如何使用 ColorMap 类绘制各种颜色条。以下是 Form1 类的代码片段
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Example1_8
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
SetStyle(ControlStyles.ResizeRedraw, true);
This.BackColor = Color.White;
this.Width = 340;
this.Height = 340;
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
int width = 30;
int height = 128;
int y = 10;
// 创建不透明颜色映射,alpha = 255
ColorMap cm = new ColorMap();
Font aFont = new Font("Arial", 20, FontStyle.Bold);
g.DrawString("OPAQUE COLOR", aFont, Brushes.Black, 10, 60);
DrawColorBar(g, 10, y, width, height, cm, "Spring");
DrawColorBar(g, 10 + 40, y, width, height, cm, "Summer");
DrawColorBar(g, 10 + 2 * 40, y, width, height, cm, "Autumn");
DrawColorBar(g, 10 + 3 * 40, y, width, height, cm, "Winter");
DrawColorBar(g, 10 + 4 * 40, y, width, height, cm, "Jet");
DrawColorBar(g, 10 + 5 * 40, y, width, height, cm, "Gray");
DrawColorBar(g, 10 + 6 * 40, y, width, height, cm, "Hot");
DrawColorBar(g, 10 + 7 * 40, y, width, height, cm, "Cool");
y = y + 150;
// 创建透明颜色映射,alpha = 150
ColorMap cm1 = new ColorMap(64, 150);
g.DrawString("TRANSPARENT COLOR", aFont, Brushes.Black, 10, 210);
DrawColorBar(g, 10, y, width, height, cm1, "Spring");
DrawColorBar(g, 10 + 40, y, width, height, cm1, "Summer");
DrawColorBar(g, 10 + 2 * 40, y, width, height, cm1, "Autumn");
DrawColorBar(g, 10 + 3 * 40, y, width, height, cm1, "Winter");
DrawColorBar(g, 10 + 4 * 40, y, width, height, cm1, "Jet");
DrawColorBar(g, 10 + 5 * 40, y, width, height, cm1, "Gray");
DrawColorBar(g, 10 + 6 * 40, y, width, height, cm1, "Hot");
DrawColorBar(g, 10 + 7 * 40, y, width, height, cm1, "Cool");
}
private void DrawColorBar(Graphics g, int x, int y,
int width, int height, ColorMap map, string str)
{
int[,] cmap = new int[64, 4];
switch(str)
{
case "Jet"
cmap = map.Jet();
break;
case "Hot"
cmap = map.Hot();
break;
case "Gray"
cmap = map.Gray();
break;
case "Cool"
cmap = map.Cool();
break;
case "Summer"
cmap = map.Summer();
break;
case "Autumn"
cmap = map.Autumn();
break;
case "Spring"
cmap = map.Spring();
break;
case "Winter"
cmap = map.Winter();
break;
}
int ymin = 0;
int ymax = 32;
int dy = height / (ymax - ymin);
int m = 64;
for (int i = 0; i < 32; i++)
{
int colorIndex = (int)((i - ymin) *
m / (ymax - ymin));
SolidBrush aBrush = new SolidBrush(Color.FromArgb(
cmap[colorIndex, 0], cmap[colorIndex, 1],
cmap[colorIndex, 2], cmap[colorIndex, 3]));
g.FillRectangle(aBrush, x, y + i * dy, width, dy);
}
}
}
}
在 DrawColorBar 方法中,我们通过将颜色条分成 32 个子矩形来绘制它。然后我们为 y 数据分配从 0 到 31 的值。switch 语句选择指定的颜色映射矩阵。以下代码片段
int colorIndex = (int)((i - ymin) * m / (ymax - ymin));
使用 Y 数据计算颜色映射矩阵的索引。然后我们使用此颜色映射矩阵创建一个 SolidBrush 对象。
在 OnPaint 方法中,我们创建了两个 ColorMap 对象,cm 和 cm1。cm 使用默认参数:colormapLength = 64 和 alphaValue = 255;即不透明颜色。cm1 的参数被重新指定为 colormapLength = 64 和 alphaValue = 150,这表示颜色变得透明。
此项目产生的结果如图所示,其中显示了 ColorMap 类中定义的八种不同的颜色映射。
这个项目来自新书《Practical C# Charts and Graphics》的示例,您可以在其中找到更多针对实际 .NET 应用程序的高级图表和图形编程。有关更多信息,请访问我的网站 www.authors.unicadpublish.com/~jack_xu
<h2>关于作者</h2>Jack Xu 博士拥有理论物理学博士学位。他在 Basic、Fortran、C、C++、Matlab 和 C# 方面拥有超过 15 年的编程经验,专注于数值计算方法、算法、物理建模、计算机辅助设计(CAD)开发、图形用户界面和 3D 图形。目前,他负责基于 Microsoft .NET 框架开发商业 CAD 工具。
请阅读我的其他文章