Image Resizing Script required - a better one...

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: Image Resizing Script required - a better one...

Post by Celauran »

Actually, let me show the full function since there are a few other small tweaks required.

Code: Select all

// Takes input from a form post and saves original image plus all required resizes
function resizeImage($path_to_file, $file_name, $resize_type)
{
    $imagine = new Imagine\Gd\Imagine();

    $target_directory = dirname(__DIR__) . getPath($resize_type);
    $pathinfo = pathinfo($file_name);
    $prefix = time();
    $renamed = "{$prefix}_{$pathinfo['basename']}";

    // Open the uploaded image with the Imagine library
    $image = $imagine->open($path_to_file);

    // Save the original
    $options = getImageOptions($pathinfo['extension']);
    $path_to_original = $target_directory['fullsize'] . DIRECTORY_SEPARATOR . $renamed;
    $image->save($path_to_original, $options);

    // Resize

    // Get the size of the original image
    $box = $image->getSize();

    // Get the sizes we need
    $widths = getWidths($resize_type);

    // Create resized images
    foreach ($widths as $key => $width) {
        $ratio = $width / $box->getWidth();
        $scaled_box = $box->scale($ratio);
        $new_filename = "{$prefix}_{$pathinfo['filename']}_{$key}.{$pathinfo['extension']}";

        // Re-open the original for scaling so we're not creating a larger image from a smaller
        $source = $imagine->open($path_to_original);
        $source->resize($scaled_box)->save($target_directory['thumbnail'] . DIRECTORY_SEPARATOR . $new_filename, $options);
    }

    // We don't want the full path, just the file name
    return $renamed;
}
simonmlewis
DevNet Master
Posts: 4435
Joined: Wed Oct 08, 2008 3:39 pm
Location: United Kingdom
Contact:

Re: Image Resizing Script required - a better one...

Post by simonmlewis »

So resizeImage has the information from the form. The target_directory line, after the root, calls the getPath function with the value of resize_type (thumbnails, Categories.).... and uses the output from that function to place into that path.
What is that about return $renamed? Why is that different from before?
Love PHP. Love CSS. Love learning new tricks too.
All the best from the United Kingdom.
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: Image Resizing Script required - a better one...

Post by Celauran »

simonmlewis wrote:So resizeImage has the information from the form. The target_directory line, after the root, calls the getPath function with the value of resize_type (thumbnails, Categories.).... and uses the output from that function to place into that path.
What is that about return $renamed? Why is that different from before?
Nothing important. It was returning "{$prefix}_{$pathinfo['basename']}" in two places. I just saved it as a variable so it's easier to re-use.
simonmlewis
DevNet Master
Posts: 4435
Joined: Wed Oct 08, 2008 3:39 pm
Location: United Kingdom
Contact:

Re: Image Resizing Script required - a better one...

Post by simonmlewis »

So with the addition of Stockbanners I now have this:

Code: Select all

function getPath($target)
{
    $paths = array(
        'fullsize' => '/images/pages',
        'thumbnail' => '/images/pages',
    );

    if ($target === 'thumbnails') {
        $paths['fullsize'] = '/images/productphotos';
        $paths['thumbnail'] = '/images/productphotos/small';
    }
    if ($target === 'stockbanners') {
        $paths['fullsize'] = '/images/stockbanners';
        $paths['thumbnail'] = '/images/stockbanners';
    }

    return $paths;
}

// Takes input from a form post and saves original image plus all required resizes
function resizeImage($path_to_file, $file_name, $resize_type)
{
    $imagine = new Imagine\Gd\Imagine();
    
    $target_directory = dirname(__DIR__) . getPath($resize_type);
    $pathinfo = pathinfo($file_name);
    $prefix = time();
    $renamed = "{$prefix}_{$pathinfo['basename']}";

    // Open the uploaded image with the Imagine library
    $image = $imagine->open($path_to_file);

    // Save the original
    $options = getImageOptions($pathinfo['extension']);
    $path_to_original = $target_directory . DIRECTORY_SEPARATOR . "{$prefix}_{$pathinfo['basename']}";
    $image->save($path_to_original, $options);

    // Resize

    // Get the size of the original image
    $box = $image->getSize();

    // Get the sizes we need
    $widths = getWidths($resize_type);

    // Create resized images
    foreach ($widths as $key => $width) {
        $ratio = $width / $box->getWidth();
        $scaled_box = $box->scale($ratio);
        $new_filename = "{$prefix}_{$pathinfo['filename']}_{$key}.{$pathinfo['extension']}";

        // Re-open the original for scaling so we're not creating a larger image from a smaller
        $source = $imagine->open($path_to_original);
        $source->resize($scaled_box)->save($target_directory . DIRECTORY_SEPARATOR . $new_filename, $options);
    }
    return $renamed;
}
Love PHP. Love CSS. Love learning new tricks too.
All the best from the United Kingdom.
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: Image Resizing Script required - a better one...

Post by Celauran »

$target_directory is an array now, so you'll need to specify which key (fullsize or thumbnail) to use when saving.
simonmlewis
DevNet Master
Posts: 4435
Joined: Wed Oct 08, 2008 3:39 pm
Location: United Kingdom
Contact:

Re: Image Resizing Script required - a better one...

Post by simonmlewis »

So part of that is in here:

Code: Select all

// Create resized images
    foreach ($widths as $key => $width) {
        $ratio = $width / $box->getWidth();
        $scaled_box = $box->scale($ratio);
        $new_filename = "{$prefix}_{$pathinfo['filename']}_{$key}.{$pathinfo['extension']}";

        // Re-open the original for scaling so we're not creating a larger image from a smaller
        $source = $imagine->open($path_to_original);
        $source->resize($scaled_box)->save($target_directory . DIRECTORY_SEPARATOR . $new_filename, $options);
    }
I somehow tell it which part of the array to save these in.

And then the same for the smaller files?
Love PHP. Love CSS. Love learning new tricks too.
All the best from the United Kingdom.
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: Image Resizing Script required - a better one...

Post by Celauran »

Right. When you see $target_directory, you need to replace it with either $target_directory['fullsize'] or $target_directory['thumbnail'] as appropriate.
simonmlewis
DevNet Master
Posts: 4435
Joined: Wed Oct 08, 2008 3:39 pm
Location: United Kingdom
Contact:

Re: Image Resizing Script required - a better one...

Post by simonmlewis »

Sorry you have lost me now.. :(
Love PHP. Love CSS. Love learning new tricks too.
All the best from the United Kingdom.
User avatar
Celauran
Moderator
Posts: 6427
Joined: Tue Nov 09, 2010 2:39 pm
Location: Montreal, Canada

Re: Image Resizing Script required - a better one...

Post by Celauran »

Bah. That was my bad. I was having you try to concatenate an array and a string.

I took the time to debug and test it on my machine. This works. You'll need to tweak the short array syntax and maybe fix the paths, but this works exactly as intended. Go through the code and we can discuss anything you're unclear on.

Code: Select all

<?php

require_once dirname(dirname(__DIR__)) . '/vendor/autoload.php';

// Returns required quality settings for Imagine based on image's extension
function getImageOptions($extension)
{
    switch ($extension) {
        case 'jpg':
        case 'jpeg':
            $options = ['jpeg_quality' => 85];
            break;
        case 'png':
            $options = ['png_compression_level' => 8];
            break;
        default:
            $options = [];
    }

    return $options;
}

function getPaths($resize_type)
{
    $paths = [
        'fullsize' => DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'pages',
        'thumbnail' => DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'pages',
    ];

    if ($resize_type === 'thumbnails') {
        $paths['fullsize'] = DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'productphotos';
        $paths['thumbnail'] = DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'productphotos' . DIRECTORY_SEPARATOR . 'small';
    }

    if ($resize_type === 'stockbanners') {
        $paths['fullsize'] = DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'stockbanners';
        $paths['thumbnail'] = DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'stockbanners';
    }

    return $paths;
}

function getSrcSet($filename, $resize_type = 'wide')
{
    $root_directory = dirname(__DIR__);

    $paths = getPaths($resize_type);
    $fullsize_directory = $root_directory . $paths['fullsize'];
    $thumbnail_directory = $root_directory . $paths['thumbnail'];

    $images_path = str_replace(DIRECTORY_SEPARATOR, '/', $paths['thumbnail']);
    $srcset = [];

    $widths = getWidths($resize_type);

    if (file_exists($fullsize_directory . DIRECTORY_SEPARATOR . $filename)) {
        $basename = pathinfo($filename, PATHINFO_FILENAME);
        $extension = pathinfo($filename, PATHINFO_EXTENSION);

        foreach ($widths as $size => $width) {
            $fullname = $basename . '_' . $size . '.' . $extension;
            if (file_exists($thumbnail_directory . DIRECTORY_SEPARATOR . $fullname)) {
                $srcset[] = "{$images_path}/{$fullname} {$size}w";
            } else {
                resizeSingleImage($filename, $size, $width, $resize_type);
                $srcset[] = "{$images_path}/{$fullname} {$size}w";
            }
        }
    }

    return implode(', ', $srcset);
}

// Returns an array of widths, keyed by target screen size
function getWidths($resize_option)
{
    switch($resize_option) {
        case 'categories':
        case 'products':
        case 'stockbanners':
            $widths = [
                '475' => 237,
                '768' => 384,
                '1920' => 451,
            ];
            break;
        case 'wide':
            $widths = [
                '475' => 237,
                '768' => 384,
                '1920' => 950,
            ];
            break;
        case 'desktopslide':
            $widths = [
                '475' => 475,
                '768' => 768,
                '1920' => 1920,
            ];
            break;
       case 'thumbnails':
            $widths = [
                '475' => 237,
                '768' => 384,
                '1920' => 451,
                '2520' => 600,
            ];
            break;
         default:
            $widths = [];
            break;
    }

    return $widths;
}

// Takes input from a form post and saves original image plus all required resizes
function resizeImage($path_to_file, $file_name, $resize_type)
{
    $imagine = new Imagine\Gd\Imagine();

    $paths = getPaths($resize_type);
    $fullsize_directory = dirname(__DIR__) . $paths['fullsize'];
    $thumbnail_directory = dirname(__DIR__) . $paths['thumbnail'];
    $pathinfo = pathinfo($file_name);
    $prefix = time();
    $renamed = "{$prefix}_{$pathinfo['basename']}";

    // Open the uploaded image with the Imagine library
    $image = $imagine->open($path_to_file);

    // Save the original
    $options = getImageOptions($pathinfo['extension']);
    $path_to_original = $fullsize_directory . DIRECTORY_SEPARATOR . $renamed;
    $image->save($path_to_original, $options);

    // Resize

    // Get the size of the original image
    $box = $image->getSize();

    // Get the sizes we need
    $widths = getWidths($resize_type);

    // Create resized images
    foreach ($widths as $key => $width) {
        $ratio = $width / $box->getWidth();
        $scaled_box = $box->scale($ratio);
        $new_filename = "{$prefix}_{$pathinfo['filename']}_{$key}.{$pathinfo['extension']}";

        // Re-open the original for scaling so we're not creating a larger image from a smaller
        $source = $imagine->open($path_to_original);
        $source->resize($scaled_box)->save($thumbnail_directory . DIRECTORY_SEPARATOR . $new_filename, $options);
    }

    // We don't want the full path, just the file name
    return $renamed;
}

// Resizes a single image to a specific size and with a specific suffix
function resizeSingleImage($original, $suffix, $width, $type)
{
    $imagine = new Imagine\Gd\Imagine();

    $paths = getPaths($type);
    $source_directory = dirname(__DIR__) . $paths['fullsize'];
    $target_directory = dirname(__DIR__) . $paths['thumbnail'];
    $pathinfo = pathinfo($original);

    // Open the uploaded image with the Imagine library
    $image = $imagine->open($source_directory . DIRECTORY_SEPARATOR . $original);

    // Get the size of the original image
    $box = $image->getSize();

    $ratio = $width / $box->getWidth();
    $scaled_box = $box->scale($ratio);
    $new_filename = "{$pathinfo['filename']}_{$suffix}.{$pathinfo['extension']}";

    $options = getImageOptions($pathinfo['extension']);
    $image->resize($scaled_box)->save($target_directory . DIRECTORY_SEPARATOR . $new_filename, $options);
}
simonmlewis
DevNet Master
Posts: 4435
Joined: Wed Oct 08, 2008 3:39 pm
Location: United Kingdom
Contact:

Re: Image Resizing Script required - a better one...

Post by simonmlewis »

Yes I think I understand all that. Didn't realise how much I would need to add in, but it does make sense.
going to start on this in the morning. Thanks again.
Love PHP. Love CSS. Love learning new tricks too.
All the best from the United Kingdom.
simonmlewis
DevNet Master
Posts: 4435
Joined: Wed Oct 08, 2008 3:39 pm
Location: United Kingdom
Contact:

Re: Image Resizing Script required - a better one...

Post by simonmlewis »

I have made those changes. I can see what's happening there too, and have added my comments in.
It works on the landing pages (banners), but when I add a product, it's saying saved_filename is undefined.

The upload form has this:

Code: Select all

			<div class='edittitle'>Add a Photograph</div>
			// used in the function to state which size images and location
			<input type='hidden' name='resize' value='thumbnails'>
			<input name='photoprimary' type='file' /> [browse to the file on your PC]
The script to call the function has this:

Code: Select all

require_once 'functions/functionConsumerResize.php';
// If we have an uploaded image without errors
if (!empty($_FILES) && isset($_FILES['photoprimary'])) {
    $saved_filename = resizeImage($_FILES['photoprimary']['tmp_name'], $_FILES['photoprimary']['name'], $resize);
}
So I'm a little bit confused.
Love PHP. Love CSS. Love learning new tricks too.
All the best from the United Kingdom.
simonmlewis
DevNet Master
Posts: 4435
Joined: Wed Oct 08, 2008 3:39 pm
Location: United Kingdom
Contact:

Re: Image Resizing Script required - a better one...

Post by simonmlewis »

I'm looking through this code. saved_filename isn't mentioned in the function. So how is $saved_filename being given that new name?
I thought it would be $new_filename? Yet on the banner page, it works, and that uses the same variable names. (apart from this page has photoprimary and the banners has homeimage.
Love PHP. Love CSS. Love learning new tricks too.
All the best from the United Kingdom.
simonmlewis
DevNet Master
Posts: 4435
Joined: Wed Oct 08, 2008 3:39 pm
Location: United Kingdom
Contact:

Re: Image Resizing Script required - a better one...

Post by simonmlewis »

I'm now NOT getting those errors. Found the issue there in my own form.
It's added it to the database, but for these product photos, it's not uploading the images.
I'm comparing it with my Edit page, as when I add an image there, using this script, it does work! Rather odd.
Love PHP. Love CSS. Love learning new tricks too.
All the best from the United Kingdom.
simonmlewis
DevNet Master
Posts: 4435
Joined: Wed Oct 08, 2008 3:39 pm
Location: United Kingdom
Contact:

Re: Image Resizing Script required - a better one...

Post by simonmlewis »

I've checked the error logs and nothing about this shows up. Nothing in the function.
I'm rather foxed. I guess we need to do some vardump exercises to find the cause.
The form has the enc code. The resize code is in there. It's basically the same as the Edit Banner script that adds it in the Edit screen. And that works!
Love PHP. Love CSS. Love learning new tricks too.
All the best from the United Kingdom.
simonmlewis
DevNet Master
Posts: 4435
Joined: Wed Oct 08, 2008 3:39 pm
Location: United Kingdom
Contact:

Re: Image Resizing Script required - a better one...

Post by simonmlewis »

Cracked it. It is because on my ADD script, I have two forms. One for Adding, one for Sell Similar.
I was editing the Sell Similar part. I noticed when I checked the source code to double check the code was there.

I knew it couldn't be the function as it worked in Edit.

It works! Yay.
Love PHP. Love CSS. Love learning new tricks too.
All the best from the United Kingdom.
Post Reply