image creating slow down servre - php

I have function and with this funqction I`m trying to create some images in my server
foreach($value[0] as $imagekey => $imageval) {
$imgname = $gancxadeba . '_' . $imagekey;
$saveaddr = dirname(dirname($_SERVER['PHP_SELF'])).'/www/classifieds_images/';
$as = '.JPG';
$originalname = $imgname . $as;
if(!file_exists($saveaddr.$originalname)) {
if (preg_match('/\.(jpg)$/', $imageval)) {
$getfile = imagecreatefromjpeg($imageval);
} elseif (preg_match('/\.(JPG)$/', $imageval)) {
$getfile = imagecreatefromjpeg($imageval);
} elseif (preg_match('/\.(png)$/', $imageval)) {
$getfile = imagecreatefrompng($imageval);
} else {
$getfile = imagecreatefromgif($imageval);
}
list($width, $height) = getimagesize($imageval);
$newWidth = 90;
$newHeight = 120;
$original = imagecreatetruecolor($width, $height);
imagecopyresampled($original, $getfile, 0, 0, 0, 0, $width, $height, $width, $height);
imagejpeg($original, "../www/classifieds_images/$originalname");
echo 'განცხადება: ' . $gancxadeba . ' ორიგინალი სურათი: ' . $imgname . ' created!' . PHP_EOL;
$thumbname = $imgname . '_THUMB' . $as;
if (!file_exists($saveaddr . $thumbname)) {
$thumb = imagecreatetruecolor($newWidth, $newHeight);
imagecopyresampled($thumb, $getfile, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
imagejpeg($thumb, "../www/classifieds_images/$thumbname");
echo 'განცხადება: ' . $gancxadeba . ' თამბი სურათი: ' . $imgname . ' created!' . PHP_EOL;
}
}
$image[$imagekey] = $imgname;
}
as you understand Im getting image link and then chacking if file exists and Im creating file if it not exists.
but my server slow down.
it is using 2GB RAM.
what can I do to accelerate my server?
I tryed file_put_content() first and then creating thumb
but it not working as well as gd library.
so please help me to do this function quicker than is.

One thing to note (not really an answer to your problem):
When using GD2 functions, don't trust file extension. Someone could save JPEG with name "trollpic.gif" and cause your imagecreatefromgif to throw an error.
Use exif data instead:
http://php.net/manual/en/function.exif-imagetype.php
Also - you could try imegemagick as an alternative to GD2 if that's possible (it's not on some cheaper hosting services).
[EDIT]
$original = imagecreatetruecolor($width, $height);
imagecopyresampled($original, $getfile, 0, 0, 0, 0, $width, $height, $width, $height);
imagejpeg($original, "../www/classifieds_images/$originalname");
Looks like $getfile and $original both keep the same data.
Check if this will work:
$original = imagecreatetruecolor($width, $height);
imagejpeg($getfile, "../www/classifieds_images/$originalname");
It's not the best you can do to optimize your code, but at least it's a start.
I'd recommend setting some limit to how many files can be processed in one execution of the script and queueing it - that's the best you could do if you're trying to process a lot of data, not necessarily image related.
[EDIT2]
Also - unset variables when they're no longer needed.
When you've done everything to an image and saved it in a file - destroy the resource. It won't remove image file, just drop its data from memory.
http://php.net/manual/en/function.imagedestroy.php

Related

How can I resize an image from URL using PHP?

I'm receiving Images from URLs and I would like to save these images into a new directory, in three different sizes. I'm already getting the URLs here, now I just need a way to resize each image, with a specific height and width.
I dont want to resize uploaded images, only Images from a specific URL.
My code:
$content = file_get_contents('http://www.joomlaworks.net/images/demos/galleries/abstract/7.jpg');
$name = "http://www.joomlaworks.net/images/demos/galleries/abstract/7.jpg";
$parts = explode('.', $name);
$new_url = rand(0, pow(10, 5)) . '_' . time() . '.' . $parts[count($parts) - 1];
file_put_contents(DIRECTORY.'/' . $new_url , $content);
How can I do that? Thanks.
here is the solution based on imagecopyresampled (GD library) http://php.net/manual/en/function.imagecopyresampled.php
$content = file_get_contents('http://www.joomlaworks.net/images/demos/galleries/abstract/7.jpg');
$name = "http://www.joomlaworks.net/images/demos/galleries/abstract/7.jpg";
$parts = explode('.', $name);
$new_url = rand(0, pow(10, 5)) . '_' . time() . '.' . $parts[count($parts) - 1];
file_put_contents(DIRECTORY.'/' . $new_url , $content);
resizeImage($new_url, DIRECTORY.'/1_' . $new_url, 100, 100);
resizeImage($new_url, DIRECTORY.'/2_' . $new_url, 200, 200);
resizeImage($new_url, DIRECTORY.'/3_' . $new_url, 300, 300);
function resizeImage($source, $dest, $new_width, $new_height)
{
list($width, $height) = getimagesize($source);
$image_p = imagecreatetruecolor($new_width, $new_height);
$image = imagecreatefromjpeg($source);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
imagejpeg($image_p, $dest, 100);
}

Resizing a BLOB image in PHP before sending to client

I have an image of which I am fetching from a database as a BLOB however I am sending the client the full size image of which is then resized on their side. The images can get very large so I would like to resize the image before it is sent to the client.
I currently have the following code:
if (!empty($row['img'])) {$img = $row['img'];}
$width = imagesx(imagecreatefromstring($img));
$height = imagesy(imagecreatefromstring($img));
$resizer = $width/200;
$newHeight = floor($height/$resizer);
$news = $news . "<div class='newsItem' style='min-height:".$newHeight."px;'>";
if (isset($img)) {$news = $news . "<img src='data:image/jpeg;base64,".base64_encode($img)."' width='200' height='".$newHeight."'>";}
$news = $news . "<h2>".$title."</h2><hr class='newsHr'><span>".$text."</span></div>";
What functions can I use to resize $img?
This should work for you. Example taken from this Manual
<?php
// Load
$thumb = imagecreatetruecolor($newwidth, $newheight);
$source = imagecreatefromjpeg($filename);
// Resize
imagecopyresized($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
// Output
imagejpeg($thumb);
?>
To convert BLOB mage to file use.
file_put_contents('/path/to/new/file_name', $my_blob);
Works with me!
<?php
function resize($blobImage, $toWidth, $toHeight) {
$gdImage = imagecreatefromstring($blobImage);
if ($gdImage) {
list($width, $height) = getimagesizefromstring($blobImage);
$gdRender = imagecreatetruecolor($toWidth, $toHeight);
$colorBgAlpha = imagecolorallocatealpha($gdRender, 0, 0, 0, 127);
imagecolortransparent($gdRender, $colorBgAlpha);
imagefill($gdRender, 0, 0, $colorBgAlpha);
imagecopyresampled($gdRender, $gdImage, 0, 0, 0, 0, $toWidth, $toHeight, $width, $height);
imagetruecolortopalette($gdRender, false, 255);
imagesavealpha($gdRender, true);
ob_start();
imagepng($gdRender);
$imageContents = ob_get_contents();
ob_end_clean();
imagedestroy($gdRender);
imagedestroy($gdImage);
return $imageContents;
}
}
$image = '<img src="data:image/jpeg;base64,'. base64_encode( resize($row['image_data'], 45, 45) ) . '" />';

GD script fails to process all images in array

I've been building a gallery in php as a learning exercise and also because I'll need one to display my wedding photos in a couple of months.
I have written a function that processes the images. It looks to see what images are in the original folder and generates a thumbnail and preview for each. It's worked fine up until now as I've been testing with small batches of images.
Now I have 24 images in the original folder it only process the first 18. I don't get any errors displayed it just seems to stop.
Function
function processImgs($previewWidth, $thumbWidth, $thumbPath, $previewPath, $originalPath) {
$images = glob($originalPath."*");
foreach($images as $image){
$path_parts = pathinfo($image);
// setup filenames
$thumbFile = $thumbPath . "thumb_" . $path_parts['filename'] . ".jpg";
$previewFile = $previewPath . "preview_" . $path_parts['filename'] . ".jpg";
// calculate new images sizes
$size = getimagesize($image);
$originalWidth = $size['0'];
$originalHeight = $size['1'];
$previewHeight = $originalHeight / ($originalWidth / $previewWidth);
$thumbHeight = $originalHeight / ($originalWidth / $thumbWidth);
//create new images
$original = imagecreatefromjpeg($image);
$preview = imagecreatetruecolor($previewWidth, $previewHeight);
$thumb = imagecreatetruecolor($thumbWidth, $thumbHeight);
imagecopyresampled($preview, $original, 0, 0, 0, 0, $previewWidth, $previewHeight, $originalWidth, $originalHeight);
imagecopyresampled($thumb, $original, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $originalWidth, $originalHeight);
// save images to their new folders
imagejpeg($preview, $previewFile);
imagejpeg($thumb, $thumbFile);
imagedestroy($original);
imagedestroy($preview);
imagedestroy($thumb);
// give some feedback when the script runs
if (file_exists($thumbFile) && file_exists($previewFile)) {
echo ". " . $path_parts['filename'] . " processed successfully.<br>";
} else {
echo ". " . $path_parts['filename'] . " <strong>failed.</strong><br>";
}
}
}
I call the function like this
processImgs(1200, 400, "thumb/", "preview/", "original/");
I don't know why it doesn't work with more files. Is there a time limit that I could be hitting? It does take a while. I'm currently building this locally on MAMP.
UPDATE
Mike was correct, the function was timing out. His solution is much more suitable.
I have now created a script that does what he suggested and it has solved the problem. Thanks for the help. I've added the script below in case it's of use to others.
$newWidth = 400;
if (isset($_GET['img'])) {
$img = $_GET['img'];
$filename = $img . ".jpg";
if (file_exists($filename)) {
$fp = fopen($filename, 'rb');
header("Content-Type: image/jpeg");
header("Content-Length: " . filesize($filename));
fpassthru($fp);
exit;
} else {
$originalFile = "../original/" . $filename;
$original = imagecreatefromjpeg($originalFile);
$size = getimagesize($originalFile);
$newHeight = $size['1'] / ( $size['0'] / $newWidth);
$new = imagecreatetruecolor($newWidth, $newHeight);
imagecopyresampled($new, $original, 0, 0, 0, 0, $newWidth, $newHeight, $size['0'], $size['1']);
imagejpeg($new, $filename);
imagedestroy($original);
imagedestroy($new);
$fp = fopen($filename, 'rb');
header("Content-Type: image/jpeg");
header("Content-Length: " . filesize($filename));
fpassthru($fp);
}
}

Resizing and moving an image

I'm kind of a beginner in PHP and here's what I'm trying to do:
Recieve an uploaded image and move it to temp/ folder
Examine it and decide whether it needs to be resized or not (it needs, if it's not 135px wide)
If needs to be resized, resize it and save as results/{number}_cover.jpg
If it doesn't, copy an uploaded image right away to the same place, without resizing
And here's my code:
$target_path = "temp/";
$target_path = $target_path . basename($_FILES["file" . $a]["name"]);
move_uploaded_file($_FILES["file" . $a]["tmp_name"], $target_path);
list($current_width, $current_height, $type, $attr) = getimagesize($target_path);
if($current_width != 135) {
$filename = $a . "_cover.jpg";
$result_image = "results/" . $filename;
$writing = fopen($result_image, 'w');
$scale = (135 / $current_width);
$new_width = 135;
$new_height = $current_height * $scale;
$result_image = imagecreatetruecolor($new_width, $new_height);
$current_image = imagecreatefromjpeg($target_path);
imagecopyresampled($result_image, $current_image, 0, 0, 0, 0, $new_width, $new_height, $current_width, $current_height);
imagejpeg($result_image, null, 100);
fclose($writing);
} else {
$target_path = "results/";
$target_path = $target_path . $a . "_cover.jpg";
move_uploaded_file($_FILES["file" . $a]["tmp_name"], $target_path);
}
However, this is what this code does for me:
1. If an image needs resizing, it just give me an image data to the browser instead of saving it to the file
2. If it doesn't need resizing, nothing happens.
What am I doing wrong?
Thanks in advance for your help!

Reading image from a local temporary file using php

Scenario : Earlier I was reading the url of image directly and resized the image into 4 different size . But I had execution time out . Now I read the url and copy it into a temporary folder and pass the images in local temporary folder to imagecreatefromjpeg().
protected static function saveImage($row,$url){
$percent = 1.0;
$imagethumbsize = 200;
$db = PJFactory::getDbo();
$details = $db->getImageDetails();
$max = sizeof($details);
$tempfilename = "C:".DS."xampp".DS."htdocs".DS."opg-uat".DS."img".DS."temp".DS.$row['CategoryID'].".jpg";
$tempcopy = copy($url,$tempfilename);
foreach ($details as $array) {
$new_width=$array[2];
$new_height=$array[3];
$newfilename = "C:".DS."xampp".DS."htdocs".DS."opg-uat".DS."img".DS."c".DS.$row['CategoryID']."-".$array[1].".jpg";
$image_p = imagecreatetruecolor($new_width, $new_height);
$image = imagecreatefromjpeg($tempfilename);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
imagejpeg($image_p, $newfilename);
}
}
Error : The images are correctly being saved in temp folder . But in the destination folder images of all sizes are created but the image looks only black . (Not getting the actual image) . I guess there is some problem with the file reading from local .
Any idea ?
Thanks in advance.
If you are trying to read files other than JPG files, it will return only black images,
So while reading images, check which filetype your file really has and then call the correct function between the three (jpeg, png, gif).
Do you set $width and $height anywhere?
$width = imagesx($image);
$height= imagesy($image);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);

Categories