Алгоритм для изменения размера изображения и поддержания пропорции для iPhone

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

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

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

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

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); } } } 

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

 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. } 

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

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

Может быть, немного более короткая рутина будет:

 // 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, то оно сокращается.

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

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); 

Любой, приходящий на эту страницу от 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 

Как и ответ 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);