Page 20 of 37
Re: Image Resizing Script required - a better one...
Posted: Thu Mar 09, 2017 11:20 am
by simonmlewis
why not add a fourth parameter to resizeSingleImage and pass that value in?
Remember, you are suggesting an idea, on an area I still know extremely little about.
I understand that I shouldn't be copying and pasting. But I don't know how to get those sizes to be used everywhere, without doing that.
Re: Image Resizing Script required - a better one...
Posted: Thu Mar 09, 2017 11:31 am
by Celauran
simonmlewis wrote:why not add a fourth parameter to resizeSingleImage and pass that value in?
Remember, you are suggesting an idea, on an area I still know extremely little about.
I do recognize that but I hope that as we work through this together you walk away understanding more about it. Otherwise I'd just have given you the answer.
simonmlewis wrote:I understand that I shouldn't be copying and pasting. But I don't know how to get those sizes to be used everywhere, without doing that.
Look at what we've done with the other functions. Inside the function signature (ie. between the parentheses after the function name) we list which variables it will accept and what they will be called within the scope of that function. This is why you pass $row->image into getSrcSet but refer to is as $filename within the function. Inside resizeSingleImage, we're currently accepting the filename of the original image, the suffix to append to the new file, and the width we want the new file to be. Those are $original, $suffix, and $width, respectively. You could add a fourth variable to that list, call it something meaningful like $save_path, and then add that argument when you're calling the function.
So we'd now have something like:
Code: Select all
// Resizes a single image to a specific size and with a specific suffix
function resizeSingleImage($original, $suffix, $width, $save_path)
{
$imagine = new Imagine\Gd\Imagine();
$target_directory = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . $save_path;
$pathinfo = pathinfo($original);
// Open the uploaded image with the Imagine library
$image = $imagine->open($target_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);
}
Then from inside our getSrcSet function, which is where we
call resizeSingleImage, we pass along $actualfolder like so:
Code: Select all
function getSrcSet($filename, $resize_type = 'wide')
{
switch($resize_type) {
case 'stockbanners':
$actualfolder = 'stockbanners';
break;
default:
$actualfolder = 'pages';
break;
}
$root_directory = dirname(__DIR__);
$images_directory = DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . $actualfolder;
$images_path = "/images/{$actualfolder}"; // Still need this for srcset output
$source_directory = $root_directory . $images_directory;
$srcset = [];
$widths = getWidths($resize_type);
if (file_exists($source_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($source_directory . DIRECTORY_SEPARATOR . $fullname)) {
$srcset[] = "{$images_path}/{$fullname} {$size}w";
} else {
resizeSingleImage($filename, $size, $width, $actualfolder);
$srcset[] = "{$images_path}/{$fullname} {$size}w";
}
}
}
return implode(', ', $srcset);
}
Does that make sense?
Re: Image Resizing Script required - a better one...
Posted: Thu Mar 09, 2017 11:43 am
by simonmlewis
Two areas here I don't understand.
One I have seen a fair bit, but still don't get it.
1) function getSrcSet($filename, $resize_type = 'wide')
Which is that pinpointing the "wide" case??
2) $save_path - where is it getting that from?
I am assuming that from a function further up the page, you can attach that to a function further down, and that is what 2) is doing??
Re: Image Resizing Script required - a better one...
Posted: Thu Mar 09, 2017 11:47 am
by simonmlewis
This is it at the moment.
I keep seeing differences between yours and mine. I've never had code before that has $variable,$variable2,$variable3... in a row like that. So trying to get a grasp on how each area uses that sort of string.
This is still product big errors.
When I get errors in my own code I tend to know the cause and go straight to it. I am assuming with 'functions' you are very similar.
I have never used functions, but this lesson is helping me a lot. Just trying to grasp it, learn it, and see the magic it can do.
Code: Select all
<?php
require_once '/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' => 97];
break;
case 'png':
$options = ['png_compression_level' => 8];
break;
default:
$options = [];
}
return $options;
}
function getSrcSet($filename, $resize_type = 'wide')
{
switch($resize_type) {
case 'stockbanners':
$actualfolder = 'stockbanners';
break;
default:
$actualfolder = 'pages';
break;
}
$root_directory = dirname(__DIR__);
$images_directory = DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . $actualfolder;
$images_path = "/images/{$actualfolder}"; // Still need this for srcset output
$source_directory = $root_directory . $images_directory;
$srcset = [];
$widths = getWidths($resize_type);
if (file_exists($source_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($source_directory . DIRECTORY_SEPARATOR . $fullname)) {
$srcset[] = "{$images_path}/{$fullname} {$size}w";
} else {
resizeSingleImage($filename, $size, $width, $actualfolder);
$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;
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();
switch($resize_type) {
case 'stockbanners':
$actualfolder = 'stockbanners';
break;
default:
$actualfolder = 'pages';
break;
}
$target_directory = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . $actualfolder;
$pathinfo = pathinfo($file_name);
$prefix = time();
// 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);
}
}
// Resizes a single image to a specific size and with a specific suffix
function resizeSingleImage($original, $suffix, $width, $save_path)
{
$imagine = new Imagine\Gd\Imagine();
$target_directory = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . $save_path;
$pathinfo = pathinfo($original);
// Open the uploaded image with the Imagine library
$image = $imagine->open($target_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);
}
?>
[text]Fatal error: Uncaught exception 'Imagine\Exception\InvalidArgumentException' with message 'File C:\xampp\phpMyAdmin\site-wide\images\stockbanners\ does not exist.' in C:\xampp\phpMyAdmin\site-wide\vendor\imagine\imagine\lib\Imagine\Image\AbstractImagine.php:72 Stack trace: #0 C:\xampp\phpMyAdmin\site-wide\vendor\imagine\imagine\lib\Imagine\Gd\Imagine.php(86): Imagine\Image\AbstractImagine->checkPath('C:\\xampp\\phpMyA...') #1 C:\xampp\phpMyAdmin\site-wide\functions\functionConsumerResize.php(148): Imagine\Gd\Imagine->open('C:\\xampp\\phpMyA...') #2 C:\xampp\phpMyAdmin\site-wide\functions\functionConsumerResize.php(49): resizeSingleImage(NULL, 475, 237, 'stockbanners') #3 C:\xampp\phpMyAdmin\site-wide\includes\page.inc(310): getSrcSet(NULL, 'stockbanners') #4 C:\xampp\phpMyAdmin\site-wide\index.php(42): include('C:\\xampp\\phpMyA...') #5 C:\xampp\phpMyAdmin\site-wide\index.php(437): getPage(Object(PDO)) #6 {main} thrown in C:\xampp\phpMyAdmin\site-wide\vendor\imagine\imagine\lib\Imagine\Image\AbstractImagine.php on line 72[/text]
Re: Image Resizing Script required - a better one...
Posted: Thu Mar 09, 2017 11:49 am
by Celauran
simonmlewis wrote:Two areas here I don't understand.
One I have seen a fair bit, but still don't get it.
1) function getSrcSet($filename, $resize_type = 'wide')
Which is that pinpointing the "wide" case??
Can you please clarify what you mean here? $resize_type is the name of the variable within the scope of the function, and 'wide' is its default value -- what will be used if we do not pass a second argument. Not sure if that answers your question or not.
simonmlewis wrote:2) $save_path - where is it getting that from?
I am assuming that from a function further up the page, you can attach that to a function further down, and that is what 2) is doing??
We're defining it. When you define a function (eg. function someName(arguments go here)) you specify how many parameters it will accept and what they will be called. The function cannot see out into the larger application. The only things it knows about are the things you explicitly pass in. If you need to see more of the outside, you need to accept and pass in more arguments. That is exactly what is happening here. Initially we were unconcerned about a save path as everything was being saved to the same directory. Now we have new requirements so the hard-coded directory is no longer adequate. To work around this, we modify the function signature to accept an additional parameter and we then use that parameter within the function itself when declaring the full path to which images will be saved.
Re: Image Resizing Script required - a better one...
Posted: Thu Mar 09, 2017 11:54 am
by Celauran
Stack traces. These are indispensable at identifying where things have gone wrong. Cleaned up a little for the sake of readability, here's what you just posted.
Code: Select all
Fatal error: Uncaught exception 'Imagine\Exception\InvalidArgumentException' with message 'File C:\xampp\phpMyAdmin\site-wide\images\stockbanners\ does not exist.' in C:\xampp\phpMyAdmin\site-wide\vendor\imagine\imagine\lib\Imagine\Image\AbstractImagine.php:72
Stack trace:
#0 C:\xampp\phpMyAdmin\site-wide\vendor\imagine\imagine\lib\Imagine\Gd\Imagine.php(86): Imagine\Image\AbstractImagine->checkPath('C:\\xampp\\phpMyA...')
#1 C:\xampp\phpMyAdmin\site-wide\functions\functionConsumerResize.php(148): Imagine\Gd\Imagine->open('C:\\xampp\\phpMyA...')
#2 C:\xampp\phpMyAdmin\site-wide\functions\functionConsumerResize.php(49): resizeSingleImage(NULL, 475, 237, 'stockbanners')
#3 C:\xampp\phpMyAdmin\site-wide\includes\page.inc(310): getSrcSet(NULL, 'stockbanners')
#4 C:\xampp\phpMyAdmin\site-wide\index.php(42): include('C:\\xampp\\phpMyA...')
#5 C:\xampp\phpMyAdmin\site-wide\index.php(437): getPage(Object(PDO))
#6 {main} thrown in C:\xampp\phpMyAdmin\site-wide\vendor\imagine\imagine\lib\Imagine\Image\AbstractImagine.php on line 72
The first thing that jumps out at me is this line:
[text]#3 C:\xampp\phpMyAdmin\site-wide\includes\page.inc(310): getSrcSet(NULL, 'stockbanners')[/text]
NULL? That's interesting. I'm assuming you're passing in $row->image, but we're getting nothing. Does this product not have an associated image? That's liable to happen at some point and we need to guard against that. Any thoughts on how we might accomplish that?
Re: Image Resizing Script required - a better one...
Posted: Thu Mar 09, 2017 12:45 pm
by simonmlewis
It won't be that. It's only calling that from the database if it finds one is there. So it won't ever be a case of trying when there isn't one there.
However, it might be possible that in my copying over, I've failed to copy that image. I'll check on that when I get home. Not sure what else would cause a NULL in there.
Re: Image Resizing Script required - a better one...
Posted: Thu Mar 09, 2017 1:16 pm
by simonmlewis
Found it.
Code: Select all
if ($row->stockbanner == "yes")
{
$file = "/images/stockbanners/$rowprod->stockbanner";
$ext = pathinfo($file, PATHINFO_EXTENSION);
$filename = pathinfo($file, PATHINFO_FILENAME);
echo "<a href='$row->url'>";
$image = $rowprod->stockbanner; // <<< this was $row->image
$srcset = getSrcSet($image, 'stockbanners');
echo "<img src='/images/stockbanners/$image' srcset='{$srcset}' alt='$row->freetext'/>";
}
else
{
$image = $row->image;
$srcset = getSrcSet($image, 'stockbanners');
echo "<img src='/images/pages/$image' srcset='{$srcset}' alt='$row->freetext'/>";
}
It works and resizes perfectly.
Re: Image Resizing Script required - a better one...
Posted: Fri Mar 10, 2017 4:27 am
by simonmlewis
I am gradually rolling this out on our other admin and home pages, though I need to tweak some, where we give an option to "replace image".
But I have a query about Composer installation no a server - if you know about that?
Our hosts confirm they have installed it, but we are getting an error in the log.
Code: Select all
$widths = [
'475' => 237,
'768' => 384,
'1920' => 451,
];
On this first [.
I looked at the folder structure in FTP, and no vendor folder has been created. Our control panel is Plesk 12.
Why would it not show that vendor folder? Does it mean they haven't installed Composer correctly??
Re: Image Resizing Script required - a better one...
Posted: Fri Mar 10, 2017 5:03 am
by Celauran
What does the error say? Are you sure it's related to Composer? Also, Composer is generally run from the command line. If it's shared hosting and you don't have access to the command line, you'll want to talk to them to get that set up or you may need to upload your vendor directory from your development server, which isn't ideal.
Re: Image Resizing Script required - a better one...
Posted: Fri Mar 10, 2017 5:18 am
by simonmlewis
So if I add my composer 'vendor' folder, that will likely fix it?
Or do I think I need to ask them for the full string of that?
Also, trying to ascertain the best method here.
I have added the script to delete the Stock Banners in the two admin areas (we show Stock Banners in one big list, and in each individual product).
Is it best when uploading a new one to upload the others too, or leave that to the function, so it's all done from one easy place?
What I am thinking here, is that with the Product Photos, the thumbnails - using that function, adding in another version for "product", that uses /productphotos/small, to store them, and it just adds them on the fly (like Wordpress does).
And when admin deletes an image, it deletes all four.
Sounds like a more effective and manageable solution.
Re: Image Resizing Script required - a better one...
Posted: Fri Mar 10, 2017 5:24 am
by Celauran
simonmlewis wrote:So if I add my composer 'vendor' folder, that will likely fix it?
Or do I think I need to ask them for the full string of that?
I would talk to your hosting provider and see what they can recommend. That they have Composer installed is encouraging. Wouldn't make much sense to me to have it installed yet have no way for your users to leverage it. I haven't worked with shared hosting in a long while, so I don't know what the most common practice is. If it's a VPS and you have shell access, then you can just log in and run
composer install yourself.
simonmlewis wrote:Also, trying to ascertain the best method here.
I have added the script to delete the Stock Banners in the two admin areas (we show Stock Banners in one big list, and in each individual product).
Is it best when uploading a new one to upload the others too, or leave that to the function, so it's all done from one easy place?
What I am thinking here, is that with the Product Photos, the thumbnails - using that function, adding in another version for "product", that uses /productphotos/small, to store them, and it just adds them on the fly (like Wordpress does).
And when admin deletes an image, it deletes all four.
Sounds like a more effective and manageable solution.
I would try as much as possible to create the thumbnails on upload and delete the whole lot when you delete the original image. Sure, we now have provisions to resize on the fly if/as needed, but that also causes some rendering delay for the user. Better the site administrator should have to wait a second or two than a customer should.
Re: Image Resizing Script required - a better one...
Posted: Mon Mar 13, 2017 5:56 am
by simonmlewis
Agreed.
So we now have an error on our sandbox server. And it's in the most bizarre please:
Code: Select all
if (isset($resize))
{
if ($resize == "categories" || $resize == "products")
{
// An array of widths, keyed by target screen size
$widths = [
'475' => 237,
'768' => 384,
'1920' => 451,
];
.........
It doesn't like that first [.
I know that is just an array. We are running 5.3.3. Now where there are two versions of 3.3 and one didn't use those. But surely it's just array code.
Re: Image Resizing Script required - a better one...
Posted: Mon Mar 13, 2017 6:18 am
by Celauran
Short array syntax wasn't introduced until 5.4. You'll need array() for 5.3. Also, you really shouldn't be running 5.3 any longer.
Re: Image Resizing Script required - a better one...
Posted: Mon Mar 13, 2017 6:30 am
by simonmlewis
ahhhhhhhhhhhhh
So for now, how do I edit the $widths to accept it on this server until we update?