Как я могу преобразовать координаты XY и высоту / ширину на масштабированном изображении в изображение оригинального размера? - PullRequest
10 голосов
/ 14 февраля 2011

Схожий вопрос

Я пытаюсь сделать то же самое, что и в связанном вопросе, но с C #. Я показываю масштабированное изображение и позволяю пользователю выбрать область для обрезки. Однако я не могу просто взять координаты x1y1, x2y2 из выделенного масштабированного изображения и обрезать их из оригинала. Я попытался сделать некоторую основную математику, как в другом вопросе, но это, очевидно, также не правильный подход (он определенно ближе)

Редактировать

Размеры исходного изображения: w = 1024 h = 768

Размеры масштабированного изображения: w = 550 h = 412

Я начинаю с изображения, скажем, 1024x768. Я хочу, чтобы он поместился как можно больше в коробке 550х550. Я использую следующий метод, чтобы получить масштабированный размер изображения (при сохранении соотношения сторон). Затем я делаю базовое изменение размеров для этих новых измерений.

Что касается области выбора, она может быть от (0,0) до (100 100).

private static Rectangle MaintainAspectRatio(Image imgPhoto, Rectangle thumbRect)
{
    int sourceWidth = imgPhoto.Width; int sourceHeight = imgPhoto.Height; int sourceX = 0; int sourceY = 0; int destX = 0; int destY = 0;

    float nPercent = 0;
    float nPercentW = 0;
    float nPercentH = 0;

    nPercentW = ((float)thumbRect.Width / (float)sourceWidth);
    nPercentH = ((float)thumbRect.Height / (float)sourceHeight);

    //if we have to pad the height pad both the top and the bottom
    //with the difference between the scaled height and the desired height
    if (nPercentH < nPercentW)
    {
        nPercent = nPercentH;
        destX = (int)((thumbRect.Width - (sourceWidth * nPercent)) / 2);
    }
    else
    {
        nPercent = nPercentW;
        destY = (int)((thumbRect.Height - (sourceHeight * nPercent)) / 2);
    }

    int destWidth = (int)(sourceWidth * nPercent);
    int destHeight = (int)(sourceHeight * nPercent);

    Rectangle retRect = new Rectangle(thumbRect.X, thumbRect.Y, destWidth, destHeight);
    return retRect;
}

Ответы [ 2 ]

9 голосов
/ 14 февраля 2011

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

Возьмите простой примерсетки 12x12 в качестве оригинала и сетки 4x4 в качестве масштабированной версии.
- (1,1) :( 2,2) в масштабированной версии = (3,3) :( 8,8)
- 2x2 пикселя = 25% площади масштабированной версии
- 6x6 пикселей = 25% площади оригинальной версии

Если бы нужно было просто умножить на те же коэффициенты масштабирования, это быgive (3,3) :( 6,6).


OriginalTop = INT (ScaledTop * YScalingFactor);
OriginalLeft = INT (ScaledLeft * XScalingFactor);

OriginalBottom = INT ((ScaledBottom + 1) * YScalingFactor) - 1;
OriginalRight = INT ((ScaledRight + 1) * XScalingFactor) - 1;


РЕДАКТИРОВАТЬ :

Лучший способ объяснить, что я пытаюсь сказать, - нарисовать изображение.И я сосу в ASCII Art.Итак, вот еще одна попытка со словами.

Пиксель не точка.Это маленький прямоугольник в своем собственном правом.

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

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


При повторном использовании примера (12x12) => (4x4) каждый масштабированный пиксель представляет собой весь набор пикселей 3x3 в оригинале.Говоря о верхнем левом углу, вы выбираете верхний левый пиксель группы пикселей 3х3 в оригинале.А если говорить о правом нижнем углу, вы выбираете нижний правый размер группы пикселей 3x3 в оригинале.


РЕДАКТИРОВАТЬ : использовать только целые числа.

NewTop    = ((   OldTop    ) * NewHeight / OldHeight);
NewLeft   = ((   OldLeft   ) * NewWidth  / OldWidth );

NewBottom = ((OldBottom + 1) * NewHeight / OldHeight) - 1;
NewRight  = ((OldRight  + 1) * NewWidth  / OldWidth ) - 1;


Единственное соображение - убедиться, что вы не переполнили свой тип данных после умножения.Но с изображениями вы не будете, если это не адское изображение.

0 голосов
/ 14 февраля 2011

Вы можете получить проценты для масштабированных изображений и превратить их обратно в координаты для немасштабированного изображения:

pX1 = scaledX1/scaled_width
pY1 = scaledY1/scaled_height

unscaledX1 = ceiling(unscaled_width * pX1)
unscaledY1 = ceiling(unscaled_height * pY1)
...