Как сделать новые данные координаты пропорциональными старым? - PullRequest
0 голосов
/ 17 ноября 2011

У меня есть какой-то объект. Он имеет некоторые оригинальные ширину и высоту. Мне дают новые ширину и высоту. Как принять новые заданные ширину и высоту для объекта оригинальных? (Скажем, у нас был квадрат 1000x1000, и нам были даны некоторые желаемые максимально возможные координаты, скажем 1900x1200, какой алгоритм будет производить 1200x1200 из него? он должен вернуть 400x400 ...)

Итак, я начал пытаться создать код, который бы изменял его, но потерпел неудачу с:

void resize_coefs(const int & original_w, const int & original_h, int & new_w, int & new_h)
{
    double VW = new_w; 
    double VH =  new_h;

    double rw = original_w/VW;
    double rh = original_h/VH;
    if (rw>=rh){
        new_h = VH;
        new_w = rh*new_w + 2;

    }
    else
    {
        new_w = VW;
        new_h= rw*new_h;
    }
}

Ответы [ 2 ]

3 голосов
/ 17 ноября 2011

Сделайте так:

  1. Рассчитать коэффициент масштабирования для ширины.
  2. Рассчитать масштабный коэффициент для высоты.
  3. Используйте наименьший коэффициент масштабирования для масштабирования ширины и высоты.

Пример кода:

void resize_coefs(const int original_w, const int original_h, int & new_w, int & new_h)
{
    double scale = std::min(
        ((double) new_w) / original_w ,
        ((double) new_h) / original_h );
    new_w = std::min( scale * original_w, new_w );
    new_h = std::min( scale * original_h, new_h );
}

Из-за возможных ошибок округления рекомендуется проверить, что new_w и new_h все еще находятся в границах после масштабирования.

РЕДАКТИРОВАТЬ: Вот версия, которая делает то же самое только с целочисленной арифметикой, используя подсказку, предоставленную Керреком в своем ответе. Немного трудно понять, что он придерживается точно такой же логики.

void resize_coefs(const int original_w, const int original_h, int & new_w, int & new_h)
{
    int num, den;
    if (new_w * original_h < new_h * original_w) {
        num = new_w;
        den = original_w;
    } else {
        num = new_h;
        den = original_h;
    }
    new_w = original_w * num / den;
    new_h = original_h * num / den;
}
1 голос
/ 17 ноября 2011

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

const double orig_width, orig_height;
const double max_new_width, max_new_height;

const double orig_ar = orig_width / orig_height;
const double new_ar = max_new_width / max_new_height;

const double scale = new_ar < orig_ar ? max_new_width / orig_width : max_new_height / orig_height;

const double new_height = orig_height * scale;
const double new_width  = orig_width  * scale;

Вы можете сделать это полностью с целыми числами, если хотите. Помните, что a/b == c/d эквивалентно a*d == b*c (и вам даже не нужно беспокоиться о нуле в знаменателе).

Обновление: Вот конкретная целочисленная функция, которую я бы использовал:

void scale(unsigned int orig_width, unsigned int orig_height,
           unsigned int max_new_width, unsigned int max_new_height)
{
  const bool scale_width = max_new_width * orig_height < orig_width * max_new_height;

  const unsigned int new_height = scale_width ?
                                  orig_height * max_new_width / orig_width :
                                  orig_height * max_new_height / orig_height;
  const unsigned int new_width  = scale_width ?
                                  orig_width  * max_new_width / orig_width :
                                  orig_width  * max_new_height / orig_height;

  std::cout << "New dims: " << new_width << " x " << new_height << std::endl;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...