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

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);//保存图片
}
}

  再接再励,继续。

  

  

C#做上位机软件——绘图并传输给下位机的更多相关文章

  1. "废物利用"也抄袭——“完全”DIY"绘图仪"<二、下位机程序设计>

    就不说怎么组装了吧,一把辛酸泪.说程序,因为这有两把辛酸泪……一把给下位机的C代码一把为了VB.NET的图像处理……不过就上上一篇说的,它们可以正确运行了,并且今天克服了Arduino上电过程中步进电 ...

  2. [自娱自乐] 4、超声波测距模块DIY笔记(四)——终结篇·基于C#上位机软件开发

    前言 上一节我们已经基本上把超声波硬件的发射和接收模块全部做好了,接下来我们着手开发一个软硬结合的基于C#的平面定位软件! 目录 一.整体思路 二.效果提前展示 2-1.软件部分展示 2-2.硬件部分 ...

  3. 【安富莱原创开源应用第1期】花式玩转网络摄像头之TCP上位机软件实现,高端大气上档次,速度2MB/S,华丽丽的界面效果

    说明:1.例子是两年前做的,一直没有顾上整理出来,今天特地整理出来,开源出来给大家玩.2.上位机是emWin模拟器开发的,大家估计很难猜到,所以你会emWin话的,就可以轻松制作上位机.做些通信和控制 ...

  4. C++ MFC实现基于RFID读写器的上位机软件

    C++ MFC实现基于RFID读写器的上位机软件 该博客涉及的完整工程托管在https://github.com/Wsine/UpperMonitor,觉得好请给个Star (/▽\=) 运行和测试环 ...

  5. 开源串口 Ymodem 上位机软件

    概述 上位机使用Qt开发,计划整合多个工具为一体,用作以后的调试工具. 当前完成功能: 1.串口调试 支持hex和ascii 码发送,接受. 支持自动添加回车换行. 支持定时发送,最短间隔100ms, ...

  6. 我编写的EEPROM 上位机软件

    进入模式: 上位机发送 消息 上位机EEPROM 按下进入模式 消息的ID号是:0x08111111 数据是: 00 01 ff 00 00 00 00 00 上位机显示 运行状态 :为进入模式 当我 ...

  7. 8-ESP8266 SDK开发基础入门篇--编写串口上位机软件

    https://www.cnblogs.com/yangfengwu/p/11087558.html 咱用这个编写 ,版本都无所谓哈,只要自己有就可以,不同版本怎么打开 https://www.cnb ...

  8. 手机刷机软件与ROM的盈利模式分析

    一. 智能手机的兴起不过短短几年时间,更新迭代已经让实体键盘成为回忆.智能手机带来的是人们生活习惯的改变,对于手机的重度依赖,是好是坏不去评价.智能手机相对于之前的手机最大的改变不仅仅是屏幕的飞速变大 ...

  9. C# WPF上位机实现和下位机TCP通讯

    下位机使用北京大华程控电源DH1766-1,上位机使用WPF.实现了电压电流实时采集,曲线显示.上午在公司调试成功,手头没有程控电源,使用TCP服务端模拟.昨天写的TCP服务端正好排上用场. 界面如下 ...

随机推荐

  1. php截取中文无乱码

    在PHP中需要对字符串进行截取,如果没有装mb扩展(mb_substr函数),对中文截取就需要进行相应的处理.下面是对字符串 "世s界s的功s\\\夫萨的mn是非得失sdf dsf dsf ...

  2. js 闭包

    this.color = "blue"; (function(_this) { setInterval(function() { if (_this.color !== " ...

  3. kailli linux download

    https://www.offensive-security.com/kali-linux-arm-images/ Courses Certifications Online Labs Penetra ...

  4. coreseek安装过程

    一.sphinx 全文检索 通过sphinx检索到id,然后到mysql里面拿到记录 什么是劝我呢检索?结构化数据: 具有固定格式或者长度的数据非结构化数据: 标题 内容 等不定长的数据非机构化数据还 ...

  5. Java集合之HashMap

    1. HashMap概述: HashMap是基于哈希表的Map接口的非同步实现(Hashtable跟HashMap很像,唯一的区别是Hashtalbe中的方法是线程安全的,也就是同步的).此实现提供所 ...

  6. Spring,Mybatis 整合Memcache

    Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度.Memcached ...

  7. 面向科学计算的Python IDE--Anaconda

    1.下载 2.安装,假定路径为D:/Anaconda 3.在命令行中查看已安装的包及其版本 D: cd Anaconda conda list 结果: # packages in environmen ...

  8. knn-伪代码与实现过程

    knn特点 优点:精度高,对异常值不明感,无数据输入嘉定 缺点:计算复杂度高,空间复杂度高 适用范围:数值型和标称型 knn算法的伪代码 1.计算已知类别数据集中的点与当前之间的距离 2.按照距离递增 ...

  9. linux启动过程分析

    参考:http://blog.chinaunix.net/uid-26495963-id-3066282.html http://www.comptechdoc.org/os/linux/startu ...

  10. C++11中自定义range

    python中的range功能非常好用 for i in range(100): print(i) 现在利用C++11的基于范围的for循环特性实现C++中的range功能 class range { ...