裁剪图像未正确裁剪

问题描述 投票:1回答:2

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

c# .net winforms drawing
2个回答
1
投票

而不是floodingGraphicsBitmap事件中使用一次性对象,例如MouseUpPictureBox1对象的内存,处理PaintPictureBox2事件并使用支持的[ C0]对象绘制,只需使用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 des = GetRect();

    if (des == Rectangle.Empty) return null;

    var src = pictureBox1.ClientRectangle;
    var b = new Bitmap(des.Width, des.Height);

    using (var g = Graphics.FromImage(b))
    {
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        g.SmoothingMode = SmoothingMode.HighQuality;
        g.CompositingQuality = CompositingQuality.HighQuality;

        g.DrawImage(pictureBox1.Image, new Rectangle(0, 0, des.Width, des.Height), des, 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) { var b = GetCroppedImage(); if (b != null) { 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); } } } }


0
投票

将SizeMode设置为Normal可能无法使用以下代码裁剪图像

SOQ60819266

裁剪将相对于Picturebox的宽度和高度。

将新的位图行更改为以下内容

Bitmap bit = new Bitmap(pictureBox1.Image, pictureBox1.Width, pictureBox1.Height);
Bitmap cropImg = new Bitmap(Rect.Width, Rect.Height);

或将图片框的SizeMode设置为StretchImage

Bitmap bit = new Bitmap(pictureBox1.Image, pictureBox1.Image.Width, pictureBox1.Image.Height);
Bitmap cropImg = new Bitmap(Rect.Width, Rect.Height);
© www.soinside.com 2019 - 2024. All rights reserved.