Как «умно изменить размер» отображаемого изображения с исходным соотношением сторон - PullRequest
10 голосов
/ 09 июня 2010

У меня есть приложение, в котором конечные пользователи могут определять размер и расположение изображений в конструкторе.Поскольку спецификация требует, чтобы изображение было «растянуто» до содержащего элемента управления, конечный пользователь может получить неуклюже растянутое изображение.

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

Самый быстрый способ решить эту проблему состоит в том, чтобы на самом деле предоставить две опции: 1) масштабирование по ширине 2)масштаб с высоты.Пользователь выбирает метод, а алгоритм регулирует размер изображения, используя исходное соотношение сторон.Например: изображение отображается в конструкторе в формате 200x200, а исходное изображение - 1024x768 пикселей.Пользователь выбирает «Smart Size from width», и новый размер становится ~ 200x150, поскольку исходное соотношение сторон составляет ~ 1.333

Это нормально, но как я могу сделать алгоритм умнее и не беспокоить пользователя, спрашивая, какое измерениепересчет должен быть основан на?

Ответы [ 10 ]

26 голосов
/ 09 июня 2010

Если я правильно интерпретирую вашу спецификацию, вы хотите, чтобы результат был не больше, чем тот, который изначально выложил конечный пользователь; Вы хотите, чтобы одно из двух измерений сократилось, а другое осталось прежним. Другими словами, новый размер должен заполнить пространство конструктора в одном направлении, а укороченный размер - в другом направлении, чтобы сохранить исходное соотношение сторон.

original_ratio = original_width / original_height
designer_ratio = designer_width / designer_height
if original_ratio > designer_ratio
    designer_height = designer_width / original_ratio
else
    designer_width = designer_height * original_ratio

Часто вы будете работать с целочисленными координатами, но деления для получения вышеуказанных соотношений должны быть с плавающей точкой. Вот перестановка формулы, чтобы она была более целочисленной. Убедитесь, что у ваших целых чисел есть диапазон для обработки максимальной ширины * высоты.

if original_width * designer_height > designer_width * original_height
    designer_height = (designer_width * original_height) / original_width
else
    designer_width = (designer_height * original_width) / original_height
9 голосов
/ 11 сентября 2012

Вот решение, которое я придумала, когда приходится иметь дело с этой проблемой.Получился довольно короткий и понятный имо, просто хотел поделиться им.

Удобные «формулы»: ratio = W / H W = H * ratio H = W / ratio

  1. Рассчитайте соотношение.
  2. Рассчитайте высоту изображения, если вы установите ширину для нового размера ширины (максимально допустимая ширина).
  3. Рассчитайте ширинуизображение, если вы установите высоту нового размера (максимально допустимая высота).
  4. Посмотрите, какой из двух размеров не перекрывает максимальный размер в любом измерении.Если отношение не равно 1, один из них всегда будет неправильным, а один всегда будет правильным.

В Javascript

// Returns array with new width and height
function proportionalScale(originalSize, newSize)
{
    var ratio = originalSize[0] / originalSize[1];

    var maximizedToWidth = [newSize[0], newSize[0] / ratio];
    var maximizedToHeight = [newSize[1] * ratio, newSize[1]];

    if (maximizedToWidth[1] > newSize[1]) { return maximizedToHeight; }
    else { return maximizedToWidth; }
}

originalSize иnewSize - это массив [0] = width, [1] = height

2 голосов
/ 16 февраля 2013

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

def _resize (image, sizes, rotate = None): "" "Изменяет размер изображения, чтобы оно было как можно ближе к указанномуразмеры. Изображение представляет собой поле-модель-изображение django.

    Will both scale up and down the image to meet this while keeping the proportions
    in width and height

"""

if image and os.path.isfile(image.path):

    im = pil.open(image.path)
    logging.debug('resizing image from %s x %s --> %s x %s ' % (im.size[0], im.size[1], dimensions[0], dimensions[1]))

    if rotate:
        logging.debug('first rotating image %s' % rotate)
        im = im.rotate(90)

    srcWidth = Decimal(im.size[0])
    srcHeight = Decimal(im.size[1])

    resizeWidth = srcWidth
    resizeHeight = srcHeight

    aspect = resizeWidth / resizeHeight # Decimal

    logging.debug('resize aspect is %s' % aspect)

    if resizeWidth > dimensions[0] or resizeHeight > dimensions[1]:
        # if width or height is bigger we need to shrink things
        if resizeWidth > dimensions[0]:
            resizeWidth = Decimal(dimensions[0])
            resizeHeight = resizeWidth / aspect

        if resizeHeight > dimensions[1] :
            aspect = resizeWidth / resizeHeight
            resizeHeight = Decimal(dimensions[1])
            resizeWidth = resizeHeight * aspect

    else:
        # if both width and height are smaller we need to increase size
        if resizeWidth < dimensions[0]:
            resizeWidth = Decimal(dimensions[0])
            resizeHeight = resizeWidth / aspect

        if resizeHeight > dimensions[1] :
            aspect = resizeWidth / resizeHeight
            resizeHeight = Decimal(dimensions[1])
            resizeWidth = resizeHeight * aspect

    im = im.resize((resizeWidth, resizeHeight), pil.ANTIALIAS)

    logging.debug('resized image to %s %s' % im.size)
    im.save(image.path)

else:
    # no action, due to no image or no image in path
    pass

return image
2 голосов
/ 13 апреля 2011

Там нет учета количества копий и наклеек, а!Я также хотел знать это, и все, что я видел, было бесконечными примерами масштабирования ширины ИЛИ высоты .. кто хотел бы, чтобы другое переполнение было!

Не превышает исходные размеры изображений Используется математическая схема, которая работает правильно, например, ширина / аспект по высоте и высота * аспект по ширине, поэтому изображения фактически масштабируются должным образом вверх и вниз: /

//////////////

private void ResizeImage(Image img, double maxWidth, double maxHeight)
{
    double srcWidth = img.Source.Width;
    double srcHeight = img.Source.Height;

    double resizeWidth = srcWidth;
    double resizeHeight = srcHeight;

    double aspect = resizeWidth / resizeHeight;

    if (resizeWidth > maxWidth)
    {
        resizeWidth = maxWidth;
        resizeHeight = resizeWidth / aspect;
    }
    if (resizeHeight > maxHeight)
    {
        aspect = resizeWidth / resizeHeight;
        resizeHeight = maxHeight;
        resizeWidth = resizeHeight * aspect;
    }

    img.Width = resizeWidth;
    img.Height = resizeHeight;
}
1 голос
/ 15 мая 2017

Мое решение уменьшить и увеличить размер в javascript на основе https://stackoverflow.com/a/5654847/1055015

var scale =  function (srcWidth, srcHeight, maxWidth, maxHeight) {

      let resizeWidth  = srcWidth;
      let resizeHeight = srcHeight;

      let aspect = resizeWidth / resizeHeight;
      let scaleX = maxWidth / srcWidth;
      let scaleY = maxHeight / srcHeight;
      let scale  = Math.min(scaleX, scaleY);

      resizeWidth *= scale;
      resizeHeight *= scale;

      if (resizeWidth > maxWidth) {
        resizeWidth  = maxWidth;
        resizeHeight = resizeWidth / aspect;
      }

      if (resizeHeight > maxHeight) {
        aspect       = resizeWidth / resizeHeight;
        resizeHeight = maxHeight;
        resizeWidth  = resizeHeight * aspect;
      }

      return {
        width : resizeWidth,
        height: resizeHeight,
      };
    }
1 голос
/ 09 июня 2010

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

if (width > height) {
    scaledWidth = 200;
    scaledHeight = (height * 200) / width;
} else {
    scaledHeight = 200;
    scaledWidth = (width * 200) / height;
}
1 голос
/ 09 июня 2010

Рассчитайте новые размеры для обоих вариантов («масштаб по ширине» и «масштаб по высоте»), а затем используйте тот, который подходит на дисплее.

В качестве альтернативы вы также можете рассчитать соотношение сторон «ограничительной рамки» и сравнить его с соотношением сторон исходного изображения. В зависимости от того, какое соотношение сторон больше, высоту или ширину необходимо масштабировать.

Вы также можете ограничить процесс изменения размера, чтобы во всех случаях выполнялось «масштабирование по ширине». Затем, чтобы изменить размер изображения, пользователь всегда должен изменить его ширину. Высота всегда будет регулироваться автоматически.

0 голосов
/ 22 января 2017

Я использовал этот способ, чтобы изменить размер изображения до FHD.

if ( width >= height) {
  var original_ratio = width / height
  new_width = 1080 * original_ratio
  console.log("new new_width = " + Math.round(new_width) );
  console.log("new new_height = 1080");
} else {
  var original_ratio =  height / width
  new_height = 1080 * original_ratio
  console.log("new new_height = " + Math.round(new_height) );
  console.log("new new_width = 1080");
}

Вы можете изменить 1080 на новый размер.

Я надеюсь, что это будет полезно для кого-то по крайней мере.

0 голосов
/ 18 марта 2013

вот мое решение,

a = аспект sw = ширина исходного изображения sh = высота исходного изображения dw = запрошенная максимальная ширина dh = запрошенная максимальная высота

sw и sh будет содержать окончательный вариантизмененные значения

код PHP:

$a = $sw / $sh;

if($a > 1){
    //  wider image
    if($sw != $dw){
        $rt = $dw / $sw;
        $sw = $sw * $rt;
        $sh = $sh * $rt;
    }

    if($sh > $dh){
        $rt = $dh / $sh;
        $sw = $sw * $rt;
        $sh = $sh * $rt;
    }
}else{
    //  taller image
    if($sh != $dh){
        $rt = $dh / $sh;
        $sh = $sh * $rt;
        $sw = $sw * $rt;
    }

    if($sw > $dw){
        $rt = $dw / $sw;
        $sh = $sh * $rt;
        $sw = $sw * $rt;
    }
}
0 голосов
/ 09 июня 2010

Вам просто нужно определить масштаб, необходимый для обоих измерений, а затем взять меньшее из 2.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...