Enkelt histogram
Denne logikken går fram av følgende kode:
List<int> data=null;
public Form1()
{
InitializeComponent();
data = new List<int>(100);
}
private void buttonDaw_Click(object sender, EventArgs e)
{
String[] lines = textBox1.Text.Split('\r');
data=new List<int>(lines.Length);
try
{
foreach (string line in lines)
if (line.Trim().Length > 0)
data.Add(Convert.ToInt32(line.Trim()));
}
catch (Exception ex)
{
labelMsg.Text = "feil format";
}
// force a redraw
panel1.Invalidate();
}
private void panel1_Resize(object sender, EventArgs e)
{
// we force a redraw when panel is sized
panel1.Invalidate();
}
Vi kan lage bildet etter to strategier:
- Vi kan tegne i panelet, kopiere denne tegningen til en bitmap som vi så lagrer i det formatet vi ønsker
- Vi kan tegne direkte i en bitmap (ikke på skjermen), eventuelt kopiere til skjermen for å inspisere, og så lage bitmapen direkte.
Nedenfor finner du kode for begge strategiene
Tegne på skjermen
Vi tegner på skjermen, i panelet og kopierer til en bitmap som vi så lagrer.. Selve tegnerutina, drawData, er sitert mot slutten av modulen.
private void panel1_Paint(object sender, PaintEventArgs e)
{
// we draw on the panel and copy it to a bitmap
// then we save it
Rectangle Rec = new Rectangle(0, 0, panel1.Width, panel1.Height);
drawData(e.Graphics, Rec, data);
// copy the drawing to a bitmap
Bitmap canvas = new Bitmap(Rec.Width, Rec.Height);
Graphics bg = Graphics.FromImage(canvas);
// copy from screen, in screen coordinates
Rectangle screenR = panel1.RectangleToScreen(Rec);
bg.CopyFromScreen(new Point(screenR.X, screenR.Y),
new Point(0, 0),
new Size(screenR.Width,screenR.Height));
// save the drawing
canvas.Save(Path.Combine(Application.StartupPath, "bildetest.gif"));
}
Tegne direkte på en bitmap
Vi tegner til en bitmap og lagrer den. I eksempelet kopierer vi bitmapen til skjermen for å inspisere, men det er ikke nødvendig for å lage bildet..
private void panel1_Paint(object sender, PaintEventArgs e)
{
// we draw on a bitmap and copies this bitmap to the panel
// then we save it
Rectangle Rec = new Rectangle(0, 0, panel1.Width, panel1.Height);
Bitmap canvas = new Bitmap(Rec.Width, Rec.Height);
Graphics cg = Graphics.FromImage(canvas);
// set white background
cg.FillRectangle(Brushes.White,Rec);
drawData(cg, Rec,data);
// copy the drawing to the panel
e.Graphics.DrawImage(canvas,new Point(0,0));
// save the drawing
canvas.Save(Path.Combine(Application.StartupPath, "bildetest.gif"));
}
Selve uttegningen er gjort slik:
// draw data within Rec on g
private void drawData(Graphics g,Rectangle Rec,List<int>data)
{
Font tFont = new Font("Arial", 16);
SolidBrush blueBrush = new SolidBrush(Color.Blue);
// any data to display
if (data.Count == 0)
{
g.DrawString(" Ingen data ",
tFont,
blueBrush,
new Point(10, 4));
}
else
{
// find max value
float max = 0.0F;
foreach (int number in data)
max = Math.Max((float)number, max);
// Width of each column, with some margins
int w =
(Rec.Width - 10 * data.Count - 20) / data.Count;
// flip round top and leave some room at top for text
int txtheight = 20;
g.ResetTransform();
g.TranslateTransform(0.0F, Rec.Height);
g.ScaleTransform(1.0F,
-1.0F * ((Rec.Height - txtheight) / (max + 1)));
for (int ix = 0; ix < data.Count; ix++)
{
g.FillRectangle(Brushes.Red,
new Rectangle(10 + ix * (w + 10), 0, w, data[ix]));
}
// text it
g.ResetTransform();
g.DrawString("Resultater", tFont, blueBrush, new Point(10, 4));
}
g.Flush();
}
Dette kan selvsagt gjøre på mange forskjellige måter. I slik enkle tilfeller som dette kan det kanskje være en avveining om vi skal tegne direkte i pikselkoordinater eller om vi skal transformere fra et annet koordinatsystem slik jeg har gjort.
Hvis du studerer "System.Drawing.Imaging.ImageFormat" i dokumentasjonen vil du finne at du kan spare bitmaps i en rekke andre formater enn gif.



