Joshxtothe4
Joshxtothe4

Reputation: 4201

Arbitrary image resizing in PHP

What would be the best way to resize images, which could be of any dimension, to a fixed size, or at least to fit within a fixed size?

The images come from random urls that are not in my control, and I must ensure the images do not go out of an area roughly 250px x 300px, or 20% by 50% of a layer.

I would think that I would first determine the size, and if it fell outside the range, resize by a factor, but I am unsure how to work out the logic to resize if the image size could be anything.

edit:I do not have local access to the image, and the image url is in a variable with is output with img src=..., I need a way to specify the values of width and height tags.

Upvotes: 3

Views: 4350

Answers (6)

TravisO
TravisO

Reputation: 9550

I created the following function to do intelligent resizing of images with respect to ratio and even has a parameter to upscale smaller images (which is critical if your HTML layout screws up when thumbnails are wierd sizes).

function ImageIntelligentResize( $imagePath, $maxWidth, $maxHeight, $alwaysUpscale )
{
    // garbage in, garbage out
    if ( IsNullOrEmpty($imagePath) || !is_file($imagePath) || IsNullOrEmpty($maxWidth) || IsNullOrEmpty($maxHeight) )
    {
        return array("width"=>"", "height"=>"");
    }

    // if our thumbnail size is too big, adjust it via HTML
    $size = getimagesize($imagePath);
    $origWidth = $size[0];
    $origHeight = $size[1];

    // Check if the image we're grabbing is larger than the max width or height or if we always want it resized
    if ( $alwaysUpscale || $origWidth > $maxWidth || $origHeight > $maxHeight )
    {   
        // it is so let's resize the image intelligently
        // check if our image is landscape or portrait
        if ( $origWidth > $origHeight )
        {
            // target image is landscape/wide (ex: 4x3)
            $newWidth = $maxWidth;
            $ratio = $maxWidth / $origWidth;
            $newHeight = floor($origHeight * $ratio);
            // make sure the image wasn't heigher than expected
            if ($newHeight > $maxHeight)
            {
                // it is so limit by the height
                $newHeight = $maxHeight;
                $ratio = $maxHeight / $origHeight;
                $newWidth = floor($origWidth * $ratio);
            }
        }
        else
        {
            // target image is portrait/tall (ex: 3x4)
            $newHeight = $maxHeight;
            $ratio = $maxHeight / $origHeight;
            $newWidth = floor($origWidth * $ratio);
            // make sure the image wasn't wider than expected
            if ($newWidth > $maxWidth)
            {
                // it is so limit by the width
                $newWidth = $maxWidth;
                $ratio = $maxWidth / $origWidth;
                $newHeight = floor($origHeight * $ratio);
            }
        }
    }
    // it's not, so just use the current height and width
    else
    {
        $newWidth = $origWidth;
        $newHeight = $origHeight;
    }   

    return array("width"=>$newWidth, "height"=>$newHeight);
}

Upvotes: 0

Sven Lilienthal
Sven Lilienthal

Reputation: 6504

It's easy to do with ImageMagick. Either you use convert command line tool via exec or you use http://www.francodacosta.com/phmagick/resizing-images .
If you use 'convert' you can even tell ImageMagick to just resize larger images and to not convert smaller ones: http://www.imagemagick.org/Usage/resize/

If you don't have local access, you won't be able to use ImageMagick:

<?php
$maxWidth  = 250;
$maxHeight = 500;

$size = getimagesize($url);
if ($size) {
    $imageWidth  = $size[0];
    $imageHeight = $size[1];
    $wRatio = $imageWidth / $maxWidth;
    $hRatio = $imageHeight / $maxHeight;
    $maxRatio = max($wRatio, $hRatio);
    if ($maxRatio > 1) {
        $outputWidth = $imageWidth / $maxRatio;
        $outputHeight = $imageHeight / $maxRatio;
    } else {
        $outputWidth = $imageWidth;
        $outputHeight = $imageHeight;
    }
}
?>

Upvotes: 5

Alo
Alo

Reputation: 1099

If you have to keep the aspect ratio of the image intact then you should scale it by a factor so that the longer side of the image (height or width) fits inside the limitations for that side.

Upvotes: 1

David Wees
David Wees

Reputation: 288

I'm not sure of the exact solution to your answer, but I know a project written in PHP which has the solution. Go and take a look at the ImageCache built for the Drupal CMS, which is written in PHP.

It basically let's you define some actions to take on an arbitrary image, and produce almost whatever scaling/cropping you want to the image.

You'd have to learn a few of the Drupal API's to be able to understand this example, but it is extensive and if you understand their algorithms, you'd be able to solve other more complicated problems.

Upvotes: 0

Tim Almond
Tim Almond

Reputation: 12726

Have you looked at the GD library documentation, particularly the imagecopyresized method?

Upvotes: 1

Gumbo
Gumbo

Reputation: 655735

You could use the following:

$maxWidth  = 250;
$maxHeight = 500;

$validSize = true;
$imageinfo = getimagesize($filename);
if ($imageinfo) {
    $validSize &= $imageinfo[0] <= $maxWidth;
    $validSize &= $imageinfo[1] <= $maxHeight;
}

The &= is a combined operator of the bitwise-and operator & and the assignment operator =. Thus $foo &= *expr* and $foo = $foo & *expr* are equivalent.

Upvotes: 0

Related Questions