Algorithm to resize image and maintain aspect ratio to fit iPhone
Solution 1
I think the following should give you the idea. It's not in any particular language, but rather a C-like pseudo code.
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.
}
The efficiency of this code, or what you have, won't be an issue. The time it takes to actually resize the image will dwarf the time it takes to do a couple of comparisons, two divides, and two multiplies.
Is this a "more mathematical" way to do it? I suppose, in that it collapses your four cases into two. But the approach is essentially the same.
Solution 2
Maybe a slightly shorter routine would be:
// 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;
Obviously if the ratio is > 1, then it's enlarging, if < 1 then it's shrinking.
Solution 3
Below, the simplest way I know to keep proportions. Hope it helps.
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);
Solution 4
Any one coming to this page from Google looking for ASPECT FILL not ASPECT FIT, it is simply a matter of switching the ratio selection code i.e:
Jim's answer:
resizeRatio = Min(wRatio, hRatio); //Aspect Fit
becomes
resizeRatio = Max(wRatio, hRatio); //Aspect Fill
DevProd's answer:
float ratio = ratioW < ratioH?ratioW:ratioH; //Aspect Fit
becomes
float ratio = ratioW > ratioH?ratioW:ratioH; //Aspect Fill
Alex Coplan
Hello! I'm a Computer Science student. I like all things computery, but am especially interested in Ruby (+Rails), Javascript, AI and NLP. I enjoy hacking, making anything web-related and have written a couple of iPhone apps. Other things I like: Music, especially the organ! Languages: I can speak quite a bit of German and I'm a beginner in Spanish. I have a slight obsession with Duolingo Also, before you downvote my post:
Updated on June 03, 2022Comments
-
Alex Coplan about 2 years
I'm creating a web service for an iPhone app to interact with.
When my client uploads images server-side, I want my php script to resize the image, whilst maintaining the aspect ratio, so that it will fit onto the iPhone screen. (i.e. the longest side is <= 960 and the shortest <= 640
I've created a mock-up in JS, simply because I find it easier to do quickly.
I'm pretty sure, though I may be wrong, that this isn't the most efficient way of doing it. Could someone correct me with either better logic (especially the bit at the start), or a more mathematical way of approaching this?
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); } } }
-
Kasapo almost 12 yearsI had pretty much the exact same algorithm, but it was nice to see someone else's solution to this problem-- and kudos on the note that actually performing resizing action on the image will make the algorithm's efficiency a moot point.
-
Manish Jain about 11 yearsthis algo not working for me when the image's height is 800 and width is 600 while shortsidemax is 275(vertical) and longsidemax is 480(horizontal).
-
Jim Mischel about 11 years@ManishJain: You should post a question, then, showing what you've tried and the results you're getting. Be sure to link this answer and explain that it's not working.
-
Nikola Lajic almost 10 yearsI just want to note that changing between aspect fit and aspect fill is really simple. For aspect fill just filp the sign:
float ratio = ratioW > ratioH ? ratioW : ratioH;
-
akinuri about 4 yearsThis is simpler than the other answers. Use
Math.min()
to "fit" and useMath.max()
to "fill".