使用固定大小的可拖动图片框裁剪图像

我正在开展一个涉及裁剪图像的winforms项目。 我的目标是通过使用固定大小的可拖动图片框控件来完成此操作,允许用户选择他们想要保留的区域。

我的问题是当我裁剪图像时; 它“有效” ,但作物面积偏移了一点。 这是我得到的结果:

原始图像裁剪图像

为了澄清,我不是在谈论缩放,这是每个设计。 请注意,橙色框主要关注风暴的眼睛,但裁剪的图像不是。

这是我的作物操作代码:

private void tsbRecortar_Click(object sender, EventArgs e) { Rectangle recorte = new Rectangle(pbxSeleccion.Location.X, pbxSeleccion.Location.Y, pbxSeleccion.Width, pbxSeleccion.Height); foto = recortarImagen(foto, recorte); pbxImagen.Image = foto; } private Image recortarImagen(Image imagen, Rectangle recuadro) { try { Bitmap bitmap = new Bitmap(imagen); Bitmap cropedBitmap = bitmap.Clone(recuadro, bitmap.PixelFormat); return (Image)(cropedBitmap); } catch (Exception ex) { MessageBox.Show(ex.Message, "Error"); return null; } } 

pbxSeleccion是可拖动的橙色矩形; 它的父亲是pbxImage (我在表单的负载上重新表示它)。

正如你所看到的,我正在使用pbxSeleccion的坐标来定义裁剪区域的起点,但是没有按预期工作……有时候,我甚至会得到一个“Out of Memory”exception。

我认为这与图像在父图片框中的加载方式有关,关于如何在“引擎盖下”处理边距,但我没有尝试修复它……只是改变了偏移的大小。

搜索网络和SO对我有很大帮助,但对于这个特殊问题,我似乎无法找到答案……请随意指出我的代码改进,我没有长时间编码我是C#和.NET的新手

任何帮助都非常感谢。 干杯!

假设您的原始图像显示在PictureBox 。 你通过了橙色裁剪窗口的错误位置 。 以下是为您更正的代码:

 private void tsbRecortar_Click(object sender, EventArgs e){ Point p = yourPictureBox.PointToClient(pbxSelection.PointToScreen(Point.Empty)); Rectangle recorte = new Rectangle(pX, pY, pbxSeleccion.Width, pbxSeleccion.Height); foto = recortarImagen(foto, recorte); pbxImagen.Image = foto; } 

我在这里使用PointToClientPointToScreen ,因为我认为这是最好的方法。 然后,您可以安全地更改pictureBox的容器,而无需修改代码。 如果您使用如下代码,当您想将pictureBox放在另一个容器中时,它不够动态:

 Rectangle recorte = new Rectangle(pbxSeleccion.X + yourPictureBox.Left, pbxSeleccion.Y + yourPictureBox.Top, pbxSeleccion.Width, pbxSeleccion.Height); 

注意 :您也可以像这样使用RectangleToClientRectangleToScreen

 private void tsbRecortar_Click(object sender, EventArgs e){ Rectangle recorte = yourPictureBox.RectangleToClient(pbxSeleccion.RectangleToScreen(pbxSeleccion.ClientRectangle)); foto = recortarImagen(foto, recorte); pbxImagen.Image = foto; } 

尝试使用此代码在图片框中裁剪图像

  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; } 

在PictureBox上为鼠标事件编写以下代码

  private void pictureBox1_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { _selecting = true; _selection = new Rectangle(new Point(eX, eY), 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 = eX - _selection.X; _selection.Height = eY - _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); } } 

输出屏幕

  1. 裁剪之前

在此处输入图像描述

  1. 裁剪后

在此处输入图像描述