裁剪图片裁剪不正确
Cropping Image is not cropping correctly
我遵循了有关如何创建裁剪图像应用程序的 YouTube 教程。
目标:
我的目标只是将屏幕截图图像加载到 PictureBox1
。
然后用红色矩形标记一个区域以裁剪并显示到 PictureBox2
。
代码如下:
public partial class Form18 : Form
{
Rectangle Rect;
Point LocationXY;
Point LocationX1Y1;
bool IsMouseDown = false;
public Form18()
{
InitializeComponent();
}
private void Form18_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
//Clipboard image
pictureBox1.Image = Clipboard.GetImage();
}
private void picturebox1_MouseDown(object sender, MouseEventArgs e)
{
IsMouseDown = true;
LocationXY = e.Location;
}
private void picturebox1_MouseMove(object sender, MouseEventArgs e)
{
if (IsMouseDown == true)
{
LocationX1Y1 = e.Location;
Refresh();
}
}
private void picturebox1_MouseUp(object sender, MouseEventArgs e)
{
if (IsMouseDown == true)
{
LocationX1Y1 = e.Location;
IsMouseDown = false;
if (Rect != null)
{
Bitmap bit = new Bitmap(pictureBox1.Image, pictureBox1.Width, pictureBox1.Height);
Bitmap cropImg = new Bitmap(Rect.Width, Rect.Height);
Graphics g = Graphics.FromImage(cropImg);
g.DrawImage(bit, 0, 0, Rect, GraphicsUnit.Pixel);
pictureBox2.Image = cropImg;
}
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (Rect != null)
{
e.Graphics.DrawRectangle(Pens.Red, GetRect());
}
}
private Rectangle GetRect()
{
Rect = new Rectangle();
Rect.X = Math.Min(LocationXY.X, LocationX1Y1.X);
Rect.Y = Math.Min(LocationXY.Y, LocationX1Y1.Y);
Rect.Width = Math.Abs(LocationXY.X - LocationX1Y1.X);
Rect.Height = Math.Abs(LocationXY.Y - LocationX1Y1.Y);
return Rect;
}
}
输出:
这是输出结果:
在左侧 - 您可以看到屏幕截图输入,在右侧 - 您可以看到裁剪后的图像。
我不明白 - 红色标记的矩形没有正确裁剪图像? - 它显示了屏幕截图图像的不同区域。
哪里出错了?
在 PictureBox1
的 MouseUp
事件中,用一次性 Graphics
和 Bitmap
对象代替 泛洪 内存,处理 PictureBox2
的 Paint
事件并使用支持的 Graphics
对象进行绘制,只需使用 e.Graphics.DrawImage
重载来传递源矩形和目标矩形。
//...
private Point LocationXY;
private Point LocationX1Y1;
private void button1_Click(object sender, EventArgs e)
{
if (Clipboard.ContainsImage())
{
pictureBox1.Image?.Dispose();
pictureBox1.Image = Clipboard.GetImage();
}
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left)
LocationXY = e.Location;
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
LocationX1Y1 = e.Location;
pictureBox1.Invalidate();
}
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left)
{
LocationX1Y1 = e.Location;
pictureBox1.Invalidate();
pictureBox2.Invalidate();
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (MouseButtons == MouseButtons.Left)
e.Graphics.DrawRectangle(Pens.Red, GetRect());
}
private void pictureBox2_Paint(object sender, PaintEventArgs e)
{
var src = GetRect();
if (src == Rectangle.Empty) return;
var des = new Rectangle(0, 0, src.Width, src.Height);
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
e.Graphics.DrawImage(pictureBox1.Image,
des, src, GraphicsUnit.Pixel);
}
private Rectangle GetRect()
{
return new Rectangle(
Math.Min(LocationXY.X, LocationX1Y1.X),
Math.Min(LocationXY.Y, LocationX1Y1.Y),
Math.Abs(LocationXY.X - LocationX1Y1.X),
Math.Abs(LocationXY.Y - LocationX1Y1.Y)
);
}
//...
使用以下方法获取裁剪后的图像:
//...
private Bitmap GetCroppedImage()
{
var src = GetRect();
if (src == Rectangle.Empty) return null;
var des = new Rectangle(0, 0, src.Width, src.Height);
var b = new Bitmap(src.Width, src.Height);
using (var g = Graphics.FromImage(b))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.CompositingQuality = CompositingQuality.HighQuality;
g.DrawImage(pictureBox1.Image, des, src, GraphicsUnit.Pixel);
}
return b;
}
//...
然后你可以这样保存:
private void Save()
{
using (var d = new SaveFileDialog())
{
d.Filter = "PNG|*.png|JPEG|*.jpeg;*.jpg|BMP|*.bmp";
if (d.ShowDialog() != DialogResult.OK) return;
using (var b = GetCroppedImage())
{
if (b == null) return;
ImageFormat f;
switch (d.FilterIndex)
{
case 2:
f = ImageFormat.Jpeg;
break;
case 3:
f = ImageFormat.Bmp;
break;
default:
f = ImageFormat.Png;
break;
}
b.Save(d.FileName, f);
}
}
}
将SizeMode设置为Normal可能无法使用以下代码裁剪图像
Bitmap bit = new Bitmap(pictureBox1.Image, pictureBox1.Width, pictureBox1.Height);
Bitmap cropImg = new Bitmap(Rect.Width, Rect.Height);
裁剪将相对于 Picturebox 的宽度和高度。
将新的位图行更改为以下内容
Bitmap bit = new Bitmap(pictureBox1.Image, pictureBox1.Image.Width, pictureBox1.Image.Height);
Bitmap cropImg = new Bitmap(Rect.Width, Rect.Height);
或将图片框的 SizeMode 设置为 StretchImage
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
我遵循了有关如何创建裁剪图像应用程序的 YouTube 教程。
目标:
我的目标只是将屏幕截图图像加载到 PictureBox1
。
然后用红色矩形标记一个区域以裁剪并显示到 PictureBox2
。
代码如下:
public partial class Form18 : Form
{
Rectangle Rect;
Point LocationXY;
Point LocationX1Y1;
bool IsMouseDown = false;
public Form18()
{
InitializeComponent();
}
private void Form18_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
//Clipboard image
pictureBox1.Image = Clipboard.GetImage();
}
private void picturebox1_MouseDown(object sender, MouseEventArgs e)
{
IsMouseDown = true;
LocationXY = e.Location;
}
private void picturebox1_MouseMove(object sender, MouseEventArgs e)
{
if (IsMouseDown == true)
{
LocationX1Y1 = e.Location;
Refresh();
}
}
private void picturebox1_MouseUp(object sender, MouseEventArgs e)
{
if (IsMouseDown == true)
{
LocationX1Y1 = e.Location;
IsMouseDown = false;
if (Rect != null)
{
Bitmap bit = new Bitmap(pictureBox1.Image, pictureBox1.Width, pictureBox1.Height);
Bitmap cropImg = new Bitmap(Rect.Width, Rect.Height);
Graphics g = Graphics.FromImage(cropImg);
g.DrawImage(bit, 0, 0, Rect, GraphicsUnit.Pixel);
pictureBox2.Image = cropImg;
}
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (Rect != null)
{
e.Graphics.DrawRectangle(Pens.Red, GetRect());
}
}
private Rectangle GetRect()
{
Rect = new Rectangle();
Rect.X = Math.Min(LocationXY.X, LocationX1Y1.X);
Rect.Y = Math.Min(LocationXY.Y, LocationX1Y1.Y);
Rect.Width = Math.Abs(LocationXY.X - LocationX1Y1.X);
Rect.Height = Math.Abs(LocationXY.Y - LocationX1Y1.Y);
return Rect;
}
}
输出:
这是输出结果:
在左侧 - 您可以看到屏幕截图输入,在右侧 - 您可以看到裁剪后的图像。
我不明白 - 红色标记的矩形没有正确裁剪图像? - 它显示了屏幕截图图像的不同区域。
哪里出错了?
在 PictureBox1
的 MouseUp
事件中,用一次性 Graphics
和 Bitmap
对象代替 泛洪 内存,处理 PictureBox2
的 Paint
事件并使用支持的 Graphics
对象进行绘制,只需使用 e.Graphics.DrawImage
重载来传递源矩形和目标矩形。
//...
private Point LocationXY;
private Point LocationX1Y1;
private void button1_Click(object sender, EventArgs e)
{
if (Clipboard.ContainsImage())
{
pictureBox1.Image?.Dispose();
pictureBox1.Image = Clipboard.GetImage();
}
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left)
LocationXY = e.Location;
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
LocationX1Y1 = e.Location;
pictureBox1.Invalidate();
}
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left)
{
LocationX1Y1 = e.Location;
pictureBox1.Invalidate();
pictureBox2.Invalidate();
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (MouseButtons == MouseButtons.Left)
e.Graphics.DrawRectangle(Pens.Red, GetRect());
}
private void pictureBox2_Paint(object sender, PaintEventArgs e)
{
var src = GetRect();
if (src == Rectangle.Empty) return;
var des = new Rectangle(0, 0, src.Width, src.Height);
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
e.Graphics.DrawImage(pictureBox1.Image,
des, src, GraphicsUnit.Pixel);
}
private Rectangle GetRect()
{
return new Rectangle(
Math.Min(LocationXY.X, LocationX1Y1.X),
Math.Min(LocationXY.Y, LocationX1Y1.Y),
Math.Abs(LocationXY.X - LocationX1Y1.X),
Math.Abs(LocationXY.Y - LocationX1Y1.Y)
);
}
//...
使用以下方法获取裁剪后的图像:
//...
private Bitmap GetCroppedImage()
{
var src = GetRect();
if (src == Rectangle.Empty) return null;
var des = new Rectangle(0, 0, src.Width, src.Height);
var b = new Bitmap(src.Width, src.Height);
using (var g = Graphics.FromImage(b))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.CompositingQuality = CompositingQuality.HighQuality;
g.DrawImage(pictureBox1.Image, des, src, GraphicsUnit.Pixel);
}
return b;
}
//...
然后你可以这样保存:
private void Save()
{
using (var d = new SaveFileDialog())
{
d.Filter = "PNG|*.png|JPEG|*.jpeg;*.jpg|BMP|*.bmp";
if (d.ShowDialog() != DialogResult.OK) return;
using (var b = GetCroppedImage())
{
if (b == null) return;
ImageFormat f;
switch (d.FilterIndex)
{
case 2:
f = ImageFormat.Jpeg;
break;
case 3:
f = ImageFormat.Bmp;
break;
default:
f = ImageFormat.Png;
break;
}
b.Save(d.FileName, f);
}
}
}
将SizeMode设置为Normal可能无法使用以下代码裁剪图像
Bitmap bit = new Bitmap(pictureBox1.Image, pictureBox1.Width, pictureBox1.Height);
Bitmap cropImg = new Bitmap(Rect.Width, Rect.Height);
裁剪将相对于 Picturebox 的宽度和高度。
将新的位图行更改为以下内容
Bitmap bit = new Bitmap(pictureBox1.Image, pictureBox1.Image.Width, pictureBox1.Image.Height);
Bitmap cropImg = new Bitmap(Rect.Width, Rect.Height);
或将图片框的 SizeMode 设置为 StretchImage
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;