Click here to Skip to main content
15,887,135 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
<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)
        {

        }
    }
}
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.
Posted
Updated 21-May-16 3:29am
v2
Comments
Sergey Alexandrovich Kryukov 20-May-16 15:41pm    
Next time, specify what you are using: System.Windows.Forms.
On what event do you want magnified image? The problem is very simple, but it has one potential catch when the image changes the size (easy to avoid). Do you want to magnify the whole image in the PictureBox?

How the magnified area is related to "user selects"? If you have to modify only a part of the image of the PictureBox, the solution is clear: ditch PictureBox.

—SA
Member 12076824 20-May-16 21:32pm    
Thanks for reply. Sorry about that I thought I added tag. Its a windows app. I want to magnify part of the image that would be displayed on the PictureBox as zoomed area of that particular location user want to magnify
Sergey Alexandrovich Kryukov 20-May-16 23:15pm    
I say, forget the PictureBox. It's totally unsuitable. Now, you need to describe how the part of image is defined. And what is image? It that just the fixed bitmap? Do you have it in two versions, magnified and normal? What should be the area of magnified part? Do you mean that a magnified part should be superimposed on the background of normal-size one? And so on...

The code is going to be a bit complicated, but the idea is pretty simple. One tricky part is the shape of magnified area. If the shape is rectangular, it's not a problem, if not, you will have to use bitmap with opacity, and make some pixel transparent and some semitransparent, and also provide anti-aliasing of the boundary between opaque and transparent regions. On the next step, if magnified area is a round, it's pretty easy (thing "magnified glass"), if it's more complicated... And so on...

The only problem is some detail of your requirement and the level of detail you need in an answer.

—SA
Member 12076824 21-May-16 0:49am    
Its a tif image that's loaded at comboBox selectIndex change event and its different image for every index changed( which is selected from the items listed in combobox from directory). I have single version of image, I am trying to magnify the area of the actual image when user clicks around particular area that will cover up entire section of that page like rectangle.
Sergey Alexandrovich Kryukov 21-May-16 9:07am    
What does it mean, "like rectangle"? Rectangle or not? What is the magnification area? Is it something around the mouse cursor at the moment of click. If you switch magnification in click, in what event do you remove it? Another click?
—SA

1 solution

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
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900