Изменение размера нарисованного прямоугольника в соответствии с исходным изображением
Я разрабатываю приложение для управления изображениями, отсканированными на широкоформатном сканере. Эти изображения показаны как 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 выходных пикселя.