Уменьшение прямоугольника для отображения так, как оно будет выглядеть на большом исходном изображении - PullRequest
0 голосов
/ 24 декабря 2018

Я отображаю изображение в формате PictureBox и позволяю пользователю указать область на изображении, указав ширину и высоту прямоугольника. Расположение прямоугольника определяется программно.

Изображение, отображаемое в графическом окне, уменьшается для экономии времени обработки. Так, если пользователь указывает прямоугольник 200X200, он может выглядеть большим на предварительном изображении, но на исходном изображении он будет очень маленьким, а может быть довольно большим..

Как можно уменьшить или перевести прямоугольник, чтобы показать, как он будет выглядеть на большом изображении. В настоящее время я использую следующий код для масштабирования прямоугольника на большом изображении.

Rectangle ConvertToLargeRect(Rectangle smallRect, Size largeImageSize, Size smallImageSize)
{
    double xScale = (double)largeImageSize.Width / smallImageSize.Width;
    double yScale = (double)largeImageSize.Height / smallImageSize.Height;
    int x = (int)(smallRect.X * xScale + 0.5);
    int y = (int)(smallRect.Y * yScale + 0.5);
    int right = (int)(smallRect.Right * xScale + 0.5);
    int bottom = (int)(smallRect.Bottom * yScale + 0.5);
    return new Rectangle(x, y, right - x, bottom - y);
}

ОБНОВЛЕНИЕ: enter image description here enter image description here

1 Ответ

0 голосов
/ 24 декабря 2018

Я буду использовать следующие методы:

  • TranslatePictureBoxSelectedRectangleToImage
    Преобразует выбранный прямоугольник в графическом окне в координаты на изображении.

  • TranslateImageSelectedRectangleToPictureBox
    Переводит выбранный прямоугольник в окне изображения в координаты в окне изображения.

  • ScaleRectangle
    Масштабирование прямоугольника по заданному масштабуfactor.

TranslatePictureBoxSelectedRectangleToImage

public RectangleF TranslatePictureBoxSelectedRectangleToImage(PictureBox p, 
    RectangleF pictureBoxSelectedRectangle)
{
    var method = typeof(PictureBox).GetMethod("ImageRectangleFromSizeMode",
        System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
    var imageRect = (Rectangle)method.Invoke(p, new object[] { p.SizeMode });
    if (p.Image == null)
        return pictureBoxSelectedRectangle;
    var cx = (float)p.Image.Width / (float)imageRect.Width;
    var cy = (float)p.Image.Height / (float)imageRect.Height;
    var r2 = pictureBoxSelectedRectangle;
    r2.Offset(-imageRect.X, -imageRect.Y);
    return new RectangleF(r2.X * cx, r2.Y * cy, r2.Width * cx, r2.Height * cy);
}

TranslateImageSelectedRectangleToPictureBox

public RectangleF TranslateImageSelectedRectangleToPictureBox(PictureBox p, 
    RectangleF imageSelectedRectangle)
{
    var method = typeof(PictureBox).GetMethod("ImageRectangleFromSizeMode",
        System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
    var imageRect = (Rectangle)method.Invoke(p, new object[] { p.SizeMode });
    if (p.Image == null)
        return imageSelectedRectangle;
    var cx = (float)p.Image.Width / (float)imageRect.Width;
    var cy = (float)p.Image.Height / (float)imageRect.Height;
    var r2 = new RectangleF(imageSelectedRectangle.X / cx, imageSelectedRectangle.Y / cy,
        imageSelectedRectangle.Width / cx, imageSelectedRectangle.Height / cy);
    r2.Offset(imageRect.X, imageRect.Y);
    return r2;
}

ScaleRectangle

public RectangleF ScaleRectangle(RectangleF r, float c)
{
    return new RectangleF(r.X * c, r.Y * c, r.Width * c, r.Height * c);
}

Пример

Использование вышеуказанных методов со следующими допущениями:

  • У вас есть image1 в исходном размере и image2, что являетсяпрограммно измененная версия image1 с коэффициентом масштабирования c.(Это означает c = (float)image2.Width/(float)image1.Width.)
  • Вы показываете image2 в графическом окне в режиме масштабирования.

Вопрос 1 - Имея r1 в качестве выделенного прямоугольника на picureBox1, каков размер и расположение прямоугольника на image1?

ПервыйМетод показывает, как вы можете преобразовать r1 в графическом окне в прямоугольник в image2.Чтобы преобразовать его в прямоугольник в image1, поскольку вы знаете коэффициент масштабирования, который вы использовали для создания image2 из image1, достаточно применить тот же коэффициент масштабирования к результату первого метода:

//First convert rectangle of pictureBox1 to rectangle of image2
var r2 = TranslatePictureBoxSelectedRectangleToImage(pictureBox1, r1);

//Then convert rectangle of image2 to rectangle of image1
var result = ScaleRectangle(r2, 1f/c);

Вопрос 2 - Имея r1 в качестве выделенного прямоугольника на image1, каков размер и расположение прямоугольника на pictureBox1?

Второй метод показывает, как можно преобразовать r1 вimage2, прямоугольнику на pictureBox1.Для преобразования из прямоугольника в image1, поскольку вы знаете коэффициент масштабирования, который вы использовали для создания изображения2 из изображения1, достаточно применить тот же коэффициент масштабирования к r1, чтобы получить прямоугольник для image2, а затем использовать второеМетод:

//First convert rectangle of the image1 to rectangle of image2
var r2 = ScaleRectangle(r1, c);

//Then convert rectangle of image2 to rectangle of pictureBox1
var result = TranslateImageSelectedRectangleToPictureBox(pictureBox1, r2);
...