当前位置: 首页 > news >正文

Winform C# 热力图制作要点

 研究了一下常用的套路:先创建一张灰度图像,一条渐变色带,然后根据灰度图像每个点的黑度(像素值)去渐变色带里面找对应的颜色,然后按像素给灰度图像上色。

常用的一个类:ColorMap

https://learn.microsoft.com/zh-cn/dotnet/api/system.drawing.imaging.colormap?view=windowsdesktop-9.0&redirectedfrom=MSDN

 实例:

创建灰度图:

利用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博客 

--------------------------------------------------------------------------------------------------------

肯定学不完。用到的时候知道有这个东西就行了,目前是这样想的。欢迎讨论。 

 

http://www.dtcms.com/a/308856.html

相关文章:

  • HOOPS Exchange技术架构全解析:打造高效CAD/BIM数据导入与导出引擎
  • 【go】格式化的输入和输出
  • 计算机网络知识【推荐!!!】按照OSI七层模型梳理
  • BGP高级特性之GTSM实验案例
  • 蓝牙数据包解析
  • mapper.xml中的<include>是什么
  • 【React】状态管理
  • Spring 面试点(八股)
  • review| advance
  • wxPython 实践(五)高级控件
  • 企业对于DDOS攻击有哪几种安全防护对策?
  • 选择跨网文件交换系统的核心因素有哪些?
  • Kafka Streams性能优化实践指南:实时流处理与状态管理
  • 脚手架搭建React项目
  • LCGL基本使用
  • 智慧园区通行效率↑68%!陌讯多模态融合算法的实战解析
  • 【C++】1·入门基础
  • C语言基础第18天:动态内存分配
  • 什么是 MySQL 的索引?常见的索引类型有哪些?
  • 【动态规划】数位dp
  • 【AD】域管理员登录错误
  • Google政策大更新:影响金融,Ai应用,社交,新闻等所有类别App
  • 王道考研-数据结构-01
  • Qt_Gif_Creator 基于Qt的屏幕gif录制工具
  • 汽车线束行业AI智能化MES解决方案:推动智能制造与质量升级
  • cpu运行 kokoro tts 服务器语音转化首选
  • 为什么 Batch Normalization 放在全连接/卷积层的输出之后?
  • linux如何将两份hdmi edid合并
  • 硬件电路基础学习
  • Cesium 快速入门(五)坐标系