Изменение размера нарисованного прямоугольника в соответствии с исходным изображением

Я разрабатываю приложение для управления изображениями, отсканированными на широкоформатном сканере. Эти изображения показаны как ImageBrush на Canvas, На этом Canvas они могут сделать Rectangle с помощью мыши, чтобы определить область обрезки.

Моя проблема заключается в том, чтобы изменить размер Rectangle в соответствии с исходным размером изображения, чтобы обрезать точную область исходного изображения.

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

Размеры исходного изображения:

ч: 5606
ш: 7677

И когда я показываю изображение, они:

ч: 1058,04
ш: 1910

Что дает эти цифры:

float percentWidth = ((originalWidth - resizedWidth) / originalWidth) * 100;
float percentHeight = ((originalHeight - resizedHeight) / originalHeight) * 100;

percentWidth = 75,12049
percentHeight = 81,12665

Отсюда я не могу понять, как изменить размер Rectangle правильно, чтобы соответствовать исходному изображению.

Мой последний подход был такой:

int newRectWidth = (int)((originalWidth * percentWidth) / 100);
int newRectHeight = (int)((originalHeight * percentHeight) / 100);
int newRectX = (int)(rectX + ((rectX * percentWidth) / 100));
int newRectY = (int)(rectY + ((rectY * percentHeight) / 100));

Надеюсь, кто-то может привести меня в правильном направлении, потому что я не в курсе, и я не вижу, что мне не хватает.

Решение

    private System.Drawing.Rectangle FitRectangleToOriginal(
        float resizedWidth,
        float resizedHeight,
        float originalWidth,
        float originalHeight,
        float rectWidth,
        float rectHeight,
        double rectX,
        double rectY)
    {
        // Calculate the ratio between original and resized image
        float ratioWidth = originalWidth / resizedWidth;
        float ratioHeight = originalHeight / resizedHeight;

        // create a new rectagle, by resizing the old values
        // by the ratio calculated above
        int newRectWidth = (int)(rectWidth * ratioWidth);
        int newRectHeight = (int)(rectHeight * ratioHeight);
        int newRectX = (int)(rectX * ratioWidth);
        int newRectY = (int)(rectY * ratioHeight);

        return new System.Drawing.Rectangle(newRectX, newRectY, newRectWidth, newRectHeight);
    }

2 ответа

Решение

Вы на самом деле делаете форму проекции. Не используйте проценты, просто используйте соотношение между 5606 и 1058,4 = ~5,30. Когда пользователь перетаскивает прямоугольник, перепроектируйте его, который selectedWidth * 5606/1058.4,

Я думаю, что единственный надежный вариант - позволить вашим пользователям увеличивать изображение (уровень масштабирования 100% или выше) и делать выбор на части изображения. Таким образом, они могут сделать точный выбор на основе пикселей. (Предполагая, что целью вашего прямоугольника выделения является выделение части изображения.)

Теперь ваша проблема заключается в том, что вы используете вычисления с плавающей запятой, поскольку уровень масштабирования 75% и ошибки округления сделают ваши прямоугольники выбора неточными. Независимо от того, что вы делаете, когда вы пытаетесь сделать выделение на сжатом изображении, вы не выбираете точные пиксели - вы выбираете части пикселей при изменении размера прямоугольника. Поскольку частичный пиксель не может быть выбран, края выделения будут округлены в большую или меньшую сторону, поэтому вы либо выбираете один пиксель слишком много или один пиксель слишком мало в заданном направлении.

Еще одна проблема, которую я только что заметил, заключается в том, что вы искажаете изображение - по горизонтали это 75% -ое увеличение, по вертикали это 81%. Это делает его еще сложнее для пользователей, потому что изображение будет сглаживаться по-разному в двух направлениях. По горизонтали 4 исходных пикселя будут интерполированы на 3 выходных пикселя; по вертикали 5 исходных пикселей будут интерполированы на 4 выходных пикселя.

Другие вопросы по тегам