Have an Image fit to picturebox, zoom and move






4.33/5 (8 votes)
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.
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]