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

StackOverflow https://stackoverflow.com/questions/617623

  •  03-07-2019
  •  | 
  •  

Вопрос

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

<Ол>
  • 200w x 200h уменьшается на 50% и 25% отрубается сверху и снизу.

  • 200w x 100h уменьшается на 50% без обрезки.

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

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

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

    Это было полезно?

    Решение

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

    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
    

    Другие советы

    Здесь мы убеждаемся, что масштабируем только в том случае, если 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;
    }
    

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

    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 };
    
    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top