Brian Scramlin

How Image Resizing Works

8 posts in this topic

Hey Everyone,

I have a question that seems like it would have an obvious answer, but I cannot wrap my mind around it:

If I have 

<img src="<?= $page->featuredImage->size(800,500)->url ?>"/>

in an article template, does my server run a resizing script

  • every time someone requests the page?
  • Or, is it resized only the first time it is requested?
  • Or when the page is saved?

The reason I would like to know is because I have created two image processing functions my client requires, but one of them is a paid subscription service to compress the images. I don't want to call the paid API every time a page is loaded or something.

Thanks for fielding my ignorance :P

Share this post


Link to post
Share on other sites

The thumbnail generation does run when this code is executed and the file corresponding to the thumbnail does not exist at that time.

1 person likes this

Share this post


Link to post
Share on other sites

How is it possible for me to run a PHP Function on an image as it is being uploaded? This would be the ideal situation because then anywhere I need to execute the ->size() functions I don't have to re-call my compression service.

Right now all over my website I have something like  tinify($page->image->size(200,200)->url) instead I would rather just have the tinify() function called on the initial save. 

Further, if it was possible to do this for every image including CKEditor body images we would be in business!

Thank you for your help. 

Share this post


Link to post
Share on other sites

There are various topics around this exact use case on the forums. The short version: there's no obvious solution, but things you can do.

Share this post


Link to post
Share on other sites
1 hour ago, Brian Scramlin said:

How is it possible for me to run a PHP Function on an image as it is being uploaded? This would be the ideal situation because then anywhere I need to execute the ->size() functions I don't have to re-call my compression service.

Right now all over my website I have something like  tinify($page->image->size(200,200)->url) instead I would rather just have the tinify() function called on the initial save. 

Further, if it was possible to do this for every image including CKEditor body images we would be in business!

Thank you for your help. 

Tinifying images is ONLY useful on the final variations. Tinifying an original source image is completly WRONG.

This tinifying is often misunderstood.

You can resize an image on upload to variuos varirations and also tinify them, if you exactly know which variations you will need around in your site.

Here is an example how to hook into upload and process something with the image:

 

2 people like this

Share this post


Link to post
Share on other sites

Thank you, everyone. I appreciate your input. I understand in most scenarios converting the original file on upload is not the best approach. However, in this situation it seems the best way to save on calling my iMagick function and compression function. 

First off, I have never created a Processwire module and am intimidated by the prospect, but I am considering the suggested InputfieldImageThumbs module route.

Here is the original module:

class InputfieldImageThumbs extends WireData implements Module {

    public function init() {
        $this->addHookAfter('InputfieldFile::fileAdded', $this, 'createThumbs');
    }

    public function createThumbs($event) {
        $inputfield = $event->object;
        $image = $event->arguments("pagefile");
        
        $allowedTypes = array(IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF); // allowed image formats
        $detectedType = exif_imagetype($image->filename); // check if file is an image
        if(!in_array($detectedType, $allowedTypes)) return; // if not, exit

        $widths = explode(",", $this->imageWidths, 10); // convert comma separated list to array, limit to 10 values
        $widths = array_filter($widths, 'ctype_digit'); // keep only numeric entries in the array
        
        foreach($widths as $width) {
            $image->size($width,0); // generate image for each defined width
        }
    }
}

Here is a stab at my attempted module. I am very new at this, so please prepare yourself

class tinifyImages extends WireData implements Module {

    public function init() {
        $this->addHookAfter('InputfieldFile::fileAdded', $this, 'tinify');
    }

    public function tinify($event) {
        $inputfield = $event->object;
        $image = $event->arguments("pagefile");
        
        $allowedTypes = array(IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF); // allowed image formats
        $detectedType = exif_imagetype($image->filename); // check if file is an image
        if(!in_array($detectedType, $allowedTypes)) return; // if not, exit

        /* Include Tinify API Resources and Initialize */
        require_once("inc/tinify-php-master/lib/Tinify/Exception.php");
        require_once("inc/tinify-php-master/lib/Tinify/ResultMeta.php");
        require_once("inc/tinify-php-master/lib/Tinify/Result.php");
        require_once("inc/tinify-php-master/lib/Tinify/Source.php");
        require_once("inc/tinify-php-master/lib/Tinify/Client.php");
        require_once("inc/tinify-php-master/lib/Tinify.php");
        \Tinify\setKey("API_KEY");

        //function used to compress with tinify api 
        function tinify($imagePath) {
            $path_parts = pathinfo($imagePath);
            $dirname = $path_parts['dirname'] . '/';
            $filename = $path_parts['filename'];
            $savename = $dirname . $filename . '-compressed.jpg';
            if (!file_exists($_SERVER['DOCUMENT_ROOT'] . $savename)) {
                $source = \Tinify\fromFile($_SERVER['DOCUMENT_ROOT'] . $imagePath);
                $source->toFile($_SERVER['DOCUMENT_ROOT'] . $savename);
            }
            return $savename;
        }
        
        $image = tinify($image->url);
    }
}
?>

Am I close?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By horst
      Hi, here is a very useful tool that check your images in websites against responsiveness:
      https://github.com/ausi/respimagelint
       

    • By evanmcd
      Hi all,
      I've not been able to upload SVGs into a regular image field, with SVG added in the Valid File Extensions field.
      The error I'm getting is:
      Error: Call to undefined function ProcessWire\simplexml_load_string() (line 234 of /var/www/hosts/our_website/Develop/Source/wire/core/Pageimage.php) I tried the ImageRasterizer module, but that didn't fix it.
      Is there a workaround for folks that don't have the simplexml module installed?
    • By Ibrahim El Haddad
      Hi guys, 
      Yesterday, I faced a problems to run a processwire old system from backup locally, finally after your support, the system start working but still I have the below problems issues. 
      1. Once I try to press a sub-link, it guides me to Object not found, Error 404  similar to the below , and the link of the website became like below: 
      http://www.www.www.www.www.www.www.www.www.www.www.www.www.www.www.www.www.www.www.www.localhost:9999/publications-and-ressources/texts/books/
      despite of that my application name is ibrahem, so if I amend the url manually to be as 
      http://www.www.www.www.www.www.www.www.www.www.www.www.www.www.www.www.www.www.www.www.localhost:9999/ibrahem/publications-and-ressources/texts/books/
      it works fine, but every link, i should amend the url to add the application name. 
      Object not found!
      The requested URL was not found on this server. The link on the referring page seems to be wrong or outdated. Please inform the author of that page about the error.
      If you think this is a server error, please contact the webmaster.
      Error 404
       
      2. The images issues, that the images related to the book cover or another issue such as the slider is not appear, please advice.
       
      Thank you in advance for all of your support and help. 
       
    • By ocr_b
      hi,
      today i got asked by a client if it's possible to hide/unpublish images within the gallery field so he doesn't have to delete the images.
      thought about a workaround with a certain word as description ("hidden") to sort out those images.
      any other solutions?
      thanks in advance
    • By horst
      Metadata Exif
      Version 0.9.0  (currently a WIP) for PW 2.8.+ / 3.0+
      This is a new attempt to add easy EXIF reading support to ProcessWire. It should be an easy and less error prone API task. Thats why the module internally uses lowercase key names for all EXIF keys and all of your requested key names. But you are not forced to use lowercase key names, you can use any mixed chars for it as you like. You will get back an array or object with keynames / properties named the same (casesensitive) way as you have passed them in with your request.
      API
      The module adds one hook to the Pageimage: getExif($options = null)
      Without any $options passed to the method, it returns all EXIF data in a RAW multidim array.
      Passing a simple list with requested key names as array to it returns an array with only the values of those requested keynames.
      If you want change the output from array to object, you can use the a boolean "toObject" set to true. Additionally to this and / or any other option, you need to put your requested keynames list to the option "keys".
      $rawArray = $image->getExif(); $options = array('Whitebalance', 'Flash', 'ISOSpeedRatings', 'FNumber', 'UserComment'); $array = $image->getExif($options); $options = array('toObject' => true, 'keys' => array('whitebalance', 'flash', 'isospeedratings', 'fnumber', 'usercomment')); $object = $image->getExif($options);  
      Possible options are
       
      A working example
      $options = array( 'keys' => array('ISOSpeedRatings', 'FNumber', 'Flash') ); echo "<table><tr>"; foreach($options['keys'] as $key) echo "<th>{$key}</th>"; echo "</tr>"; foreach($page->images as $image) { $exif = $image->getExif($options); echo "<tr>"; foreach($exif as $value) echo "<td>$value</td>"; echo "</tr>"; } echo "</table>";  
      This will output something like:
       
      With the boolean option "unformatted" passed as true, the output would look like:
       
      For some keys, that only store something like integer values, what are not very meaningful to most of us, the module contain xyzFormatted methods. This way, it is easy to enhance and maintain the module in the future.
       
      Help wanted
      It would be nice if some of you test the module and report back if the intended API suites your needs. And you are very welcome to post suggestions for which keys you want to have a ...Formatted method.
       
      Thank you!
      https://github.com/horst-n/MetadataExif