This question already exists:
Closed 10 years ago.
Possible Duplicate:
Thumbnails in php generated gallery loading slow
Code link can be found on the bottom of the page.
The site is running from 1and1.co.uk linux based system, good enough to load the gallery much faster than it currently does.
The php generated thumbnails are loading a bit slow, can you tell me why?
http://site-perf.com/cgi-bin/show.cgi?id=vz5le19Fp5E
code:
http://satinaweb.com/tmp/functions.txt
Here is crop.php:
$sourceimage = $_GET['a'];
function crop($sourceimage) {
// Draw & resize
header('Content-Type: $imsz[\'mime\']');
list($width, $height) = getimagesize($sourceimage);
if($width > $height){
$new_width = 100;
$new_height = 75;
} else {
$new_width = 75;
$new_height = 100;
}
$image = imagecreatefromjpeg($sourceimage);
$image_p = imagecreatetruecolor($new_width, $new_height);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
imagejpeg($image_p);
imagedestroy($image_p);
imagedestroy($image);
}
crop($sourceimage);
If you have questions, please ask!
What you should have noticed from your site-perf graph most is that,
I'm not going to look through all your code, but you have a file called crop.php. This is going to be slow because it (presumably) crops the images on every page load, which takes a relatively long time (made apparent from the site-perf data); for each request, the browser spends most of it's time waiting for the server to respond.
You should consider using a cache folder to store cropped images and serve them up as-is to reduce loading time.
In crop.php, you could do something like this (pseudo code):
IF original image newer than cropped OR cropped doesn't exist
Load original image
Crop original image
Save cropped image to cache folder
ELSE
Serve already-cropped image from cache
ENDIF
Every time you call crop(), you read the image, modify it and spit it out to the client. This is incredibly wasteful, because you need to re-process the image for every request. You're even destroying the image afterwards (not that this makes much difference). Instead, use is_file() with a cache directory, and save the image to disk as well as sending it to the client.
Now, your script might look like this:
$sourceimage = $_GET['a'];
$cache_dir = dirname(__FILE__) . "/cache"; // Cache directory
$cache_file = $cache_dir . '/' . $source_image; // Path to cached image
function crop($sourceimage) {
header('Content-Type: $imsz[\'mime\']');
// If cached version of cropped image doesn't exist, create it
if(!is_file($cache_file)) {
list($width, $height) = getimagesize($sourceimage);
if($width > $height) {
$new_width = 100;
$new_height = 75;
} else {
$new_width = 75;
$new_height = 100;
}
$image = imagecreatefromjpeg($sourceimage);
$image_p = imagecreatetruecolor($new_width, $new_height);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
imagejpeg($image_p, $cache_file); // Save image file to disk
} else { // If cached file exists, output to browser without processing
echo file_get_contents($cache_file);
}
}
crop($sourceimage);
This is untested, but should work. Please don't just copy and paste the above code; read through it and make sure you understand how and why it does what it does.
Your page is loading slowly due to HTTP requests being queued.
Although each image is small, the requests are spending a large proportion of their time queued, waiting for other requests to finish before they start, in the worst cases, they are waiting for one and a half seconds before they even start downloading.
The second delay is then caused by the time it takes to create the images.
The actual download was nearly instant after waiting for these other processes.
Queued 1600ms
Waiting 986ms
Download 0ms
Rather than generate the correct sized images every time, why not store the result to be used on subsequent visits - this means the page will be slow once and then much faster all other times.
If the time your script took to crop the images was shorted, the queueing would be shorter too. Here is an example...
Check in a folder for the cropped image
If it exists, serve it (no computation required)
If it doesn't exist, generate it
Save the result in the folder to cache it
Related
UPDATE:
now I learned more I looked alot and modified I got this:
function show_image($image, $new_width, $new_height) {
//$this->helper('file'); why need this?
//$image_content = read_file($image); We does not want to use this as output.
list($old_width,$old_height) = getimagesize("$image");
//resize image
$image = imagecreatefromjpeg($image);
$thumbImage = imagecreatetruecolor($new_width, $new_height);
imagecopyresized($thumbImage, $image, 0, 0, 0, 0, $new_width, $new_height, $old_width, $old_height);
imagedestroy($image);
//imagedestroy($thumbImage); do not destroy before display :)
ob_end_clean(); // clean the output buffer ... if turned on.
header('Content-Type: image/jpeg');
imagejpeg($thumbImage); //you does not want to save.. just display
imagedestroy($thumbImage); //but not needed, cause the script exit in next line and free the used memory
exit;
}
when using this function I get a file, but I need to get a URL
I wanna be able to use:
<img src=" ... ">
Since you can't use GD on the server, a good option might be to handle it on the client side.
One idea that comes to mind is loading the image into an html5 canvas, and using that to manipulate the image characteristics before uploading it to the server.
This post talks about how you'd go about uploading image data straight from a canvas and saving it as an image on your server.
How to save a HTML5 Canvas as an image on a server
You also will likely need to take a look at the JavaScript File API to load the image into the canvas on the client side.
It's not necessarily an easy solution, but it might be your best shot without access to GD and stuff.
Background
I have read through many sites including this one for a solution. I have a watermark script which up until a few months ago worked flawlessly. My hosting provider performed routine updates and hosed my script. I made one adjustment to it, it worked. With time, the watermark script seems be very heavy on system resources, causing all sorts of issues with my site including images not loading at random, etc. Currently, it appears I could run the site on PHP version 5.4 or a version or two above and below it. Currently running at 5.4 if that should help.
Explanation
The script is intended to find image files from a specific location, pending on size, combine with one of several png images on the fly without overwriting the original image.
The script
I have modified my script significantly in the past week, with minor performance improvement. I'm at my wits end, are there further improvements to this script to be made or cleaner code. Any assistance would greatly be appreciated.
Files
.htaccess, three jpg(s), and the watermark.php script.
.htaccess
RewriteRule ^(.*)wp-content/uploads/(.*) $1watermark.php?src=wp-content/uploads/$2
watermark.php
<?php
$src = $_GET['src'];
if(preg_match('/.gif/i',$src)) { $image = imagecreatefromgif($src); }
if(preg_match('/.png/i',$src)) { $image = imagecreatefrompng($src); }
if(preg_match('/.jpeg/i',$src)||preg_match('/.jpg/i',$src)) { $image = imagecreatefromjpeg($src); }
if (!$image) exit();
// if (empty($images)) die();
if (imagesx($image) > 301 ) { $watermark = imagecreatefrompng('watermark.png'); } // height greater than 301 then apply watermark 600x600
elseif (imagesx($image) > 175 ) { $watermark = imagecreatefrompng('watermarksm.png'); } // height greater than 175 then apply small watermark 200x200
else { $watermark = imagecreatefrompng('empty.png'); } // apply a dummy watermark resulting in none. 1x1
$dest_x = imagesx($image) - imagesx($watermark) - 0;
$dest_y = imagesy($image) - imagesy($watermark) - 0;
imagecopy($image, $watermark, $dest_x, $dest_y, 0, 0, imagesx($watermark), imagesy($watermark));
header('content-type: image/jpeg');
imagejpeg($image);
imagedestroy($image);
imagedestroy($watermark);
//die();
?>
A couple of things I have tried not reflected in this script is the following "minor" change.
if(preg_match('/.gif/i',$src)) to if(preg_match('/\.gif$/i',$src))
Another variation attempted in the preg_match was with jpe$g and jp(|e)g$. Those change didn't seem to help in anyway and seemed to hurt the performance further.
Again, any guidance would be appreciated. Thank you in advance.
Why don't you once for all create watermarked version of all your images ? It will avoid the server to work each time an image will be displayed on your website, and you will gain in performance.
If for any reason you need to display the original image, do a script that check the credential of the viewer then return the image.
First of all, those regular expressions are not the performance hogs. The real performance problems comes from image manipulation.
Save the result from imagejpeg($image); into a file on disk "hidden" from the world. You can restrict access to that folder with .htaccess.
The the logic should be something like this:
<?php
// Implement getTempFile to get a path name to the hidden folder.
$tempsrc = getTempFile($src)
$tempsrcexists = file_exists($tempsrc);
if (!$tempsrcexists)
{
// Create image on disk.
...
}
// At this point, the temporary file must exist.
$fp = fopen($tempsrcexists, 'rb');
// Output data to the client from the temporary file
header("Content-type: image/jpeg");
fpassthrough($fp);
fclose($fp);
?>
This should reduce the load on the server significantly.
I posted earlier about another resizing script not working and I got a little farther with this script which does things a little differently.
I got a little farther, only now there is a new problem. The first three lines of the code successfully place three identical files in the target directory with the file and it's two thumbnail files named accordingly. I then want to load the thumbnails, which are still full-size, and resize them but the script stops at imagecreatefromjpeg() and I can't seem to figure out why because $src has a value.
I thought that I could possibly remove that line and replace $source with $src in my imagecopyresized() function, and that gets me even closer. But it then returns a thumbnail of the target size, but the thumbnail is black.
move_uploaded_file($tmpFilePath, $newFilePath);
copy($newFilePath, $thumb500);
copy($newFilePath, $thumb200);
function thumbImage($src, $dest, $newheight) {
list($width, $height) = getimagesize($src);
$newwidth = $width * ($newheight / $height);
// Load
$thumb = imagecreatetruecolor($newwidth, $newheight);
header('Content-type: image/jpeg');
$source = imagecreatefromjpeg($src);
// Resize
imagecopyresized($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
// Output
imagejpeg($thumb, $dest);
}
thumbImage($thumb500, $thumb500, 500);
thumbImage($thumb200, $thumb200, 200);
I feel as if this must be a common issue. Any suggestions anyone?
For me the supplied code block works if I use a JPEG image as source.
The problem may be that you use a PNG image that uses transparency. As JPEG can not handle transparencies, the transparent background colour will be filled. Maybe that is the problem. If not, please provide a sample image that has the problematic behaviour.
5
imagecopyresized takes an image resource as its second parameter, not a file name. You'll need to load the file first. If you know the file type, you can use imagecreatefromFILETYPE to load it. For example, if it's a JPEG, use imagecreatefromjpeg and pass that the file name - this will return an image resource.
If you don't know the file type, all is not lost. You can read the file in as a string and use imagecreatefromstring (which detects file types automatically) to load it as follows:
{$oldImage = imagecreatefromstring(file_get_contents($_FILES['image']['tmp_name']));
}
enter code here
I have a bunch of product preview images, but they are not the same dimensions.
So i wonder, is it possible to crop an image on the go, without saving it?
These two links should show what i mean:
http://xn--nstvedhandel-6cb.dk/alpha_1/?side=vis_annonce&id=12
http://xn--nstvedhandel-6cb.dk/alpha_1/?side=vis_annonce&id=13
Yes it's possible here's how i do it:
//Your Image
$imgSrc = "image.jpg";
list($width, $height) = getimagesize($imgSrc);
$myImage = imagecreatefromjpeg($imgSrc);
// calculating the part of the image thumbnail
if ($width > $height)
{
$y = 0;
$x = ($width - $height) / 2;
$smallestSide = $height;
}
else
{
$x = 0;
$y = ($height - $width) / 2;
$smallestSide = $width;
}
// copying the part into thumbnail
$thumbSize = 100;
$thumb = imagecreatetruecolor($thumbSize, $thumbSize);
imagecopyresampled($thumb, $myImage, 0, 0, $x, $y, $thumbSize, $thumbSize, $smallestSide, $smallestSide);
//final output
header('Content-type: image/jpeg');
imagejpeg($thumb);
This is not a verry light operation, like the others i also reccomend you to save the thumbnail after creating it to your file system.
You might wanna check out PHP's GD library.
You might wanna try this simple script: https://github.com/wes/phpimageresize
It also allows for caching, which should help with performance issues.
But I also prefer resizing images and saving them as thumbnails.
It certainly is possible, but what you are wanting to do probably isn't a good idea - here's why.
If you crop an image, save it, you (or rather your server) never needs to do it again. It's not a light operation.
However, if you keep cropping on the fly, your server will have to do that work each and every single time - which is quite inefficient.
As a worst case scenario, why not automatically crop them once to the dimensions you want (rather than doing it manually) and simply save those results?
Lastly, given that it is a store, wouldn't manually cropping them give your products the best possible images - and thereby the best chance of selling them?
how to take image from one folder and rename and re-size the images and move to another folder?
I need to get image from one folder and rename and re-size the same image and move into another folder using php
You will most likely be using gd for resizing the images.
Here is a pretty crappy, but hopefully useful code sample. In this case, $originalName is the name given in the $_FILES array's tmp_name position. I am resizing to a width of 1200 in this case, with the height adapting according to such width. You might (and most likely will) not desire this behavior. This is just some ugly code I used in some courses I taught about 3 years ago, I don't have the newer samples in this computer so you will have to get used to the idea :)
$newDir is where the file will be located. by calling imagejpeg or imagepng and passing the filename as second argument, it means to the function that you wish to save the image in that location.
if ($type == 'image/jpeg') {
$original = imagecreatefromjpeg($originalName);
}
else {
$original = imagecreatefrompng($originalName);
}
$width = imagesx($original);
$height = imagesy($original);
//prepare for creation of image with width of 1000
$new_height = floor($height * (1200 / $width));
// create the 1200 width image
$tmp_img = imagecreatetruecolor(1200, $new_height);
// copy and resize old image into new image
imagecopyresized($tmp_img, $original, 0, 0, 0, 0,
1200, $new_height, $width, $height);
//create a random and unique name to identify (here it isn't that random ;)
$newDir = '/this/is/some/directory/and/filename.';
if ($type == 'image/jpeg') {
imagejpeg($tmp_img, $newDir."jpg");
}
else {
imagepng($tmp_img, $newDir."png");
}
Many file system functions are already built-in with PHP (e.g. rename), and you'll find most of what you need to resize images by using the GD library here.
There are libraries available in PHP for image resize.
Here are some useful links you may like.
http://www.fliquidstudios.com/2009/05/07/resizing-images-in-php-with-gd-and-imagick/
http://php.net/manual/en/book.image.php
PHP/GD - Cropping and Resizing Images
http://net.tutsplus.com/tutorials/php/image-resizing-made-easy-with-php/
Use imagick http://php.net/manual/en/imagick.resizeimage.php
If I were you I would write a PE using a diffent language (one that you might be best used to) to adjust anything of the given image then just feel free to phpexec it to do all the steps you mentioned, you can sit relax and wait for the end result. HHAHAHHA :-)
Use imagick library to resize; it's good.