Watermarking using too much CPU time

On a property website I'm dynamically watermarking images using script that can be found here
http://phpexample.ucoz.com/publ/watermarks_usage/1-1-0-5
This works beautifully as we don't want to permanently watermark images as these are included in several feeds to portal sites where they apply their own watermark.

However, the hosting company are now saying that this script is using up too much CPU time.

Anyone got any ideas as to how we can overcome this?
LVL 1
fionafentonAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Hugh McCurdyCommented:
How about two copies of the images, one with the watermark and one without?
0
DerokorianCommented:
Personally I would save every image once its been watermarked. Then in your script you could check for the image existance. If it doesn't exist create it however if it does just output the existing image. Something like the following (note I've used my own watermark function as I dont like that class you linked lol but you could change it to use it)

<?php
// define a default watermark if none specified
define('DEFAULT_WATERMARK',   'watermark.png');

// I would prefer to do this with id's and a database lookup
// but for simplicity url might be image.php?image=picture101.jpg&wm=company_logo.png
$image = isset($_GET['image']) ? $_GET['image'] : FALSE;
if( !$image ) die('No image specified.');

$wm = isset($_GET['wm']) ? $_GET['wm'] : DEFAULT_WATERMARK;

$img_name = pathinfo($image,PATHINFO_FILENAME);
$wm_name = pathinfo($wm,PATHINFO_FILENAME);
$output_name = $img_name . '_' . $wm_name . '.png';

// Check if the watermark image already exists
if( file_exists($output_name) ) {
   $output = imagecreatefrompng($output_name);
} else {
   $output = watermark($image,$wm);
   imagepng($output,$output_name);
}

// output the image to the browser
header('Content-type: image/png');
imagepng($output);
imagedestroy($output);

function watermark($base,$watermark) 
{
   list($basew,$baseh) = getimagesize($base);
   list($wmw,$wmh) = getimagesize($watermark);
   
   // Get the scale for the watermark
   if( $basew > $baseh ) 
   {
      $wmscale = ($basew/2)/$wmw;
   } else 
   {
      $wmscale = ($baseh/2)/$wmh;
   }
   $newwmw = $wmw*$wmscale;
   $newwmh = $wmh*$wmscale;

   // Create the watermark the right size
   $wmimg = imagecreatefrompng($watermark);
   $newwmimg = imagecreate($newwmw,$newwmh);
   imagecopyresized($newwmimg,$wmimg,0,0,0,0,$newwmw,$newwmh,$wmw,$wmh);
   imagedestroy($wmimg);

   // Open the image, place watermark on it
   $baseimg = imagecreatefromjpeg($base);
   $dst_x = ($basew/2) - ($newwmw/2);
   $dst_y = ($baseh/2) - ($newwmh/2);
   imagecopy($baseimg,$newwmimg,$dst_x,$dst_y,0,0,$newwmw,$newwmh);
   imagedestroy($newwmimg);

   return $baseimg;
}
?>

Open in new window


HTH

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Hugh McCurdyCommented:
Derokorian, while yours is a variation of my answer, I like yours better.  The watermarked copy is made only if needed.  Of course, it's kept (which is my solution).  I also like your solution because it looks simple to implement and it will (almost certainly) solve the problem, as stated.

Now, if the problem is different than stated, this isn't solved.  If the watermark is supposed to contain information about the recipient, we still have a problem.

Fiona?  Are the watermarks unique to each recipient?

If they are, all I can think of is to make the code more efficient.  Perhaps run the water mark software in C if possible.
0
Cloud Class® Course: MCSA MCSE Windows Server 2012

This course teaches how to install and configure Windows Server 2012 R2.  It is the first step on your path to becoming a Microsoft Certified Solutions Expert (MCSE).

DerokorianCommented:
@hmccurdy I didn't want to suggest that you weren't right, I was merely showing how I implement the idea you already proposed - except to allow for as many watermarks as needed. Our solution would reduce CPU/RAM usage significantly and increase HD usage. However HD storage is a dime a gig (maybe even a dime a tera!)

@fiona another problem could be the size of the images, if the resolution is very high you could think about resizing them down to a more reasonable resolution when you upload them. IE if the image will never be displayed higher than 1024x768 why store it at 3200x2400 anyway? Especially since it will hog more resources to watermark / output.
0
fionafentonAuthor Commented:
Derokorian: Your solution is along the lines of what I had already concluded I would have to do. I was hoping there might be some other solution that I hadn't thought of. I have the additional problem that photos are often changed (but file names aren't).
I think the simplest solution is to include all this in the image upload script, which already resizes all the images and creates the folders and thumbnails. I'll just get it to create an extra folder and watermark the images at the same time. That way I can be sure that the watermarked and unwatermaked images are the same.
0
Hugh McCurdyCommented:
@Derokorian -- No issues with you.  I didn't think you were suggesting I wasn't right.  I like your idea.

@Fiona -- I don't think there's a better approach than we've discussed.  I think you are right about an image upload script.  If you blend in some of Derokorian's code (or write your own) with the existing script, I think you'll have the best possible solution.

The only other idea I have is to push some of the PHP work off to C/C++.  Alternatively, compile the PHP code (something I've never done) so that it doesn't go through the interpreter. But I suspect the expense of development makes that solution "not best."
0
fionafentonAuthor Commented:
Thank you both for your input. I have some code rewriting to do!
0
Hugh McCurdyCommented:
You're welcome.
0
DerokorianCommented:
Glad to help! If you need help rewriting code - feel free to post what you have and explain what you need and we'll be here!

Good luck!
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Web Development

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.