如何在imagepanel上显示所选区域的放大图像? [英] How do I display magnified image of selected area on imagepanel click?

查看:59
本文介绍了如何在imagepanel上显示所选区域的放大图像?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

<pre lang="c#"><pre>using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace ImageMagnifier
{
    public partial class ImagePanel : UserControl
    {
        public ImagePanel()
        {
            InitializeComponent();

            // Set the value of the double-buffering style bits to true.
            this.SetStyle(ControlStyles.AllPaintingInWmPaint |
              ControlStyles.UserPaint | ControlStyles.ResizeRedraw |
              ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true);
        }

        int viewRectWidth, viewRectHeight; // view window width and height

        float zoom = 1.0f;
        public float Zoom
        {
            get { return zoom; }
            set
            {
                if (value < 0.001f) value = 0.001f;
                zoom = value;

                displayScrollbar();
                setScrollbarValues();
                Invalidate();
            }
        }

        Size canvasSize = new Size(60, 40);
        public Size CanvasSize
        {
            get { return canvasSize; }
            set
            {
                canvasSize = value;
                displayScrollbar();
                setScrollbarValues();
                Invalidate();
            }
        }

        Bitmap image;
        public Bitmap Image
        {
            get { return image; }
            set 
            {
                image = value;
                displayScrollbar();
                setScrollbarValues(); 
                Invalidate();
            }
        }
        public string ImagePath { get; set; }
        InterpolationMode interMode = InterpolationMode.HighQualityBilinear;
        public InterpolationMode InterpolationMode
        {
            get{return interMode;}
            set{interMode=value;}
        }

        protected override void OnLoad(EventArgs e)
        {
            displayScrollbar();
            setScrollbarValues();
            base.OnLoad(e);
        }

        protected override void OnResize(EventArgs e)
        {
            displayScrollbar();
            setScrollbarValues();
            base.OnResize(e);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
             base.OnPaint(e);

            //draw image
            if(image!=null)
            {
                Rectangle srcRect,distRect;
                Point pt=new Point((int)(hScrollBar1.Value/zoom),(int)(vScrollBar1.Value/zoom));//lynda added - 10
                if (canvasSize.Width * zoom < viewRectWidth && canvasSize.Height * zoom < viewRectHeight)
                    srcRect = new Rectangle(0, 0, canvasSize.Width, canvasSize.Height);  // view all image
                else srcRect = new Rectangle(pt, new Size((int)(viewRectWidth / zoom), (int)(viewRectHeight / zoom))); // view a portion of image

                distRect=new Rectangle((int)(-srcRect.Width/2),-srcRect.Height/2,srcRect.Width,srcRect.Height); // the center of apparent image is on origin
 
                Matrix mx=new Matrix(); // create an identity matrix
                mx.Scale(zoom,zoom); // zoom image lynda add *1.3f to vertical stretch
                mx.Translate(viewRectWidth/2.0f,viewRectHeight/2.0f, MatrixOrder.Append); // move image to view window center

                Graphics g=e.Graphics;
                g.InterpolationMode=interMode;
                g.Transform=mx;
                g.DrawImage(image,distRect,srcRect, GraphicsUnit.Pixel);
            }

        }

        private void displayScrollbar()
        {
            viewRectWidth = this.Width;
            viewRectHeight = this.Height;

            if (image != null) canvasSize = image.Size;

            // If the zoomed image is wider than view window, show the HScrollBar and adjust the view window
            if (viewRectWidth > canvasSize.Width*zoom)
            {
                hScrollBar1.Visible = false;
                viewRectHeight = Height;
            }
            else
            {
                hScrollBar1.Visible = true;
                viewRectHeight = Height - hScrollBar1.Height;
            }

            // If the zoomed image is taller than view window, show the VScrollBar and adjust the view window
            if (viewRectHeight > canvasSize.Height*zoom)
            {
                vScrollBar1.Visible = false;
                viewRectWidth = Width;
            }
            else
            {
                vScrollBar1.Visible = true;
                viewRectWidth = Width - vScrollBar1.Width;
            }

            // Set up scrollbars
            hScrollBar1.Location = new Point(0, Height - hScrollBar1.Height);
            hScrollBar1.Width = viewRectWidth;
            vScrollBar1.Location = new Point(Width - vScrollBar1.Width, 0);
            vScrollBar1.Height = viewRectHeight;
        }

        private void setScrollbarValues()
        {
            // Set the Maximum, Minimum, LargeChange and SmallChange properties.
            this.vScrollBar1.Minimum = 0;
            this.hScrollBar1.Minimum = 0;

            // If the offset does not make the Maximum less than zero, set its value. 
            if ((canvasSize.Width * zoom - viewRectWidth) > 0)
            {
                this.hScrollBar1.Maximum =(int)( canvasSize.Width * zoom) - viewRectWidth;
            }
            // If the VScrollBar is visible, adjust the Maximum of the 
            // HSCrollBar to account for the width of the VScrollBar.  
            if (this.vScrollBar1.Visible)
            {
                this.hScrollBar1.Maximum += this.vScrollBar1.Width;
            }
            this.hScrollBar1.LargeChange = this.hScrollBar1.Maximum / 10;
            this.hScrollBar1.SmallChange = this.hScrollBar1.Maximum / 20;

            // Adjust the Maximum value to make the raw Maximum value 
            // attainable by user interaction.
            this.hScrollBar1.Maximum += this.hScrollBar1.LargeChange;

            // If the offset does not make the Maximum less than zero, set its value.    
            if ((canvasSize.Height * zoom - viewRectHeight) > 0)
            {
                this.vScrollBar1.Maximum = (int)(canvasSize.Height * zoom) - viewRectHeight;
            }

            // If the HScrollBar is visible, adjust the Maximum of the 
            // VSCrollBar to account for the width of the HScrollBar.
            if (this.hScrollBar1.Visible)
            {
                this.vScrollBar1.Maximum += this.hScrollBar1.Height;
            }
            this.vScrollBar1.LargeChange = this.vScrollBar1.Maximum / 10;
            this.vScrollBar1.SmallChange = this.vScrollBar1.Maximum / 20;

            // Adjust the Maximum value to make the raw Maximum value 
            // attainable by user interaction.
            this.vScrollBar1.Maximum += this.vScrollBar1.LargeChange;
        }

        private void vScrollBar1_Scroll(object sender, ScrollEventArgs e)
        {
            this.Invalidate();
        }

        private void ImagePanel_Load(object sender, EventArgs e)
        {

        }
    }
}

在imagePanel上显示一个用户控件的图像,我正在使用该图像进行透视场的数据输入。我想在pictureBox上显示放大图像,用户可以在点击事件中从图像面板中的图像中选择inagePanel_click)用于选择像矩形区域的图像部分。如果有人可以指导我如何做到这一点。我非常感谢任何帮助。



我尝试过:



我在textbox上尝试了类似的概念,并且工作正常,但我需要在图片点击事件中做同样的事情。

have one image displayed on imagePanel which is user control, and I am using that image for data entry with perspective fields.I want to display magnified image on pictureBox for the area user selects from image in image panel at click event(inagePanel_click) for the section of the image that was selected like rectangle area. If someone can guide me how I can do that. I really appreciate any help.

What I have tried:

I have tried similar concept at textbox enter event and works fine, but I need to do the same at image click event.

推荐答案

从你的代码示例中,它看起来像你一般都明白这个主意。这个样本有很多问题,所以你需要把它全部整理好。



首先,请看看我过去与相关的图形渲染的答案OnPaint

什么样的俏皮方法是Paint? (DataGridViewImageCell.Paint(...)) [ ^ ],

在面板上捕获绘图 [ ^ ],

mdi子表单之间的绘制线 [ ^ ],

缩放: C#.net鼠标滚轮中的缩放图像 [ ^ ],

引用:如何避免DatagridView C#中的红十字会 [ ^ ]。



首先,你不需要 PictureBox ,它没有帮助,只会给你的工作带来麻烦。



您不需要 UserControl 只需支持设计师。您的基类可以是 System.Windows.Forms.Control ,或其他一些合适的控件,如 Panel 。如您所见, OnPaint 调用是通过调用 Invalidate 间接呈现的。您不能使整个场景无效,而是使其中的一部分,矩形或路径无效。 OnPaint 做一件事:使用事件参数参数中传递的 Graphics 呈现视图的某些数据模型。



你的模特是什么?首先,为了获得合理的性能,你必须有两个图像:放大和正常。当然,你可以通过编程方式从另一个中重新采样,但永远不会从较小的尺寸变为更大的尺寸:你的源图像应该总是更大的,否则你可能会严重影响图像质量。向上扩展不是可以正常工作的,因为您没有添加像素的数据。无论如何,请确保您的重新采样只进行一次,而不是每次点击。



然后你的模型应包括放大区域的位置,大小,班次在放大和正常位图之间。最后,它应该是一个布尔标志,显示放大倍数是打开还是关闭。比方说,你可以通过鼠标点击来计算它,也可以调用无效



你的 OnPaint 获取模型数据,并根据数据绘制一个或两个图层。首先绘制未放大的图像。然后,如果启用了放大模式,则会裁剪放大的图像并将此部分绘制在顶部。确保打开优化双缓冲,否则会出现令人讨厌的闪烁。这就是全部。



非矩形放大将需要更多的处理。如果这个区域是一个圆形,它会比它更复杂的要好得多。如果你想这样,问你的问题;我会尽力回答。



-SA
From your code sample, it looks like you generally understand the idea. This sample has many problem, so you need to put it all in order.

First, please see my past answer on graphics rendering related to OnPaint:
What kind of playful method is Paint? (DataGridViewImageCell.Paint(...))[^],
capture the drawing on a panel[^],
Drawing Lines between mdi child forms[^],
on zooming: Zoom image in C# .net mouse wheel[^],
references: How to avoid Red Cross in DatagridView C#[^].

First of all, you don't need PictureBox, it is not helpful, would only add hassles to your work.

You don't need UserControl with is only needed to support the designer. Your base class can be System.Windows.Forms.Control, or some other suitable control, like Panel. As you can see, OnPaint call is indirectly rendered via the call to Invalidate. You can invalidate not the whole scene, but a part of it, rectangle or path. OnPaint does one thing: renders some data model of the view using Graphics passed in the event arguments parameter.

What is your model? First of all, for reasonable performance, you have to have two images: magnified and "normal". Of course, you can re-sample of from another programmatically, but never go from smaller size to bigger size: your source image should always be the bigger one, otherwise you can badly screw up image quality. Scaling up is not what can work well, because you don't have data for the pixels added. Anyway, make sure your re-sampling is made only once, not on each click.

Then your model should include the location of the magnified area, its size, shift between magnified and "normal" bitmap. And, finally, it should be a Boolean flag showing if the magnification is on or off. Let's say, you calculate it from the mouse clicks, which also call Invalidate.

Your OnPaint takes the model data and, depending on data, draw one or two layers. First you draw the unmagnified image. Then, if magnification mode is on, you crop magnified image and draw this part on top. Make sure to switch "optimized double buffering" on, otherwise you would get nasty flicker. That's all.

Non-rectangular magnified are will take a lot more processing. And if this area is a round, it would be much better than if it is more complicated. If you want to go this way, ask your question; I'll try to answer.

—SA


这篇关于如何在imagepanel上显示所选区域的放大图像?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆