I am trying to create a heat map with gradients that look similar to this:
This image shows three points and the gradients blend nicely together.
Here is what I am currently doing in my drawing function:
public void DrawGradient(int x, int y, Graphics g) {
using (var ellipsePath = new GraphicsPath()) {
var bounds = new Rectangle(x, y, 100, 100);
ellipsePath.AddEllipse(bounds);
var brush = new PathGradientBrush(ellipsePath);
Color[] colors = {
Color.FromArgb(64, 0, 0, 255),
Color.FromArgb(140, 0, 255, 0),
Color.FromArgb(216, 255, 255, 0),
Color.FromArgb(255, 255, 0, 0)
};
float[] relativePositions = {0f,0.25f,0.5f, 1.0f};
ColorBlend colorBlend = new ColorBlend();
colorBlend.Colors = colors;
colorBlend.Positions = relativePositions;
brush.InterpolationColors = colorBlend;
g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
g.FillEllipse(brush, bounds);
}
}
Which creates an image like this for two overlapping points:
It does not blend. How can I create a gradient blending effect in a .NET drawing?
The color gradient heat map option is used to colorize the intensity of the heatmap. The following are some examples of color gradients that you may find useful.
A minimalist heatmap function Color colorOfYourDataPoint = Color(value*255, value*255, value*255); // Single line of code (the one above we had to do anyway).
Yes this is possible with < 100 lines of .NET and GDI+ drawing code..:
You need to change these things in your code:
Here are the details:
You need two gradients:
The grayscale one goes from Black (255,0,0,0) to transparent Black (0,0,0,0). You can influence the smoothness by making the transparent end fade out faster or slower.
The color gradient enumerates your heatmap colors.
Next you need one or more bitmaps with the blurred gray circles. If the point areas are all the same, one will do..
Now you can draw the bitmaps onto the target bitmap. Make sure to set the Graphics.CompositingMode = CompositingMode.SourceOver;
This results in something like the left screenshot.
Finally you need to Remap the colors:
For this you need to set up the ColorMaps:
ColorBlend.Colors
as you like.The color lists can be created by filling a 256x1 pixel Bitmap
with a LinearGradientBrush
that uses the same two respective ColorBlends
and then using GetPixel
to pull out the colors..
After doing a SetRemapTable
we can finally draw the heatmap, and voila, the right screenshot is rather similar, even without any tweaking to get real close to your heatmap.
Your code
Here are a few remarks on the flaws in your code:
Here is the grayscale gradient I used, with a photoshop-style checkerboard background, so you can see the transparency:
Another problem with your colors is that they start with blue; they really need to start with white!
The most fundamental problem is the blending of colors. For a 'heat map', (or a 'profile map' or a 'displacement map') we need to add up the values, not mix them. For this the color channels are useless. Colors are circular and they do not naturally lend themselves to a list of ascending values. If we use the alpha channel only, we can in a simple way limit the map to a 'brightness map', which we can then color in any way we like..
Note that I have assumed that the center points are to be maxima. If they are not, you need to scale them down to a lower alpha so that adding them up doesn't overflow..
Also note, that for really important applications, like medical or scientific imaging, you should go all the way to calculate the values, so you have full control of the mapping!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With