Search code examples
phpalgorithmimageresizeaspect-ratio

Algorithm to resize image and maintain aspect ratio to fit iPhone


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

Solution

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