Click here to Skip to main content
15,867,686 members
Articles / Multimedia / GDI
Tip/Trick

Have an Image fit to picturebox, zoom and move

Rate me:
Please Sign up or sign in to vote.
4.33/5 (8 votes)
23 Mar 2011CPOL 60.2K   17   7
This demostrates fitting an image to the picturebox extend, zoom and move by transforming the picturebox device context/ graphics
On the internet, there are lot of code snippets for fitting an image to a picture box. Many of those involve operations on the bitmap, resize and interpolate.

But that can be easily achieved by transforming (scaling) the device context (Graphics object in C#) and draw the bitmap over the transformed device context.

Here it stores image in a global variable. Then this image is used to redraw in the picture box. The image is finally disposed at the disposed event of the form. No operations on the bitmap is needed.

For testing this code, you need a form with a picture box (pictureBox1), a Zoom button( button1), a text box (textBox1) to enter the zoom factor and a move button (button2).
Then use the code below.

Initially it fits the image to the picturebox (Zoom factor 1).

To Zoom, enter the zoom factor and click the zoom button.

To move the image, click the move button, click on the image, keep hold the clicked mouse button and drag. Release the mouse button.
C#
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using System.IO;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        // Factor for zoom the image
        private float zoomFac = 1;
        //set Zoom allowed
        private bool zoomSet = false;

        //value for moving the image in X direction
        private float translateX=0;
        //value for moving the image in Y direction
        private float translateY = 0;

        //Flag to set the moving operation set
        private bool translateSet = false;
        //Flag to set mouse down on the image
        private bool translate = false;

        //set on the mouse down to know from where moving starts
        private float transStartX;
        private float transStartY;

        //Current Image position after moving 
        private float curImageX=0;
        private float curImageY=0;


        //temporary storage in bitmap
        Image bmp;

        float ratio;
        float translateRatio;


        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //Picture box event handlers
            pictureBox1.Paint += new PaintEventHandler(pictureBox1_Paint);
            pictureBox1.MouseDown += new MouseEventHandler(pictureBox1_MouseDown);
            pictureBox1.MouseUp += new MouseEventHandler(pictureBox1_MouseUp);

            pictureBox1.BorderStyle = BorderStyle.FixedSingle;

            //Store the image in to bytes array
            //It is not advisable to store bitmap as such

            //Change the path name for your file
            if (System.IO.File.Exists(Application.StartupPath + "//test.jpg") != true)
            {
                MessageBox.Show("Your Image file does not exists");
                return;
            }

            if (bmp != null)
            {
                bmp.Dispose();
            }
            bmp = new Bitmap(Application.StartupPath + "//test.jpg");

            // Check potrait or landscape
            if (bmp.Width > bmp.Height)
            {
                ratio = (float)pictureBox1.Width / (float)bmp.Width;
                translateRatio = (float)bmp.Width / (float)pictureBox1.Width;
             
            }
            else
            {
                ratio = (float)pictureBox1.Height / (float)bmp.Height;
                translateRatio = (float)bmp.Height / (float)pictureBox1.Height;

            }


             this.Shown +=new EventHandler(Form1_Shown);
             this.Disposed +=new EventHandler(Form1_Disposed);
        }
        protected void Form1_Disposed(object sender, EventArgs e)
        {
            //Dispose the bmp when form is disposed.
            if (bmp != null)
            {
                bmp.Dispose();
            }
        }

        protected void Form1_Shown(object sender, EventArgs e)
        {
            //Draw the image initially
            zoomSet = true;
            pictureBox1.Refresh();
            zoomSet = false;

        }

        //Zoom Button
        private void button1_Click(object sender, EventArgs e)
        {
            if (textBox1.Text == "" || Single.TryParse(textBox1.Text, out zoomFac)==false) { return; }
            //set Zoom allowed
            zoomSet = true;

            //call the picture box paint
            pictureBox1.Refresh();
            pictureBox1.Cursor = Cursors.Arrow;

            //moving operation unset
            translateSet = false;

        }

        //Move / Pan button
        private void button2_Click(object sender, EventArgs e)
        {
            //Chnage the cursor
            pictureBox1.Cursor = Cursors.Hand;
            //set moving operation is allowed
            translateSet = true;

            zoomSet = false;
        }

        protected void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            //If move button clicked
            if (translateSet == true)
            {
                //mouse down is true
                translate = true;
                //starting coordinates for move
                transStartX = e.X;
                transStartY = e.Y;

            }
        }
        protected void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            //If mouse down is true
            if (translate == true)
            {
                //calculate the total distance to move from 0,0
                //previous image position+ current moving distance
                translateX = curImageX + ((e.X - transStartX) * (translateRatio/zoomFac));
                translateY = curImageY + ((e.Y - transStartY) * (translateRatio/zoomFac));
                //call picturebox to update the image in the new position
            }

            pictureBox1.Refresh();
            //set mouse down operation end
            translate = false;
            //set present position of the image after move.
            curImageX = translateX;
            curImageY = translateY;
         }
        protected void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            //Conditions to avoid to proceed further.
            if (bmp == null) { return; }
            if (translateSet == false && zoomSet == false) { return; }

            Graphics g = e.Graphics;

           //Scale transform operation on the picture box device context
            //zoomFac is global variable which can be used to get desired zoom
            g.ScaleTransform(ratio * zoomFac, ratio * zoomFac);

            //move image to new position
            if (translateSet == true)
            {
                g.TranslateTransform(translateX, translateY);
            }

            //Drawback the bitmap to the transformed decive context

            //Apply double buffering (Draw to a bitmap first and then draw to picturebox) if
            // using large image and experience flickering
           
            g.DrawImage(bmp, 0, 0);


        }


    }
}


[change history]

Minor error checking has been done.

Mouse move event is removed to increase performance and that operations moved to mouse up event

[/change history]

License

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


Written By
Software Developer
India India
I am developer in .Net and GIS. albin_gis@yahoo.com

Comments and Discussions

 
GeneralMy vote of 5 Pin
zhiqiangchao16-Oct-13 22:36
zhiqiangchao16-Oct-13 22:36 
GeneralRe: Will look in to this issue as soon as possible. By the way t... Pin
Albin Abel22-Mar-11 17:44
Albin Abel22-Mar-11 17:44 
Will look in to this issue as soon as possible. By the way the pan works like a window over the image and move the image underneath it. Only the viewable area visible through the window is drawn. Just like when we we view in a window at different angles, we are not viewing the whole scene. But part of it. As I am not trimming any image bytes from it, then I will look at why the drawImage not working in your case. Strange to me, but yet I ll take this serious. Thanks for informing
GeneralRe: here's an image showing the errors from dragging partially o... Pin
Ian Good22-Mar-11 12:07
Ian Good22-Mar-11 12:07 
GeneralWhen i am running it it shows Your image file does not exis... Pin
Anurag Sarkar30-Nov-11 8:54
Anurag Sarkar30-Nov-11 8:54 
GeneralRe: Hi Change your path here bmp = new Bitmap(Application.Start... Pin
Albin Abel2-Dec-11 22:00
Albin Abel2-Dec-11 22:00 
GeneralReason for my vote of 1 this demo quickly breaks down when t... Pin
Ian Good21-Mar-11 16:16
Ian Good21-Mar-11 16:16 
GeneralRe: Thanks for your comments. if you could post your error messa... Pin
Albin Abel21-Mar-11 16:44
Albin Abel21-Mar-11 16:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.