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 Peter Knight
      I have a page that's throwing an error because some of the pages in the for each loop don't have an image
      The docs say it's wise to check that an image has content and only then try to output something.
      I thought the following would work with the if($image) below.
       
      $products = $page->children(); foreach ($products as $prod){ $image = $prod->images->first(); echo" <div > <div class='prod-ov-wrapper'>"; if($image) echo " <a href='$prod->url'> <img src='{$image->height(160)->url}' class='prod-preview'> </a>"; echo" <div class='prod-ov-text'> <strong>Part No:</strong>{$prod->title} <br/> {$prod->prod_summary} <a href='$prod->url' class='uk-icon-button' uk-icon='icon: chevron-right'></a> </div> </div> </div> ";} What am I overlooking here? Thanks
    • By Xonox
      Hi,
      I need to add the original image dimensions (width x height) for the images inserted in the body field, in a few data-fields. Something like:
      <a href="/site/assets/files/1092/image-1.jpg"> <img alt="" src="/site/assets/files/1092/image-1.690x0-is.jpg" width="690" data-width="1500" data-height="1000 "> </a> Where data-width and data-height are the image-1.jpg dimensions.
      I tried to do this through a file, to control the field output:
      templates/fields/post/body.php But turns out the body comes already formatted from the DB, so I can't override the image display, unless I use some cumbersome str_replaces. Even with this solution, it's impossible to achieve the desired result.
      Is there any way I can do this through a ProcessWire process?
      I know it can be done through php, reading the file's header to extract the height and width and then do a str_replace on the body string to insert the desired code. However I'm curious if it can be done in any simpler and more effective way, without having to read the files from disk and do the replaces.
      Thanks,
    • By iNoize
      Hello, 
      i have a landingpage and need to reaname the images or save it to the filed images in the userpage 
      i have this script currently 
       
      if(isset($input->post->submit)) { $lptitle = $sanitizer->text($input->post->lptitle); $anrede = $sanitizer->text($input->post->anrede); $first_name = $sanitizer->text($input->post->first_name); $last_name = $sanitizer->text($input->post->last_name); $str = $sanitizer->text($input->post->str); $num = $sanitizer->text($input->post->num); $plz = $sanitizer->text($input->post->plz); $ort = $sanitizer->text($input->post->ort); $land = $sanitizer->text($input->post->land); $email = $sanitizer->text($input->post->email1); $fbname = $sanitizer->text($input->post->fbname); if ($page->id == '2328' ) { // Set a temporary upload location where the submitted files are stored during form processing $upload_path = $config->paths->assets . "files/stickers/"; // New wire upload $file = new WireUpload('file'); // References the name of the field in the HTML form that uploads the photo $file->setMaxFiles(1); $file->setOverwrite(false); $file->setDestinationPath($upload_path); $file->setValidExtensions(array('jpg', 'jpeg', 'png', 'gif')); // execute upload and check for errors $files = $file->execute(); // echo "Passt"; } // $group = $sanitizer->text($input->post->group2); if ($sanitizer->text($input->post->group2) == "on") { $group = "1"; }else{ $group = "0"; } $mail = \ProcessWire\wiremail(); $mail->to($email)->from("mymailhere@domain.com"); $mail->subject("Deine Anmeldung zur $page->title !"); $mail->bodyHTML("Hey $first_name,<br> <br> deine Anmeldung zur <b style='color: #4fc3f7;'>$page->titleaktion</b> war erfolgreich.<br> $page->mailoben Deine Angaben:<br> $anrede $first_name $last_name<br> $str $num<br> $land - $plz $ort<br> $email<br> $fbname<br> <br> Wir wünschen dir auf jeden Fall schonmal viel Erfolg und erfrischende Grüße!<br> $page->mailunten Gerne kannst du auch deinen Freunden von unserer $page->titleaktion per Facebook, Twitter, Google+, WhatsApp oder E-Mail berichten:<br>"); $mail->send(); $p = new Page(); // create new page object $p->template = 'fans'; // set template $p->parent = $page->id; $p->title = $first_name." ".$last_name."-".$page->numChildren; $p->gender = $anrede; $p->first_name = $first_name; $p->last_name = $last_name; $p->str = $str; $p->num = $num; $p->plz = $plz; $p->ort = $ort; $p->land = $land; $p->email = $email; $p->fbname = $fbname; $p->letter = $group; $p->save(); $p->images = $upload_path . $files[0]; $p->save(); @unlink($upload_path . $files[0]); } How to save the Image to the Userpage  ? 
       
      Thanks 
       
       
       
    • By Robin S
      A proof-of-concept module.
      ImageToMarkdown
      Alt+click an image in Page Edit to copy an image markdown string to clipboard.
      Usage
      Install the ImageToMarkdown module.
      Alt+click an image in Page Edit to copy an image markdown string to clipboard. If the "Description" field is populated it is used as the alt text.

       
      https://github.com/Toutouwai/ImageToMarkdown