Алгоритм изменения размера изображения и поддержания соотношения сторон, чтобы соответствовать iPhone - PullRequest
11 голосов
/ 23 октября 2011

Я создаю веб-сервис для взаимодействия с приложением iPhone.

Когда мой клиент загружает изображения на сервер, я хочу, чтобы мой php-скрипт изменил размер изображения, , сохраняя при этом аспектсоотношение , чтобы оно поместилось на экране iPhone.(т. е. самая длинная сторона <= 960, а самая короткая <= 640 </p>

. Я создал макет в JS просто потому, что мне проще это сделать быстро.

I 'Я вполне уверен, хотя я могу ошибаться, что это не самый эффективный способ сделать это. Может ли кто-нибудь исправить меня либо с помощью лучшей логики (особенно с самого начала), либо с помощью более математического подхода к этому?

var w = 960, h = 960, new_w, new_h;
if (w >= h && w > 960 || h >= w && h > 960 || w >= h && h > 640 || h >= w && w > 640) {
    if (w > h) {
        if (w>960) {
            new_w = 960;
            new_h = h*(new_w/w);
        }
        if (h>640) {
            new_h = 640;
            new_w = w*(new_h/h);
        }
    }
    else {
        if (h>960) {
            new_h = 960;
            new_w = w*(new_h/h);
        }
        if (w>640) {
            new_w = 640;
            new_h = h*(new_w/w);
        }
    }
}

Ответы [ 5 ]

41 голосов
/ 25 апреля 2012

Может быть, более короткая процедура будет выглядеть следующим образом:

// Calculate resize ratios for resizing 
float ratioW = targetWidth / oldWidth; 
float ratioH = targetHeight / oldHeight;

// smaller ratio will ensure that the image fits in the view
float ratio = ratioW < ratioH?ratioW:ratioH;

newWidth = oldWidth*ratio;
newHeight = oldHeight*ratio;

Очевидно, что если отношение составляет> 1, то оно увеличивается, если <1, то уменьшается. </p>

24 голосов
/ 23 октября 2011

Я думаю, что следующее должно дать вам идею.Это не на каком-то конкретном языке, а скорее на псевдокод, похожий на Си.

shortSideMax = 640;
longSideMax = 960;
function Resize(image)
{
    if (image.width >= image.height)
    {
        if (image.width <= longSideMax && image.height <= shortSideMax)
            return image;  // no resizing required
        wRatio = longSideMax / image.width;
        hRatio = shortSideMax / image.height;
    }
    else
    {
        if (image.height <= longSideMax && image.width <= shortSideMax)
            return image; // no resizing required
        wRatio = shortSideMax / image.width;
        hRatio = longSideMax / image.height;
    }

    // hRatio and wRatio now have the scaling factors for height and width.
    // You want the smallest of the two to ensure that the resulting image
    // fits in the desired frame and maintains the aspect ratio.
    resizeRatio = Min(wRatio, hRatio);

    newHeight = image.Height * resizeRatio;
    newWidth = image.Width * resizeRatio;

    // Now call function to resize original image to [newWidth, newHeight]
    // and return the result.
}

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

Является ли это «более математическим» способом сделать это?Я полагаю, в этом ваши четыре дела разбиты на два.Но подход по сути тот же.

7 голосов
/ 10 октября 2013

Ниже приведен самый простой из известных мне способов сохранения пропорций. Надеюсь, это поможет.

Javascript

function resize(width, height, maxWidth, maxHeight) {
    var ratio = Math.min(maxWidth / width, maxHeight / height);
    var newWidth = ratio * width;
    var newHeight = ratio * height;

    console.log(newWidth + ' ' + newHeight); // Test

    // Process resizing...
}

resize(1280, 1024, 600, 300);

PHP

function resize($width, $height, $maxWidth, $maxHeight) {
    $ratio = min(array($maxWidth / $width, $maxHeight / $height));
    $newWidth = $ratio * $width;
    $newHeight = $ratio * $height;

    echo $newWidth . ' ' . $newHeight; // Test

    // Process resizing...
}

resize(1600, 1280, 150, 150);
3 голосов
/ 16 июня 2014

Любой, кто приходит на эту страницу из Google, ищет ASPECT FILL , а не ASPECT FIT , это просто вопрос переключения кода выбора соотношения, например:

Ответ Джима:

resizeRatio = Min(wRatio, hRatio); //Aspect Fit

становится

resizeRatio = Max(wRatio, hRatio); //Aspect Fill

Ответ DevProd:

float ratio = ratioW < ratioH?ratioW:ratioH; //Aspect Fit

становится

float ratio = ratioW > ratioH?ratioW:ratioH; //Aspect Fill
0 голосов
/ 07 марта 2015

Аналогично ответу DevProd, но я изо всех сил пытался следовать ему сам из-за соглашения об именах.Надеюсь, это немного понятнее:

Как мне лучше всего разместить носитель (фотографию) внутри контейнера?

//Define media size and container size
int mediaWidth = 600;
int mediaHeight = 600;
int containerWidth = 1024;
int containerHeight= 768;

//Calculate best fit (whichever dimension has a smaller 'fit')
float wFits   = containerWidth  / mediaWidth;
float hFits   = containerHeight / mediaHeight;
float minFits = wFits > hFits ? hFits : wFits;

//The new size of the media, best-fit'ing inside the container
int width  = (int) (mediaWidth*minFits);
int height = (int) (mediaHeight*minFits);
...