Click here to Skip to main content
15,868,016 members
Articles / Multimedia / GDI+

Image Target Zoom (Pan Zoom)

Rate me:
Please Sign up or sign in to vote.
4.32/5 (16 votes)
22 Jan 2008CPOL2 min read 100.4K   9K   48  
To pan and zoom to a point of interest in an image.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Text;
using System.Windows.Forms;

namespace PanZoom02
{
    public partial class Form1 : Form
    {
        public class overRidePanel : Panel
        {
            protected override void OnPaintBackground(PaintEventArgs pevent) { }
        }
        Bitmap bitmap;        
        BufferedGraphicsContext currentContext;
        BufferedGraphics myBuffer;  
        PointF viewPortCenter;
        float Zoom = 1.0f;

        bool draging = false;
        Point lastMouse;

        public Form1()
        {
            InitializeComponent();
            currentContext = BufferedGraphicsManager.Current;            
            setup(false);
        }

        private void setup(bool resetViewport)
        {            
            if (myBuffer != null)
                myBuffer.Dispose();
            myBuffer = currentContext.Allocate(this.panel1.CreateGraphics(), this.panel1.DisplayRectangle);
            if (bitmap != null)
            {
                if (resetViewport)
                    SetViewPort(new RectangleF(0, 0, bitmap.Width, bitmap.Height));                
            }            
            this.panel1.Focus();
            this.panel1.Invalidate();
        }        
        private void SetViewPort(RectangleF worldCords)
        {           
           //Find smallest screen extent and zoom to that
            if (worldCords.Height > worldCords.Width)
            {
                //Use With as limiting factor
                this.Zoom = worldCords.Width / bitmap.Width;
            }
            else
                this.Zoom = worldCords.Height / bitmap.Height;

            viewPortCenter = new PointF(worldCords.X +(worldCords.Width / 2.0f), worldCords.Y + (worldCords.Height / 2.0f));
            this.toolStripStatusLabel1.Text = "Zoom: " + ((int)(this.Zoom*100)).ToString()+"%";
            
        }
        private void SetViewPort(Rectangle screenCords)
        {
        }
        private void PaintImage()
        {
            if (bitmap != null)
            {               
                float widthZoomed = panel1.Width / Zoom;
                float heigthZoomed = panel1.Height / Zoom;

                //Do checks the reason 30,000 is used is because much over this will cause DrawImage to crash
                if (widthZoomed > 30000.0f)
                {
                    Zoom = panel1.Width / 30000.0f;
                    widthZoomed = 30000.0f;
                }                
                if (heigthZoomed > 30000.0f)
                {
                    Zoom = panel1.Height / 30000.0f;
                    heigthZoomed = 30000.0f;
                }

                //we stop at 2 because at this point you have almost zoomed into a single pixel
                if (widthZoomed < 2.0f)
                {
                    Zoom = panel1.Width / 2.0f;
                    widthZoomed = 2.0f;
                }
                if (heigthZoomed < 2.0f)
                {
                    Zoom = panel1.Height / 2.0f;
                    heigthZoomed = 2.0f;
                }

                float wz2 = widthZoomed / 2.0f;
                float hz2 = heigthZoomed / 2.0f;
                Rectangle drawRect = new Rectangle(
                    (int)(viewPortCenter.X - wz2),
                    (int)(viewPortCenter.Y - hz2),
                    (int)(widthZoomed), 
                    (int)(heigthZoomed));

                //this.toolStripStatusLabel1.Text = "DrawRect = " + drawRect.ToString();
                
                myBuffer.Graphics.Clear(Color.White); //Clear the Back buffer

                //Draw the image, Write image to back buffer, and render back buffer
                myBuffer.Graphics.DrawImage(bitmap, this.panel1.DisplayRectangle, drawRect, GraphicsUnit.Pixel);
                myBuffer.Render(this.panel1.CreateGraphics());
               this.toolStripStatusLabel1.Text = "Zoom: " + ((int)(this.Zoom * 100)).ToString() + "%";                
            }
        }        

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                bitmap = (Bitmap)Bitmap.FromFile(openFileDialog1.FileName);
                setup(true);                
            }
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            setup(false);
        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {
            PaintImage();
        }

        private void panel1_MouseWheel(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            Zoom += Zoom * (e.Delta / 1200.0f); //the 1200.0f is any-number it just seem to work well so i use it.
            if (e.Delta > 0) //I prefer to use the targe zoom when zooming in only, remove "if" to have it apply to zoom in and out
                viewPortCenter = new PointF(viewPortCenter.X + ((e.X - (panel1.Width / 2)) /(2* Zoom)), viewPortCenter.Y + ((e.Y - (panel1.Height/2)) / (2*Zoom)));                            
            this.panel1.Invalidate();            
        }

        private void panel1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                draging = true;
        }

        private void panel1_MouseMove(object sender, MouseEventArgs e)
        {
            if (draging)
            {
                viewPortCenter = new PointF(viewPortCenter.X + ((lastMouse.X - e.X)/Zoom), viewPortCenter.Y + ((lastMouse.Y- e.Y)/Zoom));                
                panel1.Invalidate();                
            }
            lastMouse = e.Location;            
        }
        
        private void panel1_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                draging = false;
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
Other
United States United States
Currently I work on industrial machinery as a mechanic. I have a few other things on my resume before that are mostly computer related. I have been writing programs in various languages for about 10 years. The single most complex thing I have ever encountered as a programmer, an engineering student, a Christian, a husband, a soldier, and father is, Jesus The Christ, and the book called The Bible. It is like a masterful fractal, but like a graphical representation of a fractal you do not have to understand the math to see how simple, beautiful, and complex it is. Yes, the physical bible is a bunch of words on paper. However, to understand what The Bible says is a scary thing. The world you now live in becomes like a movie studio set, of plywood cutouts. And to look behind the cutout and understand that things are not what they seem is a real mind bender. I could keep going, but the Bible is the smallest most efficient way to communicate the information inside. Note: It is easy to read The Bible and not understand what it means. It is impossible to understand The Bible unless God allows you to, I am not being impetuous, but until you find your life the things you say and do, today, in that book. You may close your eyes and think you know what it means to be blind, but if you have ever been blind you don't 'think you know' you understand.

Comments and Discussions