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); }