Обрезка изображения не обрезается правильно - PullRequest
1 голос
/ 26 марта 2020

Я следовал учебному пособию 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

Ответы [ 2 ]

4 голосов
/ 26 марта 2020

Вместо переполнение памяти с одноразовыми объектами Graphics и Bitmap в событии 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

0 голосов
/ 26 марта 2020

Установка SizeMode на Normal может не обрезать изображение со следующим кодом

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

Обрезка будет относительно ширины и высоты Picturebox.

Измените новую строку Bitmap на следующие

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

ИЛИ Установите для параметра SizeMode для Picturebox значение StretchImage

this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
...