Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Have an Image fit to picturebox, zoom and move

0.00/5 (No votes)
23 Mar 2011 1  
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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here