Алгоритм для изменения размера изображения и поддержания пропорции для iPhone
Я создаю веб-сервис для приложения iPhone, с которым можно взаимодействовать.
Когда мой клиент загружает изображения на сервер, я хочу, чтобы мой php script изменял размер изображения, , сохраняя соотношение сторон, чтобы он поместился на экране 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);
}
}
}
Ответы
Ответ 1
Я думаю, что следующее должно дать вам эту идею. Это не на каком-либо конкретном языке, а скорее на псевдокоде 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.
}
Эффективность этого кода или того, что у вас есть, не будет проблемой. Время, необходимое для фактического изменения размера изображения, будет затмевать время, необходимое для выполнения нескольких сравнений, двух делений и двух умножений.
Это более "математический" способ сделать это? Я полагаю, что он сворачивает ваши четыре случая на два. Но подход по сути тот же.
Ответ 2
Возможно, немного более короткая процедура:
// 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, то он сокращается.
Ответ 3
Ниже, самый простой способ сохранить пропорции. Надеюсь, что это поможет.
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);
Ответ 4
Любой, приходящий на эту страницу из Google, ищущего ASPECT FILL не ASPECT FIT, это просто вопрос переключения кода выбора отношения i.e:
Джим отвечает:
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
Ответ 5
Как и ответ 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);