C#做上位机软件——绘图并传输给下位机

拿到任务之后首先分成了几个部分:

1.绘图。学习了GDI+

2.图片保存。

3.将图片转换成byte[]。由于使用Socket通信,只能传输byte[]数据,所以这一步是向下位机传输的关键。

相应地,编程实现了下面几个功能:

1.使用GDI+画图并保存为bmp格式的图片。画图部分是书上的例子,只增加了保存的相应代码。

public partial class Form1 : Form
    {
        Bitmap bitmap;
        Font myFont = new Font("Arial", 12, FontStyle.Bold);//定义字符串的样式
        Rectangle ret = new Rectangle(10, 10, 160, 160);//实例化
        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 = 0;//圆的直径
            int ci_L = 4;//画笔
            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 * 2, tem_Line - ci_L * 2);
            Font Star_font = new Font("Arial", 30, 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 = 180 + (180 - len * 20) / 2;

            for (int i = 0; i < len; i++)//将文字以指定的弧度进行绘制
            {
                g.TranslateTransform((tem_Line + ci_L / 2) / 2, (tem_Line + ci_L / 2) / 2);
                g.RotateTransform(angle);//将指定的旋转用于Graphics类的变换矩阵??????????????
                Brush myBrush = Brushes.Red;
                g.DrawString(tem.Substring(i, 1), myFont, myBrush, 60, 0);
                g.ResetTransform();//将Graphics类的全局变换矩阵重置为单位矩阵?????????
                angle += 20;//设置下一个文字的角度
            }
            bitmap.Save(@"D:\myImage123.bmp", ImageFormat.Bmp);
        }
    }
View Code

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=2*Math.PI/T;           
            double x, y1, y2;
            PointPairList list1 = new PointPairList();//定义坐标数组
            PointPairList list2 = new PointPairList();
            for (int i = 0; i < 36; 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(22, 130);//20 
            zedGraphControl1.Size = new Size(ClientRectangle.Width-44,ClientRectangle.Height-170);//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);//保存图片
        }       
    }
View Code

  再接再励,继续。

  

 

 

 

  

posted @ 2014-07-22 14:38  TryTryTryTry  阅读(2206)  评论(0编辑  收藏  举报