1.前言
用C#所繪製的圖表中加入色彩條圖例顯示,用以區分數值大小。
2.說明
ColorMap的類別可參考codeproject的"Create Custom Color Maps in C#"說明
http://www.codeproject.com/Articles/18150/Create-Custom-Color-Maps-in-C
測試資料是由R導出的資料集,輸出檔案格式為CSV
df <- data.frame(x=rnorm(10000),y=rnorm(10000))
write.table(df,file='d:/temp/sim.csv',row.names=FALSE,sep=',')
ColorMap類別
public class ColorMap
{
private int colormapLength = 255;
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;
}
public int[,] Summer()
{
int[,] cmap = new int[colormapLength, 4];
float[] summer = new float[colormapLength];
for (int i = 0; i < colormapLength; i++)
{
summer[i] = 1.0f * i / (colormapLength - 1);
cmap[i, 0] = alphaValue;
cmap[i, 1] = (int)(255 * summer[i]);
cmap[i, 2] = (int)(255 * 0.5f * (1 + summer[i]));
cmap[i, 3] = (int)(255 * 0.4f);
}
return cmap;
}
public int[,] Autumn()
{
int[,] cmap = new int[colormapLength, 4];
float[] autumn = new float[colormapLength];
for (int i = 0; i < colormapLength; i++)
{
autumn[i] = 1.0f * i / (colormapLength - 1);
cmap[i, 0] = alphaValue;
cmap[i, 1] = 255;
cmap[i, 2] = (int)(255 * autumn[i]);
cmap[i, 3] = 0;
}
return cmap;
}
public int[,] Winter()
{
int[,] cmap = new int[colormapLength, 4];
float[] winter = new float[colormapLength];
for (int i = 0; i < colormapLength; i++)
{
winter[i] = 1.0f * i / (colormapLength - 1);
cmap[i, 0] = alphaValue;
cmap[i, 1] = 0;
cmap[i, 2] = (int)(255 * winter[i]);
cmap[i, 3] = (int)(255 * (1.0f - 0.5f * winter[i]));
}
return cmap;
}
public int[,] Gray()
{
int[,] cmap = new int[colormapLength, 4];
float[] gray = new float[colormapLength];
for (int i = 0; i < colormapLength; i++)
{
gray[i] = 1.0f * i / (colormapLength - 1);
cmap[i, 0] = alphaValue;
cmap[i, 1] = (int)(255 * gray[i]);
cmap[i, 2] = (int)(255 * gray[i]);
cmap[i, 3] = (int)(255 * gray[i]);
}
return cmap;
}
public int[,] Jet()
{
int[,] cmap = new int[colormapLength, 4];
float[,] cMatrix = new float[colormapLength, 3];
int n = (int)Math.Ceiling(colormapLength / 4.0f);
int nMod = 0;
float[] fArray = new float[3 * n - 1];
int[] red = new int[fArray.Length];
int[] green = new int[fArray.Length];
int[] blue = new int[fArray.Length];
if (colormapLength % 4 == 1)
{
nMod = 1;
}
for (int i = 0; i < fArray.Length; i++)
{
if (i < n)
fArray[i] = (float)(i + 1) / n;
else if (i >= n && i < 2 * n - 1)
fArray[i] = 1.0f;
else if (i >= 2 * n - 1)
fArray[i] = (float)(3 * n - 1 - i) / n;
green[i] = (int)Math.Ceiling(n / 2.0f) - nMod + i;
red[i] = green[i] + n;
blue[i] = green[i] - n;
}
int nb = 0;
for (int i = 0; i < blue.Length; i++)
{
if (blue[i] > 0)
nb++;
}
for (int i = 0; i < colormapLength; i++)
{
for (int j = 0; j < red.Length; j++)
{
if (i == red[j] && red[j] < colormapLength)
{
cMatrix[i, 0] = fArray[i - red[0]];
}
}
for (int j = 0; j < green.Length; j++)
{
if (i == green[j] && green[j] < colormapLength)
cMatrix[i, 1] = fArray[i - (int)green[0]];
}
for (int j = 0; j < blue.Length; j++)
{
if (i == blue[j] && blue[j] >= 0)
cMatrix[i, 2] = fArray[fArray.Length - 1 - nb + i];
}
}
for (int i = 0; i < colormapLength; i++)
{
cmap[i, 0] = alphaValue;
for (int j = 0; j < 3; j++)
{
cmap[i, j + 1] = (int)(cMatrix[i, j] * 255);
}
}
return cmap;
}
public int[,] Hot()
{
int[,] cmap = new int[colormapLength, 4];
int n = 3 * colormapLength / 8;
float[] red = new float[colormapLength];
float[] green = new float[colormapLength];
float[] blue = new float[colormapLength];
for (int i = 0; i < colormapLength; i++)
{
if (i < n)
red[i] = 1.0f * (i + 1) / n;
else
red[i] = 1.0f;
if (i < n)
green[i] = 0f;
else if (i >= n && i < 2 * n)
green[i] = 1.0f * (i + 1 - n) / n;
else
green[i] = 1f;
if (i < 2 * n)
blue[i] = 0f;
else
blue[i] = 1.0f * (i + 1 - 2 * n) / (colormapLength - 2 * n);
cmap[i, 0] = alphaValue;
cmap[i, 1] = (int)(255 * red[i]);
cmap[i, 2] = (int)(255 * green[i]);
cmap[i, 3] = (int)(255 * blue[i]);
}
return cmap;
}
public int[,] Cool()
{
int[,] cmap = new int[colormapLength, 4];
float[] cool = new float[colormapLength];
for (int i = 0; i < colormapLength; i++)
{
cool[i] = 1.0f * i / (colormapLength - 1);
cmap[i, 0] = alphaValue;
cmap[i, 1] = (int)(255 * cool[i]);
cmap[i, 2] = (int)(255 * (1 - cool[i]));
cmap[i, 3] = 255;
}
return cmap;
}
}
資料轉成DataTable
public DataTable TxtConvertToDataTable(string File, string TableName, string delimiter)
{
DataTable dt = new DataTable();
DataSet ds = new DataSet();
StreamReader s = new StreamReader(File, System.Text.Encoding.Default);
//string ss = s.ReadLine();//skip the first line
string[] columns = s.ReadLine().Split(delimiter.ToCharArray());
ds.Tables.Add(TableName);
foreach (string col in columns)
{
bool added = false;
string next = "";
int i = 0;
while (!added)
{
string columnname = col + next;
columnname = columnname.Replace("#", "");
columnname = columnname.Replace("'", "");
columnname = columnname.Replace("&", "");
if (!ds.Tables[TableName].Columns.Contains(columnname))
{
ds.Tables[TableName].Columns.Add(columnname.ToUpper());
added = true;
}
else
{
i++;
next = "_" + i.ToString();
}
}
}
string AllData = s.ReadToEnd();
string[] rows = AllData.Split("\n".ToCharArray());
foreach (string r in rows)
{
string[] items = r.Split(delimiter.ToCharArray());
ds.Tables[TableName].Rows.Add(items);
}
s.Close();
dt = ds.Tables[0];
return dt;
}
繪圖
private void DrawChart(DataTable dt, ColorMap map, Graphics g, float min, float max)
{
int[,] cmap = new int[254, 4];
cmap = map.Jet();
int m = 254;
for (int i = 0; i < dt.Rows.Count; i++)
{
float posx = float.Parse(dt.Rows[i]["x"].ToString());
float posy = float.Parse(dt.Rows[i]["y"].ToString());
float val = float.Parse(dt.Rows[i]["y"].ToString());
int colorIndex = (int)((val - min) * m / (max - min));
SolidBrush s = new SolidBrush(Color.FromArgb(cmap[colorIndex, 0], cmap[colorIndex, 1], cmap[colorIndex, 2], cmap[colorIndex, 3]));
RectangleF rec = new RectangleF(posx, posy, 5, 5);
g.FillEllipse(s, rec);
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
s.Dispose();
}
}
加入色彩條圖例顯示
private void DrawColorBar(Graphics g, int x, int y, int width, int height, float min, float max, ColorMap map)
{
int[,] cmap = new int[254, 4];
cmap = map.Jet();
int bmin = 0;
int bmax = height;
int dy = (bmax - bmin) / height;
int m = 254;
for (int i = 0; i < bmax; i++)
{
int colorIndex = (int)((i - bmin) * m / (bmax - bmin));
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);
}
//在Color bar上加入刻度線與標籤
float ticklength = 0.3f * width;
Pen p = new Pen(Color.Black, 1);
StringFormat sFormat = new StringFormat();
sFormat.Alignment = StringAlignment.Near;
SizeF size = g.MeasureString("T", new Font("Arial", 7, FontStyle.Regular, GraphicsUnit.Pixel));
g.DrawLine(p, x + width, y + height, x + width, y);
for (float i = min; i <= max; i += (max - min) / 6)
{
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
float yy = y + height - (i - min) * height / (max - min);
g.DrawLine(p, x + width + 5, yy, x + width - ticklength + 5, yy);
g.DrawString((Math.Round(i, 2)).ToString(), new Font("Arial", 7), Brushes.Black, new PointF(x + width + 5, yy - size.Height / 2), sFormat);
}
}
3.應用
private void btPlot_Click(object sender, EventArgs e)
{
//讀取數值資料
DataTable dt = TxtConvertToDataTable(@"D:\Temp\sim.csv", "tmp", ",");
for (int i = 0; i < dt.Rows.Count; i++)
{
dt.Rows[i]["x"] = (double.Parse(dt.Rows[i]["x"].ToString()) * 50 + 250).ToString();
dt.Rows[i]["y"] = (double.Parse(dt.Rows[i]["y"].ToString()) * 50 + 250).ToString();
}
//計算繪圖區數值的最大值與最小值
float max = float.MinValue;
float min = float.MaxValue;
for (int i = 0; i < dt.Rows.Count; i++)
{
if (dt.Rows[i]["y"].ToString() != "")
{
float _value = float.Parse(dt.Rows[i]["y"].ToString());
if (max < _value) max = _value;
if (min > _value) min = _value;
}
}
//新增Bitmap影像
Image img = new Bitmap(500, 500);
//在image上繪圖
Graphics g = Graphics.FromImage(img);
//建立ColorMap類別實例化
ColorMap map = new ColorMap();
//繪圖
DrawChart(dt, map, g, min, max);
//繪製色彩條圖例
DrawColorBar(g, 450, 50, 15, 400, min, max, map);
//顯示影像檔
pictureBox1.Image = img;
}
圖例
文章標籤
全站熱搜

大神,请问怎样用这种方法将bitmap图像转换成你这种图例形式,多谢!