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);
}
}
Related
This is my index.php file, i have uploaded and moved image from tmp folder to image folder and it's working properly. but now i want to trim image on display, every picture should be display of same size, i have tried lots of way but it's not working.
Need for help!!
<?php
require_once('appvars.php');
include 'db_connect.php';
$sql = "SELECT * FROM gitarwar";
$data = mysqli_query($dbc, $sql);
echo "<table>";
while ($row = mysqli_fetch_array($data))
{
echo '<tr><td>';
echo '<strong>' . $row['Score'] . '</strong><br/>';
echo '<strong>Name:</strong>' . $row['Name'] . '<br/>';
echo '<strong>Datetime:</strong>' . $row['Datetime'] . '<br/>';
echo '<img src="' .GW_UPLOADPATH . $row['Screenshot'] . '" alt="Score image" />';
echo "</tr>";
}
echo"</table>";
mysqli_close($dbc);
?>
I had a similar task before. My job was to check the image, and if it is smaller than my $newWidth or $newHeight, it added.
$imageUrl = [PATH OR URL TO YOUR IMAGE FILE];
$imageContent = file_get_contents($imageUrl);
$im = imagecreatefromstring($imageContent);
$width = imagesx($im);
$height = imagesy($im);
$newwidth = 300;
$newheight = 300;
$output = imagecreatetruecolor($newwidth, $newheight);
imagealphablending($output, false);
$transparency = imagecolorallocatealpha($output, 0, 0, 0, 127);
imagefill($output, 0, 0, $transparency);
imagesavealpha($output, true);
imagecopymerge($output, $im, ($width < 300 ? (300 - $width) / 2 : 0), ($height < 300 ? (300 - $height) / 2 : 0), 0, 0, $width, $height, 100);
//Show the image
header('Content-Type: image/png');
imagepng($output); //You can save it with another parameter what is a path
imagedestroy($output);
imagedestroy($im);
You need to change this line:
imagecopymerge($output, $im, ($width < 300 ? (300 - $width) / 2 : 0), ($height < 300 ? (300 - $height) / 2 : 0), 0, 0, $width, $height, 100);
to your size.
It's actually not exactly what you want, but it could be a good starting point.
You can trim the image when uploading it, by using imagecreatefrom(jpeg|png|gif) function.
$file = "images/" . $_FILES['image']['name'];
$tmp_file = $_FILES['image']['tmp_name'];
$type = $_FILES['images']['type'];
if (move_uploaded_file($tmp_file, $file)) {
chmod($file, 0777);
// check the type of image, you can do this for other types too, just change the imagecreatefrom function to the type you want to save the image as
if ($type === 'image/jpeg') {
$jpeg = imagecreatefromjpeg($file);
$jpeg_width = imagesx($jpeg);
$jpeg_height = imagesy($jpeg);
$new_width = imagesx($jpeg) / 4; // Fix the width of the thumb nail images, change the width of image here
$new_height = imagesy($jpeg) / 4; // change the height of image here
//new image
$new_image = imagecreatetruecolor($new_width, $new_height);
imagecopyresampled($new_image, $jpeg, 0, 0, 0, 0, $new_width, $new_height, $jpeg_width, $jpeg_height);
imagejpeg($new_image, $thumb);
chmod($thumb, 0777);
}
}
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
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!
My app is receiving base64-encoded image-files from the webbrowser. I need to save them on the client. So I did:
$data = base64_decode($base64img);
$fileName = uniqid() . '.jpg';
file_put_contents($uploadPath . $fileName, $data);
return $fileName;
Which works fine.
Now I need to compress & resize the image to max. 800 width & height, maintaining the aspect-ratio.
So I tried:
$data = base64_decode($base64img);
$fileName = uniqid() . '.jpg';
file_put_contents($uploadPath . $fileName, $data);
return $fileName;
which does not work (error: "imagejpeg() expects parameter 1 to be resource, string given").
And of course, this does compress, but not resize.
Would it be best to save the file in /tmp, read it and resize/move via GD?
Thanks.
2nd part
Thanks to #ontrack I know now that
$data = imagejpeg(imagecreatefromstring($data),$uploadPath . $fileName,80);
works.
But now I need to resize the image to max 800 width and height. I have this function:
function resizeAndCompressImagefunction($file, $w, $h, $crop=FALSE) {
list($width, $height) = getimagesize($file);
$r = $width / $height;
if ($crop) {
if ($width > $height) {
$width = ceil($width-($width*($r-$w/$h)));
} else {
$height = ceil($height-($height*($r-$w/$h)));
}
$newwidth = $w;
$newheight = $h;
} else {
if ($w/$h > $r) {
$newwidth = $h*$r;
$newheight = $h;
} else {
$newheight = $w/$r;
$newwidth = $w;
}
}
$src = imagecreatefromjpeg($file);
$dst = imagecreatetruecolor($newwidth, $newheight);
imagecopyresampled($dst, $src, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
return $dst;
}
So I thought I could do:
$data = imagejpeg(resizeAndCompressImagefunction(imagecreatefromstring($data),800,800),$uploadPath . $fileName,80);
which does not work.
You can use imagecreatefromstring
To answer the second part:
$data = imagejpeg(resizeAndCompressImagefunction(imagecreatefromstring($data),800,800),$uploadPath . $fileName,80);
$data will only contain either true or false to indicate wether the operation of imagejpeg was a success. The bytes are in $uploadPath . $fileName. If you want the actual bytes back in $data you have to use a temporary output buffer:
$img = imagecreatefromstring($data);
$img = resizeAndCompressImagefunction($img, 800, 800);
ob_start();
imagejpeg($img, null, 80);
$data = ob_get_clean();
I have a class to read and output the image content, if $width is set, it will resize the image, and then output it.
If I call the function like this $image->readImage('123.jpg'); , it can output the image file correctly, but when I call $image->readImage('123.jpg', 300); to resize it, it just display a black image with resized width & height.
And I tried to replace the code from
#imagejpeg($thumb, null, 100);
to
#imagejpeg($image, null, 100);
will works~
-
protected function readImage($fileName, $width = 0)
{
if ($width <= 0) {
return #file_get_contents($this->destination . '/' . $fileName);
} else {
$imageSize = #getimagesize($this->destination . '/' . $fileName);
$actualWidth = $imageSize[0];
$actualHeigth = $imageSize[1];
if ($actualWidth <= $width) {
return #file_get_contents($this->destination . '/' . $fileName);
}
$height = (100 / ($actualWidth / $width)) * .01;
$height = #round($actualHeigth * $height);
$image = #imagecreatefromjpeg($this->destination . '/' . $fileName);
$thumb = #imagecreatetruecolor($width, $height);
#imagecopyresampled($thumb, $image, 0, 0, 0, 0, $width, $height, $actualWidth, $actualHeight);
ob_start();
#imagejpeg($thumb, null, 100);
$bits = ob_get_contents();
ob_end_clean();
return $bits;
}
}
Any experts know what happened and help me to solve it ?
Thanks.
you've been inconsistant in your spelling of $actualHeight vs $actualHeigth
if you didn't have so many # everywhere, then php would have told you this.