C#笔记 picturebox功能实现(滚动放大,拖动)
2023-02-18 16:27:17 时间
1. picturebox上的坐标与原图中坐标的转换
(1) 由于图片的长宽比例和picturebox的长宽比例不同,所以图片不想拉伸的话,左右或者上下会有留白。将picturebox的sizemode设为zoom,计算留白距离。
默认情况下,在 Normal 模式中,Image 置于 PictureBox 的左上角,凡是因过大而不适合 PictureBox 的任何图像部分都将被剪裁掉。
PictureBoxSizeMode.StretchImage:使用 StretchImage 值会使图像拉伸或收缩,以便适合 PictureBox。
PictureBoxSizeMode.AutoSize:使用 AutoSize 值会使控件调整大小,以便总是适合图像的大小。
PictureBoxSizeMode.CenterImage:使用 CenterImage 值会使图像居于工作区的中心。
PictureBoxSizeMode.Zoom:使用 Zoom 的值可以使图像被拉伸或收缩以适应 PictureBox;但是仍然保持原始纵横比。
(2)picturebox的坐标都要先减去留白距离,根据比例缩放后再加上显示区域的偏移量
private OpenCvSharp.Point GetImagePoint(System.Drawing.Point p) { OpenCvSharp.Point imagePoint; int width = showImage.Width; int height = showImage.Height; int w = Width; int h = Height; double ratio; if (w_empty>0) { ratio = h * 1.0 / height; if (p.X < w_empty || p.X > w - w_empty) imagePoint.X = -1; else imagePoint.X = LUCol + (int)((p.X - w_empty) * 1.0 / ratio); imagePoint.Y = LURow + (int)(p.Y * 1.0 / ratio); } else { ratio = w * 1.0 / width; imagePoint.X = LUCol + (int)(p.X * 1.0 / ratio); if (p.Y < h_empty || p.Y > h - h_empty) imagePoint.Y = -1; else imagePoint.Y = LURow + (int)((p.Y - h_empty) * 1.0 / ratio); } return imagePoint; }
2. 滚动放大
滚动放大时,当前坐标为放大中心。
滚动放大后,显示部分占原图的比例会减小,显示部分左上角点在原图的坐标也会移动。
从原图上裁出显示部分 new Rect(LUCol, LURow, RealWidth, RealHeight)
public void pictureBox_MouseWheel(object sender, MouseEventArgs e) { if (Image == null) return; if (e.Delta > 0) { RealWidth /= 2; RealHeight /= 2; LUCol = CurrentPoint.X - (int)RealWidth / 2; LURow = CurrentPoint.Y - (int)RealHeight / 2; } else { RealWidth *= 2; RealHeight *= 2; LUCol = CurrentPoint.X - (int)RealWidth / 2; LURow = CurrentPoint.Y - (int)RealHeight / 2; } judgeBounds(); showImage = new Mat(srcImage, new Rect(LUCol, LURow, RealWidth, RealHeight)); }
3. 拖动图片
public void pictureBox_MouseMove(object sender, MouseEventArgs e) { ... if (e.Button == MouseButtons.Left) { EndPoint = GetImagePoint(e.Location); int offsetX = EndPoint.X - CurrentPoint.X; int offsetY = EndPoint.Y - CurrentPoint.Y; LURow -= offsetY; LUCol -= offsetX; judgeBounds(); showImage = new Mat(srcImage, new Rect(LUCol, LURow, RealWidth, RealHeight)); } ... }
4. 图片放大后呈现像素块
重写paint,将插值方法改为最近邻插值
public void pictureBox_Paint(object sender, PaintEventArgs e) { if (Image == null) return; var state = e.Graphics.Save(); e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; e.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half; e.Graphics.Clear(BackColor); if(h_empty!=0) e.Graphics.DrawImage(Image, 0, h_empty, Width, Height-2*h_empty); else e.Graphics.DrawImage(Image, w_empty, 0, Width - 2*w_empty, Height); e.Graphics.Restore(state); }
相关文章
- 经典算法题每日演练——第十九题 双端队列
- 12篇学通C#网络编程——第四篇 TCP应用编程
- 玩玩图形图像——第一篇:图片灰度化
- 经典算法题每日演练——第十八题 外排序
- 经典算法题每日演练——第十七题 Dijkstra算法
- 经典算法题每日演练——第十六题 Kruskal算法
- 经典算法题每日演练——第十五题 并查集
- 经典算法题每日演练——第十四题 Prim算法
- 经典算法题每日演练——第十三题 赫夫曼树
- 经典算法题每日演练——第十二题 线段树
- 经典算法题每日演练——第十一题 Bitmap算法
- 经典算法题每日演练——第十题 树状数组
- 经典算法题每日演练——第九题 优先队列
- 经典算法题每日演练——第八题 AC自动机
- 经典算法题每日演练——第七题 KMP算法
- 6天通吃树结构—— 第五天 Trie树
- 经典算法题每日演练——第六题 协同推荐SlopeOne 算法
- 经典算法题每日演练——第五题 字符串相似度
- 经典算法题每日演练——第四题 最长公共子序列
- 玩玩小爬虫——抓取时的几个小细节