拿到任务之后首先分成了几个部分:
1.绘图。学习了GDI+
2.图片保存。
3.将图片转换成byte[]。由于使用Socket通信,只能传输byte[]数据,所以这一步是向下位机传输的关键。
相应地,编程实现了下面几个功能:
1.使用GDI+画图并保存为bmp格式的图片。画图部分是书上的例子,只增加了保存的相应代码。
public partial class Form1 : Form
{
Bitmap bitmap;
Font myFont = new Font("Arial", , FontStyle.Bold);//定义字符串的样式
Rectangle ret = new Rectangle(, , , );//实例化
public Form1()
{
InitializeComponent();
} private void button1_Click(object sender, EventArgs e)
{
bitmap = new Bitmap(panel1.Width, panel1.Height);//用于保存
this.panel1.BackgroundImage = bitmap; int tem_Line = ;//圆的直径
int ci_L = ;//画笔
if (panel1.Width >= panel1.Height)
{
tem_Line = panel1.Height;
}
else
tem_Line = panel1.Width;
ret = new Rectangle(ci_L, ci_L, tem_Line - ci_L * , tem_Line - ci_L * );
Font Star_font = new Font("Arial", , FontStyle.Regular);
string star_str = "*"; Graphics g = Graphics.FromImage(bitmap);
//Graphics g = this.panel1.CreateGraphics();//实例化画图类
g.SmoothingMode = SmoothingMode.AntiAlias;//消除绘制的锯齿,作用比较明显
g.Clear(Color.White);//以白色清空panel1控件的背景
Pen myPen = new Pen(Color.Red, ci_L);//定义画笔
g.DrawEllipse(myPen, ret);//画椭圆(绘制圆) SizeF mySize = new SizeF(ret.Width, ret.Width);//实例化SizeF类 存储有序浮点数对,通常为矩形的宽度和高度。
mySize = g.MeasureString(star_str, Star_font);//对指定字符串进行测量(测量什么??????)
g.DrawString(star_str, Star_font, myPen.Brush, new PointF((ret.Width / 2F) + ci_L - mySize.Width / 2F,
ret.Height / 2F - mySize.Width / 2F));//在指定的位置绘制 mySize = g.MeasureString("专用", myFont);
g.DrawString("专用", myFont, myPen.Brush, new PointF((ret.Width / 2F) + ci_L - mySize.Width / 2F,
ret.Height / 2F + mySize.Width / 2F));//在指定的位置绘制
string tem = "testing";
int len = tem.Length;
float angle = + ( - len * ) / ; for (int i = ; i < len; i++)//将文字以指定的弧度进行绘制
{
g.TranslateTransform((tem_Line + ci_L / ) / , (tem_Line + ci_L / ) / );
g.RotateTransform(angle);//将指定的旋转用于Graphics类的变换矩阵??????????????
Brush myBrush = Brushes.Red;
g.DrawString(tem.Substring(i, ), myFont, myBrush, , );
g.ResetTransform();//将Graphics类的全局变换矩阵重置为单位矩阵?????????
angle += ;//设置下一个文字的角度
}
bitmap.Save(@"D:\myImage123.bmp", ImageFormat.Bmp);
}
}
2.将图片转换成byte[]
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Bitmap bitmap;
byte[] imageBytes;
MemoryStream ms;
private void button1_Click(object sender, EventArgs e)//打开图片
{
openFileDialog1.Filter = "*.bmp|*.bmp";
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
if (bitmap != null)
bitmap.Dispose();
string fileName = openFileDialog1.FileName;
bitmap = new Bitmap(fileName);
/*if (bitmap.Width > bitmap.Height)//如果 图片 的宽度大于高度
{
pictureBox1.Width = panel1.Width;//设置控件的宽度
pictureBox1.Height = (int)((double)bitmap.Height * panel1.Width / bitmap.Width);
}
else
{
pictureBox1.Height = panel1.Width;
pictureBox1.Width = (int)((double)bitmap.Height * panel1.Width / bitmap.Width);
}*/
pictureBox1.Image = bitmap;//显示图片 }
} private void button2_Click(object sender, EventArgs e)
{
Image myImage = bitmap;//注意
ms = new MemoryStream();
imageBytes = new byte[ms.Length];//关于字节数组大小!!!!
myImage.Save(ms,ImageFormat.Gif);//存储到流
imageBytes=ms.ToArray();//将转换之后的结果赋值
richTextBox1.AppendText("长度:" + imageBytes.Length);
foreach (byte b in imageBytes)
{
richTextBox1.AppendText("转换之后的数据:" + b+"\r\n");
}
} private void button3_Click(object sender, EventArgs e)
{
MemoryStream ms = new MemoryStream(imageBytes);
Image returnImage = Image.FromStream(ms);
pictureBox2.Image= returnImage;//显示图片
}
}
至此,绘图、保存、转换都已经正确实现。
回归到最初的任务:画正弦函数曲线,并将数据传输给下位机(ARM),经下位机处理后将数据传回,并显示。要求上位机在画曲线时用户可以改变参数(这里设定的可变参数有幅度、周期、初相),参数改变就意味着有参照,而不是单一画出正弦函数图形,所以,必须添加坐标。最初研究添加坐标时,考虑的无非就是画坐标线,然后添加图形,但是这样的效果是无法将坐标与图形联系起来。为解决此问题,考虑了两种方案:固定坐标线,调整图像与坐标线建立联系;固定图形,让坐标去适应图形。这里需要说明的是,此时我考虑的这种所谓“坐标线”只是根据绘图区大小而画的直线,并非实际意义上的坐标系!当然这两种方案都没有实现,因为在研究过程中关注到了另外的组件:zedGraph。所以接下来的实现已经转移到这上面。
目前的效果:在zedGraph中绘制参数可变的正弦函数图像(含参考图像),然后保存为bmp格式的图片。这样加入之前将图片转换为byte[]的代码,然后将数据传输给下位机,就大功告成了!
兴奋时间还没有超过十秒钟,我就意识到自己从开始就绕了一个大圈:将数据传输给下位机并令下位机处理的,是指什么数据?仔细思考,有两种可能:
1、是列表中的坐标点,这样才能将处理之后的数据返回并再次显示,并非图片。
2、确实是图片,但即使是图片也不可能将转换之后的byte[]整个处理,因为这之间必然包含各种信息,如果不了解这些信息,如何告知下位机处理哪些数据,保留哪些数据?换句话说,也就是包含传输中数据格式的问题。
总之,无论如何,距离最后的结果还有距离。
Anyway 先将这段代码附上:
public partial class Form1 : Form
{
//private bool flag;
public Form1()
{
InitializeComponent();
} /*private void Form1_Paint(object sender, PaintEventArgs e)
{
if (flag)
{
CreateGraph(zedGraphControl1);
SetSize();
flag = false;
}
}
* */
private void button1_Click(object sender, EventArgs e)
{
//flag = true;
SetSize();
CreateGraph(zedGraphControl1);
} private void CreateGraph(ZedGraphControl zgc)
{
GraphPane myPane = zgc.GraphPane;
myPane.Clear();//消除上次痕迹
myPane.Title.Text = "正弦函数";
myPane.XAxis.Title.Text = "横坐标";
myPane.YAxis.Title.Text = "竖坐标"; //获取用户设定的数据
int T = Int32.Parse(numericUpDown1 .Text);//周期
int A = Int32.Parse(numericUpDown2.Text);//幅度
int B = Int32.Parse(numericUpDown3.Text);//初相
double w=*Math.PI/T;
double x, y1, y2;
PointPairList list1 = new PointPairList();//定义坐标数组
PointPairList list2 = new PointPairList();
for (int i = ; i < ; i++)//逐一描点画图
{
x = (double)i ;//从坐标原点开始
//y1 = 1.5 + Math.Sin((double)i * 0.2);
y1 = A*Math.Sin((double)i * w+B);
//y2 = 3.0 * (1.5 + Math.Sin((double)i * 0.2));
y2 =3.0*(Math.Sin((double)i * 0.1*Math.PI));//作为研究的参考图形
list1.Add(x, y1);
list2.Add(x, y2);
} // Generate a red curve with diamond
// symbols, and "Porsche" in the legend
LineItem myCurve = myPane.AddCurve("Sin()",
list1, Color.Red, SymbolType.Diamond); // Generate a blue curve with circle
// symbols, and "Piper" in the legend
LineItem myCurve2 = myPane.AddCurve("参考",
list2, Color.Blue, SymbolType.Circle); // Tell ZedGraph to refigure the
// axes since the data have changed
zgc.AxisChange(); //发送WM_PAINT消息放在应用程序的消息队列中,WM_PAINT消息的优先级很低,所以不会立即重绘
//zgc.Invalidate();//使窗口客户区无效,这样就需要重绘,
zgc.Refresh();//刷新显示 } private void Form1_Resize(object sender, EventArgs e)
{
//使控件大小随窗口大小改变而改变。是必要的
SetSize();
}
private void SetSize()
{
zedGraphControl1.Location = new Point(, );//20
zedGraphControl1.Size = new Size(ClientRectangle.Width-,ClientRectangle.Height-);//ClientRectangle.Width-22, ClientRectangle.Height-129);//20 20
//MessageBox.Show(ClientRectangle.Height.ToString() + "h w" + ClientRectangle.Width.ToString());
} private void button2_Click(object sender, EventArgs e)//保存图片
{
zedGraphControl1.Refresh();//刷新图片
pictureBox1.Image = zedGraphControl1.GetImage();//提取图片
pictureBox1.Image.Save(@"D:\myImage00.bmp", ImageFormat.Bmp);//保存图片
}
}
再接再励,继续。