c# - 裁剪图像未正确裁剪

标签 c# .net winforms drawing

我遵循了有关如何创建裁剪图像应用程序的 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;
    }

}

输出:

这是输出:

在左侧 - 您可以看到屏幕截图输入,在右侧 - 您可以看到裁剪后的图像。

我不明白 - 用红色标记的矩形没有正确裁剪图像? - 它显示屏幕截图图像的不同区域。

哪里出了问题?

Screenshot

最佳答案

而不是用一次性的淹没内存 GraphicsBitmap MouseUp 中的对象事件PictureBox1 ,处理Paint事件PictureBox2并使用支持的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);
        }
    }
}

SOQ60819266

关于c# - 裁剪图像未正确裁剪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60866406/

相关文章:

c# - 派生类中的无意基类构造函数 "hiding"

c# - Linq 执行不区分大小写的比较

c# - 如何获取复制文件进度

c# - EntityFramework Linq To Entities 位域/ bool 问题

.net - 由于Windows Update Create4()上出现kb4340556 : VBA COM . NET Automation错误

desktop-application - NoSQL 是否适合桌面应用程序的数据解决方案?

c# - 使用相同的名称/命名空间实例化不同的类

c# - C# 中的冗余?

c# - 在 C# GUI 应用程序中将远程 Mysql 数据库同步到本地

c# - 删除调整大小的能力