4
\$\begingroup\$

I have written a piece of code by taking help from this link. For generating thumbnail, I create a temporary scaled image and then copy from that image. I am assuming that it is resource intensive.

Settings: the maximum values for target dimensions of scale images are predefined. Also, the thumbnail is always square and its side's value is also predefined.

The logic for my code is: Maximum Target dimensions - 700X524 Thumbnail - 90X90

  1. Get source image dimensions
  2. Check if either of height or width is larger than 524 & 700 respectively If yes,
  3. Check if height> width.If yes,set height=524 and scaled width;else set width=700 and scale height.
  4. create true color image from imagecreatettruecolor.
  5. Generate scaled image with new dimensions from the original image

For thumbnail:

  1. Check if either of scaled height and width is greater than 90
  2. If yes, scale the shorter side to 90 and longer side accordingly.
  3. Create a true color canvas of the further scaled dimensions.
  4. Create a short image with the shorter side being 90 and larger one scaled accordingly
  5. Create a true color canvas of dimensions 90X90
  6. Copy thumbnail image to this canvas from the recently created shorter scaled image.

The code:

<?php

// default dimensions 
//height : 524px 
//width: 700px

$source_image = imagecreatefromjpeg("bg.jpg"); 
$source_imagex = imageSX($source_image); 
$source_imagey = imagesy($source_image);

//destination image size calculation, should not exceed the target

//check if height and width are larger than required and then scale 
if($source_imagey>524 || $source_imagex > 700) {
if($source_imagey>$source_imagex){
   $new_height = 524;       
       $new_width = 524/$source_imagey*$source_imagex;
}else{
   $new_width = 700;
       $new_height = 700/$source_imagex*$source_imagey;     
    } 
 }

 $dest_image = imagecreatetruecolor($new_width, $new_height);

 //poor quality but fast 
 imagecopyresized($dest_image, $source_image, 0, 0, 0, 0, $new_width,
 $new_height, $source_imagex, $source_imagey);
 imagejpeg($dest_image,"final.jpg", 80);


 //better quality but slow 
 imagecopyresampled($dest_image, $source_image, 0, 0, 0, 0, $new_width,
 $new_height, $source_imagex, $source_imagey); 
 imagejpeg($dest_image, 'final2.jpg', 80);

 //create square thumbnail 
 // resize image to scale shorter side to 90px 
 if($new_width>90 || $new_height>90) {  
    if($new_height>$new_width)  
    {       
       $thumb_height = (90/$new_width)*$new_height;             
       $thumb_width = 90;
       $top = ($tHeight - 90)/2;
       $left = 0;   
    }else{
   $thumb_width = (90/$new_height)*$new_width;
   $thumb_height = 90;
       $left = ($thumb_width-90)/2;         
       $top = 0;    
    } 
 }
 $image_t = imagecreatetruecolor($thumb_width,$thumb_height);   
 imagecopyresampled($image_t, $dest_image, 0, 0, 0, 0, $thumb_width,
 $thumb_height, $new_width, $new_height);

 $thumb_image = imagecreatetruecolor(90,90); 
 imagecopy($thumb_image, $image_t, 0, 0, $left, $top,
 $thumb_width,$thumb_height); 
 imagejpeg($thumb_image, 'thumb.jpg', 80);

 imagedestroy($thumb_image); 
 imagedestroy($dest_image);    
 imagedestroy($image_t);

Is this approach of creating a temporary image of smaller size and then copying thumbnail from it, correct ? Is there an alternative to this ? How can it be further optimized ?

UPDATE: The class that I have created, with the above code and some help and insight gained from the link at nettuts, can be found on github

\$\endgroup\$
  • 1
    \$\begingroup\$ This is a small recommendation. You should wrap this all in a class. This makes everything modular so you can easily reference the image source without having to manually go through everything. \$\endgroup\$ – Keiran Lovett Sep 10 '12 at 9:50
  • \$\begingroup\$ @KeiranLovett: Thanks for the suggestion. I too intend to wrap this in the class. Even inside the class, whether this approach is right or not, or is there a better way to do it ? \$\endgroup\$ – gentrobot Sep 10 '12 at 10:54
  • \$\begingroup\$ I've had to do something similar to this twice. I found using a premade class and tweaking it to better suit your needs is better. As people here like to say again and again "Why reinvent the wheel?" I'd recommend taking a look at this here - if you think net-tuts has a better approach then use it! net.tutsplus.com/tutorials/php/… \$\endgroup\$ – Keiran Lovett Sep 10 '12 at 13:32
  • \$\begingroup\$ @KeiranLovett: I have created a class, as you suggested. I am yet to add a method to generate the thumbnails. \$\endgroup\$ – gentrobot Sep 12 '12 at 10:10
  • 1
    \$\begingroup\$ Instead of using the file extension to determine which image function you should be using, I would suggest looking at the exif_imagetype function. This function returns one of the IMAGETYPE_XXX constants, which you can use to determine which one of the image functions to use. This will be more accurate, because even if someone renames a JPEG as .gif, it will still return the correct image type. \$\endgroup\$ – AndrewR Sep 12 '12 at 20:30
3
\$\begingroup\$

Please don't count this as an answer. I've never done anything with any of the image libraries before, so I can't help you with the specifics. I would have put this into a comment, but its obviously too big. However, here are a few things to ponder.

First, in regards to the comments Keiran Lovett made, a class may make this a little simpler to work with, but it may also add an unnecessary level of overhead or abstraction. This seems like a relatively simple application, thus the overhead and abstraction that a class would introduce may not be worth it. It depends on a number of things, but the main ones I would contemplate are if I were going to be doing a lot of different things with these images, or how much simpler or faster/slower it would make it. Either way, I definitely would start using functions, and then if you decide to use a class it will make the transition easier.

Your maximum width and height should be made into constants, or at the very least variables. This avoids the "magic numbers" and makes it easier to use and update these values should you ever decide to change them.

define( 'MAX_Y', 524 );
define( 'MAX_X', 700 );

How do you treat images that have been rotated? An image flipped to a different aspect ratio would result in a smaller image on one axis and a skewed thumbnail. Or at least, so it would seem to me. I'm not sure how to do this, but it is something you may want to look in to.

And finally, in regards to how memory intensive this is going to be, I don't know. The best way to find out would be to run some tests and profile it. Create 100 (or more) oversize images and run the necessary code in a loop to convert each one. This is where having functions would be handy.

$start = microtime( TRUE );
for( $i = 0; $i < 100; $i++ ) {
    //functions to scale and convert
}
$total = microtime( TRUE ) - $start;
\$\endgroup\$
  • \$\begingroup\$ I really am not sure whether to accept this as an answer, but you really gave me very valuable suggestions. I simply wish I could upvote it more than once :D \$\endgroup\$ – gentrobot Sep 10 '12 at 17:59
  • \$\begingroup\$ I don't believe I understand the basic elements of this enough for it to count as an answer. If you disagree, that's fine, I just don't feel it should count as an answer. Glad I could be of some help though :) \$\endgroup\$ – mseancole Sep 10 '12 at 18:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.