Масштабируйте изображение, чтобы полностью заполнить ограничивающую рамку - PullRequest
7 голосов
/ 06 марта 2009

Например, если мне нужно заполнить ограничивающий прямоугольник шириной 100 пикселей и высотой 50 пикселей, следующие входные изображения будут иметь следующее поведение:

  1. 200 Вт х 200 ч уменьшается на 50% и 25% отрубается сверху и Дно.

  2. 200 Вт x 100 ч сокращается на 50% без обрезки.

  3. 100 Вт х 200 ч получает не масштабируется, но 75px отрубается сверху и снизу.

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

Примет ответ на любом языке, включая псевдокод. Ссылка на страницу с ответом тоже отличная!

Ответы [ 3 ]

12 голосов
/ 06 марта 2009

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

scale = max(maxwidth/oldwidth, maxheight/oldheight)
scaledwidth = oldwidth * scale
scaledheight = oldheight * scale
if scaledheight > maxheight:
    croptop = (scaledheight - maxheight) / 2
    cropbottom = (scaledheight - maxheight) - croptop
if scaledwidth > maxwidth:
    cropleft = (scaledwidth - maxwidth) / 2
    cropright = (scaledwidth - maxwidth) - cropleft
1 голос
/ 06 марта 2009

Здесь мы удостоверяемся, что мы масштабируем, только если X больше 100%; затем, после того, как мы это сделаем, мы гарантируем, что у нас только 50 пикселей по нашему Y. Если мы больше 50, то мы берем разницу и делим на 2, чтобы убрать сумму сверху / снизу.

double percent_x = 1.0;

if(X > 100) {
 percent_x = (float)100/X;
 X *= percent_x;
 Y *= percent_x;
}

int diff_y;
int top_cut, bott_cut;
if( Y > 50 ) {
 diff_y = (Y - 50) / 2;
 top_cut = bott_cut = diff_y;
}
0 голосов
/ 27 августа 2017

В значительной степени , вдохновленный ответом Марка Рэнсома (большое спасибо - вы спасли меня). Для тех, кто хотел бы сделать это без обрезки изображения (просто вписывается в границы), я обнаружил, что это работает:

if (maxWidth > width && maxHeight > height) {
  return { width, height };
}

aspectRatio = width / height,
scale       = max(maxWidth / width, maxHeight / height);

scaledHeight = height * scale,
scaledWidth  = width * scale;

if (scaledHeight > maxHeight) {
  scaledHeight = maxHeight;
  scaledWidth  = aspectRatio * scaledHeight;
} else if (scaledWidth > maxWidth) {
  scaledWidth  = maxWidth;
  scaledHeight = scaledWidth / aspectRatio;
}

return { scaledHeight, scaledWidth };
...