1.先上样图

软件在用户交互方面未做完善 ,后续会逐步完善。

代码已经同步到Github,欢迎下载使用,但是请注明出处。

Github地址:https://github.com/zhouchen/zhouchen.chart

2.软件基本构想

软件加载图片后,先做计算,给matrix赋值,使得图片大小适合窗口,然后居中显示。图片大小适合窗口,是对图像进行第一次缩放,代码如下:

        // 缩放图片到窗口能刚好展示完全public void AdaptView(){if (_bitmap == null){return;}using (var graphPath = new GraphicsPath()){graphPath.AddRectangle(_rcImg);graphPath.Transform(_matrix);PointF[] pointFs = graphPath.PathPoints;float fxmin = pointFs[0].X;float fymin = pointFs[0].Y;float fxmax = pointFs[0].X;float fymax = pointFs[0].Y;foreach (var pt in pointFs){if (pt.X < fxmin){fxmin = pt.X;}else if (pt.X > fxmax){fxmax = pt.X;}if (pt.Y < fymin){fymin = pt.Y;}else if (pt.Y > fymax){fymax = pt.Y;}}float fWidth = fxmax - fxmin;float fHeight = fymax - fymin;if (fWidth * rcBgArea.Height < fHeight * rcBgArea.Width){DScale = rcBgArea.Height / fHeight;}else{DScale = rcBgArea.Width / fWidth;}_matrix.Scale((float)DScale, (float)DScale, MatrixOrder.Append);}}

先计算图像进行矩阵变换后的最小外接矩形(图片刚加载的时候,其实外接矩形就是图片本身的尺寸,这里未了考虑之后图片进行矩阵变换后,想要重新恢复到能窗口显示,所以要进行矩阵变换的计算),然后计算相应的缩放比例,并设置到变换矩阵中。

缩放之后就要对图像进行第一次平移,这样能实现在窗口居中,代码如下:

        // 平移图片到窗口的中间public void TranslationCenter(){if(_bitmap == null){return;}Matrix matrixinv = _matrix.Clone();matrixinv.Invert();Point[] ptViewCenter = new Point[] { new Point(rcBgArea.Left + rcBgArea.Width / 2, rcBgArea.Top + rcBgArea.Height / 2) };matrixinv.TransformPoints(ptViewCenter);_matrix.Translate(ptViewCenter[0].X - _rcImg.Width / 2, ptViewCenter[0].Y - _rcImg.Height / 2);this.Refresh();}

这里的思路就要和缩放有点逆向,因为平移是平移图片,显示窗口的中心坐标要先换算成图片坐标系的点的坐标,所以要先将窗口中心点的坐标通过逆矩阵,计算出相对与图片坐标系的坐标,然后进行相应的计算赋值,才可以完成图像的平移。

缩放平移后,就是需要展示。展示采用GDI+的双缓冲技术。代码如下:

        private void ChartView_Paint(object sender, PaintEventArgs e){Graphics graph = e.Graphics;graph.SmoothingMode = SmoothingMode.HighQuality;// 双缓冲绘图Bitmap bmpChartView = new Bitmap(this.Width, this.Height);Graphics bmpChartView_g = Graphics.FromImage(bmpChartView);bmpChartView_g.SmoothingMode = SmoothingMode.HighQuality;DrawView(bmpChartView_g);graph.DrawImage(bmpChartView, 0, 0);bmpChartView_g.Dispose();bmpChartView.Dispose();}

因为之前设置好了_matrix,所以绘图就变得简单多了,只需要将矩阵设置到Graphics即可,代码如下:

        // 绘图private void DrawView(Graphics graph){DrawMainView(graph);DrawScrollV(graph);DrawScrollH(graph);}// 绘制图片展示区private void DrawMainView(Graphics graph){// 填充背景graph.FillRectangle(_ImgBg, rcBgArea);if (_bitmap == null){return;}Bitmap bitImg = new Bitmap(_rcImg.Width, _rcImg.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);Graphics bitImg_g = Graphics.FromImage(bitImg);bitImg_g.Transform = _matrix;bitImg_g.DrawImage(_bitmap, 0, 0, _bitmap.Width, _bitmap.Height);graph.DrawImage(bitImg, rcBgArea.Left, rcBgArea.Top, bitImg.Width, bitImg.Height);foreach(var chart in LstChart){chart.DrawChart(graph, _matrix);}bitImg_g.Dispose();bitImg.Dispose();}

值得注意的是,我还会在图片上绘制一些图形,如果在绘制图片之后,然后在图片上绘制图形,那么图形的线条宽度会随着图片的缩放进行相应的缩放,但是如果是在绘图Graphics上绘制的话,那就不会了,这个主要看实际的情况需要。比如PhotoShop就是要编辑图片,那么自然就是要对线条进行相应缩放,又比如Visio所画的图形,这就不要随着缩放而缩放。我在这里选择后者。

3.鼠标实现平移

这个比较简单,鼠标点击的时候,记录下点击的坐标(鼠标点击获取到的e.location是相对于视图窗口的坐标,需要通过逆矩阵换算出图片实际的坐标),鼠标移动到新的坐标的时候,两两进行相减,然后把结果赋值到_matrix中即可

 _matrix.Translate((points[0].X - _LastPt.X), (points[0].Y - _LastPt.Y));

4.鼠标实现旋转

这个和平移很相似,该有的换算都得算上,这里需要把平移需要的坐标,改成角度即可,角度的计算代码如下,这里都是相对于图像的中心点旋转,需要重新设置旋转点,修改对应的旋转中心点就可以了:

double corrb = Math.Atan2(_LastPt.Y - _rcImg.Height / 2, _LastPt.X - _rcImg.Width / 2);
double corre = Math.Atan2(points[0].Y - _rcImg.Height / 2, points[0].X - _rcImg.Width / 2);
_matrix.RotateAt((float)((corre -corrb) *180.0f/Math.PI), new Point(_rcImg.Width / 2, _rcImg.Height / 2));
DRoute += (Double)((corre - corrb) * 180.0f / Math.PI);

5.鼠标实现缩放

缩放实际上要实现两步,第一步是缩放,缩放后鼠标所在的坐标相对与图片来说发生了变化,所以还需要一步进行图像的平移,代码如下:

        private void ChartView_MouseWheel(object sender, MouseEventArgs e){Point[] points = new Point[] { e.Location };Matrix matrix_Invert = _matrix.Clone();matrix_Invert.Invert();matrix_Invert.TransformPoints(points);Console.WriteLine(points[0]);if (_rcImg.Contains(points[0])){double step = 1.2;if (e.Delta < 0){step = 1.0 / 1.2;}DScale *= step;_matrix.Scale((float)step, (float)step);Point[] pointse = new Point[] { e.Location };matrix_Invert = _matrix.Clone();matrix_Invert.Invert();matrix_Invert.TransformPoints(pointse);_matrix.Translate((pointse[0].X - points[0].X), (pointse[0].Y - points[0].Y));Refresh();}}

C# winform 通过Matrix实现图像的自由平移、缩放、旋转相关推荐

  1. [Python从零到壹] 三十八.图像处理基础篇之图像几何变换(平移缩放旋转)

    欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...

  2. C语言数字图像处理---1.5图像基本变换之平移缩放旋转

    本篇作为新年到来前的最后一篇,提前祝大家新年快乐! 图像几何变换又叫做图像基本变换,主要包括图像平移.图像缩放和图像旋转几个部分,当然还有图像镜像等简单的内容.图像基本变换是图像处理的基本内容,是学习 ...

  3. C#图像处理-OpenCVSharp教程(十二) OpenCVSharp图像几何变换:平移、旋转、缩放、转置和镜像等

    本文作者Color Space,文章未经作者允许禁止转载! 本文将介绍OpenCVSharp图像几何变换:平移.旋转.缩放.转置和镜像等! 一.图像缩放 // 图像缩放-- - Resize Mat ...

  4. [Python图像处理] 三十六.OpenCV图像几何变换万字详解(平移缩放旋转、镜像仿射透视)

    该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...

  5. 图像的几何变换—平移、旋转、镜像、缩放、剪切(原理+调用函数+像素操作)

    目录 一.平移 1.调用函数(平移矩阵) 2.像素操作(遍历赋值) 二.旋转 1.调用函数(旋转矩阵) 2.像素操作(反向映射) 三.镜像 1.调用函数(镜像矩阵) 2.像素操作(反向映射) 四.缩放 ...

  6. 矩阵宏观调度:Zigzag扫描打印矩阵matrix,图像工程的一种编码

    矩阵宏观调度:Zigzag扫描打印矩阵matrix,图像工程的一种编码 提示:极其重要的矩阵处理技巧,矩阵下标的宏观调度 文章目录 矩阵宏观调度:Zigzag扫描打印矩阵matrix,图像工程的一种编 ...

  7. 基于OpenCV+WinForm开发的图形图像渲染控件

    基于OpenCV+WinForm开发的图形图像渲染控件 WinForm版图形图像渲染控件 图像居中渲染 图像放大 图像缩小 绘制图形 点 线 矩形 圆形 旋转矩形 多边形 资源连接 WinForm版图 ...

  8. 图像算法二:【图像几何变换】平移、镜像、转置、缩放、旋转、插值

    作为一个强大的科学计算软件,MATLAB广泛运用于较多领域,以其简单的编程风格著称.这篇文章便通过matlab语言来讲述如何进行图像的各种几何变换. 图像几何变换又称为图像空间变换,它是将一幅图像中的 ...

  9. Matlab图像的平移,旋转,缩放,裁剪

    %%------------------------Matlab图像的平移,旋转,缩放,裁剪------------------------------- %-------------------头文 ...

最新文章

  1. idea怎么配置spring
  2. Android 数据访问之Internal Storage 数据保存在内存 demo+笔记
  3. 2019.8.6原型链与继承
  4. vue中ref 的使用
  5. nfine框架连接oracle,NFine快速开发框架(无后门)
  6. 安卓暗黑模式软件_程序员欢呼!微软 GitHub 安卓版 App 发布预览:支持暗黑模式...
  7. M1 Repast Simphony打不开 无反应问题解决
  8. 一个比CAM350好用的看GERBER软件
  9. 串口调试助手出现乱码
  10. 按键精灵脚本:采集鼠标当前所在坐标的颜色
  11. ie6, ie7兼容性问题以及处理办法汇总
  12. 天龙手游角色删除服务器还有显示,天龙八部手游怎么删除角色_角色删除方法详解_玩游戏网...
  13. 【目标检测】MMDetection的安装与基础使用
  14. 一些常用的软件和资源网站
  15. 鲍尔默:微软发展来自对八个核心领域持续投资 (作者:三张 | 出处:网易科技 )
  16. 手把手教你如何玩转Solr(包含项目实战)[转载]
  17. 印尼城市排名west java_印尼城市有哪些 印尼十大城市排名
  18. 菜谱微信小程序源码,包含后端业务逻辑
  19. SDIO_WiFi驱动学习之SDIO架构介绍及源码分析
  20. MyBatis select标签

热门文章

  1. 手写Vue3.0响应式
  2. VBA学习笔记1:将同个文件夹中的工作簿汇总为一个工作簿,并建立目录超链接
  3. 京东2020双十一脚本(基于Autojs)
  4. 数据结构面试大全(二) - [算法]
  5. 关于重装系统时读取不到硬盘和设置主板AHCI蓝屏问题
  6. 节日期间该如何运营店铺?远超同行
  7. 【机器人领域会议】简介
  8. python接口返回状态码,Python脚本接口返回正常,状态码405
  9. CSP-J/S 自闭加憨憨记
  10. Ubuntu安装mcrypt扩展