Quite often I was in need a function to scale an image to the size right to fit into bounding box.

For example, displaying images of real estate or product image in the shop site. Images can be different sizes, less or bigger of target size, portrait or landscape, etc..

I wrote little helper function in PHP that does that tasks using two modes: FIT and FILL. It uses standard PHP-GD extension.

Why did I re-invent the wheel?

Solution seems easy and should be widely deployed, however I haven't found a working one on the Internet.  All my findings didn't do the job right and the way they work was not clear and I was not able to fix them.

My function accepts source image, destination image and operation (FIT or FILL). It scales image UP and DOWN and uses a very simple algorithm. See examples below:

# Image FIT/FILL example using PHP GD

Here is an example to give the idea how it works in two different modes

Fit mode

In fit mode it scales image to FIT image into bounding BOX leaving free space on the edges.

 

Fill mode

In FILL mod it scales image proportionally to fill entire bounding box with image, so no white space is left on the borders.
 

Like the pictures, ehh? :)

# Source code

Examples below are generated in real time using code below, feel free to use it and improve.

$w = intval($_GET['width']);
$h = intval($_GET['height']);
$mode = $_GET['mode']=='fit'?'fit':'fill';
if ($w <= 1 || $w >= 1000) $w = 100;
if ($h <= 1 || $h >= 1000) $h = 100;

// Source image
$src = imagecreatefromjpeg('./sample.jpg');

// Destination image with white background
$dst = imagecreatetruecolor($w, $h);
imagefill($dst, 0, 0, imagecolorallocate($dst, 255, 255, 255));

// All Magic is here
scale_image($src, $dst, $mode);

// Output to the browser
Header('Content-Type: image/jpeg');
imagejpeg($dst);


function scale_image($src_image, $dst_image, $op = 'fit') {
    $src_width = imagesx($src_image);
    $src_height = imagesy($src_image);

    $dst_width = imagesx($dst_image);
    $dst_height = imagesy($dst_image);

    // Try to match destination image by width
    $new_width = $dst_width;
    $new_height = round($new_width*($src_height/$src_width));
    $new_x = 0;
    $new_y = round(($dst_height-$new_height)/2);

    // FILL and FIT mode are mutually exclusive
    if ($op =='fill')
        $next = $new_height < $dst_height; else $next = $new_height > $dst_height;

    // If match by width failed and destination image does not fit, try by height 
    if ($next) {
        $new_height = $dst_height;
        $new_width = round($new_height*($src_width/$src_height));
        $new_x = round(($dst_width - $new_width)/2);
        $new_y = 0;
    }

    // Copy image on right place
    imagecopyresampled($dst_image, $src_image , $new_x, $new_y, 0, 0, $new_width, $new_height, $src_width, $src_height);
}