研究了一下常用的套路:先创建一张灰度图像,一条渐变色带,然后根据灰度图像每个点的黑度(像素值)去渐变色带里面找对应的颜色,然后按像素给灰度图像上色。
常用的一个类:ColorMap
实例:
创建灰度图:
利用GDI+,白到黑渐变生成:
Bitmap bitmap2 = CreateIntensityMask2(new Bitmap((int)panel1.Width, (int)panel1.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb), HeatPoints);
panel1.BackgroundImage = bitmap2;
private Bitmap CreateIntensityMask2(Bitmap bitmap, List<HeatPoint> aHeatPoints)
{
//从Bitmap获得Graphics GDI+ 绘图图面
Graphics graphics = Graphics.FromImage(bitmap);
//清除整个绘图面并以白色填充
graphics.Clear(System.Drawing.Color.White);
PointF p1 = new PointF(0, 0);//p1点在(0,0)处
PointF p2 = new PointF(200, 300);//p2点在(800,500)处
Color c1 = Color.FromArgb(255, 255, 255);
Color c2 = Color.FromArgb(0, 0, 0);
var brush = new System.Drawing.Drawing2D.LinearGradientBrush(p1, p2, c1, c2);
graphics.FillRectangle(brush, 0, 0, 800, 500);
return bitmap;
}
效果:
创建色带:
第一种:
private void CreatePaletteImage()
{
List<Color> newColors = new List<Color>();
//颜色集合
newColors.AddRange(GetGradientColorList(Color.Red, Color.Yellow, 64));
newColors.AddRange(GetGradientColorList(Color.Yellow, Color.Green, 64));
newColors.AddRange(GetGradientColorList(Color.Green, Color.Blue, 64));
newColors.AddRange(GetGradientColorList(Color.Blue, Color.Navy, 64));
//颜色调色板展示
Bitmap colorBitmap = new Bitmap(colorPanel.Width, colorPanel.Height);
//从位图中获得GDI+对象
Graphics graphic = Graphics.FromImage(colorBitmap);
for (int i = 0; i < 256; i++)
{
SolidBrush solidBrush = new SolidBrush(newColors[i]);
Rectangle rectangle = new Rectangle((int)(i * 2), 0, (int)2, colorPanel.Height);
graphic.FillRectangle(solidBrush, rectangle);
graphic.Save();
solidBrush.Dispose();
}
colorPanel.BackgroundImage = colorBitmap;
}
效果:
把生成矩形宽度设为1会更明显:
Rectangle rectangle = new Rectangle((int)(i * 2), 0, (int)1, colorPanel.Height);
第二种:
private void CreateColorMap()
{
ColorBlend colorBlend = new ColorBlend(8);
colorBlend.Colors = new Color[10]
{
Color.FromArgb(0, 255, 0, 0), // 纯红
Color.FromArgb(20, 255, 0, 100),
Color.FromArgb(40, 200, 0, 150),
Color.FromArgb(60, 150, 0, 180), // 红紫色
Color.FromArgb(80, 100, 0, 200), // 紫蓝色
Color.FromArgb(100, 50, 50, 220),
Color.FromArgb(120, 0, 100, 230),
Color.FromArgb(140, 0, 150, 240),
Color.FromArgb(160, 0, 200, 250),
Color.FromArgb(180, 0, 255, 255) // 蓝青色
};
colorBlend.Positions = new float[10] { 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.75f, 0.9f, 1.0f };
Color startColor = colorBlend.Colors[0];
Color endColor = colorBlend.Colors[colorBlend.Colors.Length - 1];
using (Bitmap colorMapBitmap = new Bitmap(1000, 1, PixelFormat.Format32bppArgb))
{
Rectangle colorRect = new Rectangle(0, 0, colorMapBitmap.Width, colorMapBitmap.Height);
using (Graphics bitmapGraphics = Graphics.FromImage(colorMapBitmap))
{
using (LinearGradientBrush brush = new LinearGradientBrush(colorRect, startColor, endColor, LinearGradientMode.Horizontal))
{
brush.InterpolationColors = colorBlend;
bitmapGraphics.FillRectangle(brush, colorRect);
}
}
var image = new Bitmap(colorMapBitmap);
//显示
panel1.BackgroundImage = image;
BitmapData colorMapData = colorMapBitmap.LockBits(colorRect, ImageLockMode.ReadOnly, colorMapBitmap.PixelFormat);
colorMapBitmap.UnlockBits(colorMapData);
}
}
ColorBlend 会自动生成渐变色。
效果:
上色:
这里使用第一种色带
//上色
panel3.BackgroundImage = Colorize(bitmap2);
/// <summary>
/// 上色
/// </summary>
/// <param name="mask">灰度图</param>
/// <returns>彩色图</returns>
public Bitmap Colorize(Bitmap mask)
{
//创建新的位图,为上色做准备
Bitmap output = new Bitmap(mask.Width, mask.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
//同理,从Bitmap获得Graphics GDI+ 绘图图面
Graphics graphics = Graphics.FromImage(output);
//清除整个绘图面并以透明填充
graphics.Clear(System.Drawing.Color.Transparent);
// 构建一组颜色映射以将我们的灰度蒙版重新映射为全色
ColorMap[] colorMaps = CreatePalette();
// 创建新的图像属性类来处理颜色重新映射
// 注入我们的颜色映射数组来指示图像属性类如何进行着色
ImageAttributes imageAttr = new ImageAttributes();
imageAttr.SetRemapTable(colorMaps);
// 使用新的颜色映射方案将我们的蒙版绘制到我们的内存位图工作表面上
graphics.DrawImage(mask, new System.Drawing.Rectangle(0, 0, mask.Width, mask.Height), 0, 0, mask.Width, mask.Height, GraphicsUnit.Pixel, imageAttr);
return output;
}
//创建调色板,颜色映射
private ColorMap[] CreatePalette()
{
//此类定义现有颜色与要转换到的新颜色之间的映射。 应用地图时,旧颜色的任何像素都转换为新颜色。
ColorMap[] colorMaps = new ColorMap[256];
List<Color> newColors = new List<Color>();
//颜色集合
newColors.AddRange(GetGradientColorList(Color.Red, Color.Yellow, 64));
newColors.AddRange(GetGradientColorList(Color.Yellow, Color.Green, 64));
newColors.AddRange(GetGradientColorList(Color.Green, Color.Blue, 64));
newColors.AddRange(GetGradientColorList(Color.Blue, Color.Navy, 64));
//颜色调色板展示
Bitmap colorBitmap = new Bitmap(colorPanel.Width, colorPanel.Height);
Graphics graphic = Graphics.FromImage(colorBitmap);
for (int i = 0; i < 256; i++)
{
SolidBrush solidBrush = new SolidBrush(newColors[i]);
Rectangle rectangle = new Rectangle((int)(i * 2), 0, (int)2, colorPanel.Height);
graphic.FillRectangle(solidBrush, rectangle);
graphic.Save();
solidBrush.Dispose();
}
colorPanel.BackgroundImage = colorBitmap;
// 遍历每个像素颜色并创建一个新的颜色映射
for (int X = 0; X <= 255; X++)
{
colorMaps[X] = new ColorMap();
colorMaps[X].OldColor = System.Drawing.Color.FromArgb(X, X, X);//灰度就是没有色彩,RGB色彩分量全部相等
colorMaps[X].NewColor = System.Drawing.Color.FromArgb(255, newColors[X]);
}
return colorMaps;
}
解析:
colorMaps定义现有灰色与要转换到的新颜色之间的映射集合:
每一个映射的两个属性:
OldColor 对应灰度图像上的颜色;
NewColor 对应彩色色带上的颜色;
newColors是一个长度为256的颜色集合,就是色带上的颜色集合;
for (int X = 0; X <= 255; X++)
{
colorMaps[X] = new ColorMap();
//灰度就是没有色彩,RGB色彩分量全部相等
colorMaps[X].OldColor = System.Drawing.Color.FromArgb(X, X, X);//旧色
colorMaps[X].NewColor = System.Drawing.Color.FromArgb(255, newColors[X]);//新色
}
效果:
当然热力图没有这样的,上面只是为了展示相关功能。
要制作热力图,移步:C# .Net实现简易灰度图和酷炫HeatMap热力图winform(进阶)_c# 热力图-CSDN博客
「C#」生成HeatMap(热度图)的实现_c# 热力图-CSDN博客
--------------------------------------------------------------------------------------------------------
肯定学不完。用到的时候知道有这个东西就行了,目前是这样想的。欢迎讨论。