.net – 用Windows Forms缩放大图片
发布时间:2020-12-14 01:52:37 所属栏目:Windows 来源:网络整理
导读:我必须在 Windows窗体应用程序中显示一个大图像.用户应该可以标记图像的区域,然后应该像下面所示的示例一样进行缩放. 如前所述,图像会非常大,所以我的问题是:是否可以使用默认的PictureBox控件来实现这一点,还是我最好使用第三方控件?如果是这样,请推荐一
我必须在
Windows窗体应用程序中显示一个大图像.用户应该可以标记图像的区域,然后应该像下面所示的示例一样进行缩放.
如前所述,图像会非常大,所以我的问题是:是否可以使用默认的PictureBox控件来实现这一点,还是我最好使用第三方控件?如果是这样,请推荐一个包含提供这些功能的控件的库. 正如所承诺的,这是我制作的控件的来源: /// <summary> /// A panel used to display an image and zoom into areas of the displayed /// image. /// </summary> public sealed class PictureZoomPanel : Panel { // The image to dispay,set in the Image property private Image _image; // The current zoom factor private float _zoom = 1; // The zoom rectangle on the panel. private Rectangle _panelZoomRect; // _panelZoomRect on the actual image private Rectangle? _imageZoomRect; // Used in the mouse event handlers private bool _mouseDown; // The pen used to draw the zoom rectangle private Pen _zoomPen; /// <summary> /// Create a new <see cref="PictureZoomPanel"/> /// </summary> public PictureZoomPanel() { // To prevent flickering DoubleBuffered = true; // To make resizing smoother ResizeRedraw = true; // Set default zoom pen ZoomPen = null; } /// <summary> /// The image to be displayed /// </summary> [Category("Appearance"),Description("The image to be displayed.")] public Image Image { get { return _image; } set { _image = value; ZoomToFit(); } } /// <summary> /// The pen used to draw the zoom rectangle. /// </summary> [Category("Appearance"),Description("The pen used to draw the zoom rectangle.")] public Pen ZoomPen { get { return _zoomPen; } set { _zoomPen = value ?? new Pen(Color.Green,2); } } /// <summary> /// Sets the zoom to a value where the whole image is visible. /// </summary> public void ZoomToFit() { _imageZoomRect = null; _mouseDown = false; _zoom = 1; // If no image is present,there is nothing further to do if (_image == null) return; var widthZoom = (float) Width / _image.Width; var heightZoom = (float) Height / _image.Height; // Make sure the whole image is visible _zoom = widthZoom < heightZoom ? widthZoom : heightZoom; // Force redraw Invalidate(); } protected override void OnMouseDown(MouseEventArgs e) { if (_image == null) return; _mouseDown = true; _panelZoomRect = new Rectangle(e.X,e.Y,0); } protected override void OnMouseUp(MouseEventArgs e) { if (_image == null || !_mouseDown) return; _mouseDown = false; // Without this,doubling clicking the control would cause zoom if (_panelZoomRect.Height == 0 || _panelZoomRect.Width == 0) return; // Tell the paint method to zoom _imageZoomRect = CalculateImageZoomRectangle(); _zoom = RecalculateZoom(); } protected override void OnMouseMove(MouseEventArgs e) { if (_image == null) return; // This makes sure that the left mouse button is pressed. if (e.Button == MouseButtons.Left) { // Draws the rectangle as the mouse moves _panelZoomRect = new Rectangle( _panelZoomRect.Left,_panelZoomRect.Top,e.X - _panelZoomRect.Left,e.Y - _panelZoomRect.Top); } // Force redraw to make sure the zoomRegion is painted Invalidate(); } private Rectangle CalculateImageZoomRectangle() { // Calculate all the coordinates to required to transform var topLeft = new Point(_panelZoomRect.X,_panelZoomRect.Y); var topRight = new Point(_panelZoomRect.X + _panelZoomRect.Width,_panelZoomRect.Y); var bottomLeft = new Point(_panelZoomRect.X,_panelZoomRect.Y - _panelZoomRect.Height); var bottomRight = new Point(_panelZoomRect.X + _panelZoomRect.Height,_panelZoomRect.Y - _panelZoomRect.Height); var points = new [] { topLeft,topRight,bottomLeft,bottomRight }; // Converts the points from panel to image position var mx = new Matrix(_zoom,_zoom,0); mx.Invert(); mx.TransformPoints(points); var rectangleWidth = points[1].X - points[0].X; var rectangleHeight = points[0].Y - points[2].Y; // _imageZoom != null,means that we are zooming in on an // already zoomed in image. We must add the original values // to zoom in deeper return _imageZoomRect == null ? new Rectangle(points[0].X,points[0].Y,rectangleWidth,rectangleHeight) : new Rectangle(points[0].X + _imageZoomRect.Value.X,points[0].Y + _imageZoomRect.Value.Y,rectangleHeight); } private float RecalculateZoom() { if (!_imageZoomRect.HasValue) return _zoom; var widthZoom = (float)Width / _imageZoomRect.Value.Width; var heightZoom = (float)Height / _imageZoomRect.Value.Height; return widthZoom < heightZoom ? widthZoom : heightZoom; } protected override void OnPaint(PaintEventArgs e) { if (_image == null) { OnPaintBackground(e); return; } e.Graphics.Transform = new Matrix(_zoom,0); // Turn of interpolation when zoomed e.Graphics.InterpolationMode = _imageZoomRect != null ? InterpolationMode.NearestNeighbor : InterpolationMode.Default; DrawImage(e); if (_mouseDown) DrawZoomRectangle(e); base.OnPaint(e); } private void DrawImage(PaintEventArgs e) { var destRec = !_imageZoomRect.HasValue ? new Rectangle(0,_image.Width,_image.Height) : new Rectangle(0,_imageZoomRect.Value.Width,_imageZoomRect.Value.Height); var sourceRec = !_imageZoomRect.HasValue ? new Rectangle(0,_image.Height) : _imageZoomRect.Value; e.Graphics.DrawImage(_image,destRec,sourceRec.Location.X,sourceRec.Location.Y,sourceRec.Width,sourceRec.Height,GraphicsUnit.Pixel); } private void DrawZoomRectangle(PaintEventArgs e) { e.Graphics.Transform = new Matrix(); e.Graphics.DrawRectangle(_zoomPen,_panelZoomRect); } } 解决方法
您可以通过翻译图形对象来实现缩放.而不是使用PictureBox,我认为
double buffered Panel是更好的选择工具.
您处理绘制事件,并从那里调整它的矩阵表示.此外,您需要调整AutoScrollMinSize属性以使滚动条表示缩放图像的正确范围. 快速举例: Bitmap bmp = new Bitmap(@"c:myimage.png"); int zoom = 2; private void Form1_Load(object sender,EventArgs e) { panel1.AutoScrollMinSize = new Size(bmp.Width * zoom,bmp.Height * zoom); } private void panel1_Paint(object sender,PaintEventArgs e) { using (Matrix mx = new Matrix(zoom,zoom,0)) { mx.Translate(panel1.AutoScrollPosition.X / zoom,panel1.AutoScrollPosition.Y / zoom); e.Graphics.Transform = mx; e.Graphics.DrawImage(bmp,new Point(0,0)); } } 此方法用于跟踪缩放图像的鼠标移动: protected Point BacktrackMouse(MouseEventArgs e) { Matrix mx = new Matrix(_zoom,0); mx.Translate(this.AutoScrollPosition.X * (1.0f / zoom),this.AutoScrollPosition.Y * (1.0f / zoom)); mx.Invert(); Point[] p = new Point[] { new Point(e.X,e.Y) }; mx.TransformPoints(p); return p[0]; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
推荐文章
站长推荐
热点阅读