I\'m working on a winforms project that involves cropping an image. My goal is to do this by using a fixed-size draggable picturebox control, allowing the user to select the are
Try This Code for Cropping the Image in picturebox
public static Image Fit2PictureBox(this Image image, PictureBox picBox)
{
Bitmap bmp = null;
Graphics g;
// Scale:
double scaleY = (double)image.Width / picBox.Width;
double scaleX = (double)image.Height / picBox.Height;
double scale = scaleY < scaleX ? scaleX : scaleY;
// Create new bitmap:
bmp = new Bitmap(
(int)((double)image.Width / scale),
(int)((double)image.Height / scale));
// Set resolution of the new image:
bmp.SetResolution(
image.HorizontalResolution,
image.VerticalResolution);
// Create graphics:
g = Graphics.FromImage(bmp);
// Set interpolation mode:
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
// Draw the new image:
g.DrawImage(
image,
new Rectangle( // Ziel
0, 0,
bmp.Width, bmp.Height),
new Rectangle( // Quelle
0, 0,
image.Width, image.Height),
GraphicsUnit.Pixel);
// Release the resources of the graphics:
g.Dispose();
// Release the resources of the origin image:
image.Dispose();
return bmp;
}
public static Image Crop(this Image image, Rectangle selection)
{
Bitmap bmp = image as Bitmap;
// Check if it is a bitmap:
if (bmp == null)
throw new ArgumentException("Kein gültiges Bild (Bitmap)");
// Crop the image:
Bitmap cropBmp = bmp.Clone(selection, bmp.PixelFormat);
// Release the resources:
image.Dispose();
return cropBmp;
}
Write The Following Code For Mouse Event on PictureBox
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
_selecting = true;
_selection = new Rectangle(new Point(e.X, e.Y), new Size());
}
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && _selecting)
{
// Create cropped image:
try
{
Image img = pictureBox1.Image.Crop(_selection);
// Fit image to the picturebox:
pictureBox1.Image = img.Fit2PictureBox(pictureBox1);
}
catch { }
_selecting = false;
}
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
// Update the actual size of the selection:
if (_selecting)
{
_selection.Width = e.X - _selection.X;
_selection.Height = e.Y - _selection.Y;
// Redraw the picturebox:
pictureBox1.Refresh();
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (_selecting)
{
// Draw a rectangle displaying the current selection
Pen pen = Pens.LightSkyBlue;
e.Graphics.DrawRectangle(pen, _selection);
}
}
Output Screen
Suppose your original image is displayed in a PictureBox
. You passed in the wrong location of the orange cropping window. Here is the corrected code for you:
private void tsbRecortar_Click(object sender, EventArgs e){
Point p = yourPictureBox.PointToClient(pbxSelection.PointToScreen(Point.Empty));
Rectangle recorte = new Rectangle(p.X, p.Y, pbxSeleccion.Width, pbxSeleccion.Height);
foto = recortarImagen(foto, recorte);
pbxImagen.Image = foto;
}
I use PointToClient
and PointToScreen
here because I think it's the best way to do. You can then change the container of your pictureBox
safely without having to modify the code. If you use the code like the following, it's not dynamically enough when you want to place your pictureBox
in another container:
Rectangle recorte = new Rectangle(pbxSeleccion.X + yourPictureBox.Left,
pbxSeleccion.Y + yourPictureBox.Top,
pbxSeleccion.Width, pbxSeleccion.Height);
NOTE: you can also use RectangleToClient
and RectangleToScreen
like this:
private void tsbRecortar_Click(object sender, EventArgs e){
Rectangle recorte = yourPictureBox.RectangleToClient(pbxSeleccion.RectangleToScreen(pbxSeleccion.ClientRectangle));
foto = recortarImagen(foto, recorte);
pbxImagen.Image = foto;
}