PHP GD Image Cropping Function - php

I use this piece of code to make thumbnails of an uploaded image.
$file = randString().'.jpg';
$uniPath = 'i/u'.$login;
$completePath = $uniPath.'/a/'.$file;
$thumbPath = $uniPath.'/b/'.$file;
if(copy($_FILES['filename']['tmp_name'], $completePath)){
function convertPic($w_dst, $h_dst, $n_img){
$wxh = $w_dst.'x'.$h_dst;
switch($wxh){
case '150x150': $letter = 'b'; break;
case '50x50': $letter = 'c'; break;
default: $letter = 'z';
}
$dbPath = '/i/u1/'.$letter.'/'.$n_img;
$new_img = $_SERVER['DOCUMENT_ROOT'].$dbPath;
$file_src = "img.jpg"; // temporary safe image storage
$img_src = $file_src;
unlink($file_src);
move_uploaded_file($_FILES['filename']['tmp_name'], $file_src);
list($w_src, $h_src, $type) = getimagesize($file_src); // create new dimensions, keeping aspect ratio
$ratio = $w_src/$h_src;
$h_ratio = ($h_dst / $h_src);
$w_ratio = ($w_dst / $w_src);
if($w_src > $h_src){ //landscape
$w_crop = round($w_src * $h_ratio);
$h_crop = $h_dst;
$src_x = ceil(($w_src - $h_src)/2);
$src_y = 0;
}
elseif($w_src < $h_src){ // portrait
$h_crop = round($h_src * $w_ratio);
$w_crop = $w_dst;
$src_y = ceil(($h_src - $w_src)/2);
$src_x = 0;
}
else { //square
$w_crop = $w_dst;
$h_crop = $h_dst;
$src_x = 0;
$src_y = 0;
}
switch ($type)
{case 1: // gif -> jpg
$img_src = imagecreatefromgif($file_src);
break;
case 2: // jpeg -> jpg
$img_src = imagecreatefromjpeg($file_src);
break;
case 3: // png -> jpg
$img_src = imagecreatefrompng($file_src);
break;
}
$img_dst = imagecreatetruecolor($w_dst, $h_dst); // resample
imagecolorallocate($img_dst, 255, 255, 255) or die("fail imagecolorallocate");
imagecopyresampled($img_dst, $img_src, 0, 0, $src_x, $src_y, $w_crop, $h_crop, $w_src, $h_src) or die("imagecopyresampled($img_dst, $img_src, 0, 0, $src_x, $src_y, $w_crop, $h_crop, $w_src, $h_src)");
imagejpeg($img_dst, $new_img); // save new image
unlink($file_src); // clean up image storage
imagedestroy($img_src);
imagedestroy($img_dst);
return $db_path;
}
convertPic(150, 150, $file);
convertPic(250, 250, $file);
But for some reason the convertPic function does not work if called twice as in the example above. If it is called once everything works fine. I've put an alert if imagecopyresampled fails and it outputs
imagecopyresampled(Resource id #17,
img.jpg, 0, 0, 0, 0, 250, 250, , )
I think the problem is with the temporary image storing but not sure. Please help.

It would appear that you're processing an uploaded image. As part of the processing function, you move the uploaded file from its temporary directory, and then do some work on it.
When you call the function again the second time, the uploaded file is not longer in the temporary directory, and things blow up.
function convertPic(...) {
....
move_uploaded_file($_FILES['filename']['tmp_name'], $file_src);
....
unlink($file_src);
....
}
Basically the first call to convertPic processes and then deletes the "source", which means it's no longer available for the second call immediately afterwards.

I guess problem is with unlink($file_src)...
First, you call convertPic() function and it works OK because your img.jpg is still here, then you remove your image with unlink() and try to call again same routine that actually needs this file to work properly.
Also you can't move same file twice, so you have to move it outside the function, do your job as many times as needed, and after that, unlink image. Unlink should be after double-call of convertPic(), and move_uploaded_file() should be before function convertPic().
Well, that's what I think on first sight.

Related

Compress & resize images using PHP GD lib not working for png and weird results for jpg

I am trying to compress & resize my images using the php GD library. Nearly every answer on SO and everywhere else is the same, but for my solution, the PNG's are not being correctly transformed, and some jpg's are giving bizarre results.
This is the code I am using:
public function resizeImages() {
ini_set('max_execution_time', 0);
//Initial settings, Just specify Source and Destination Image folder.
$ImagesDirectory = FCPATH . 'design/img/test/'; //Source Image Directory End with Slash
$DestImagesDirectory = FCPATH . 'design/img/test/thumb/'; //Destination Image Directory End with Slash
$NewImageWidth = 150; //New Width of Image
$NewImageHeight = 150; // New Height of Image
$Quality = 90; //Image Quality
//Open Source Image directory, loop through each Image and resize it.
if($dir = opendir($ImagesDirectory)){
while(($file = readdir($dir))!== false){
$imagePath = $ImagesDirectory.$file;
$destPath = $DestImagesDirectory.$file;
$checkValidImage = #getimagesize($imagePath);
if(file_exists($imagePath) && $checkValidImage) //Continue only if 2 given parameters are true
{
//Image looks valid, resize.
if (resize_image($imagePath,$destPath,$NewImageWidth,$NewImageHeight,$Quality))
{
echo $file.' resize Success!<br />';
/*
Now Image is resized, may be save information in database?
*/
} else {
echo $file.' resize Failed!<br />';
}
}
}
closedir($dir);
}
}
and the resize_image function looks like this:
function resize_image($SrcImage,$DestImage, $MaxWidth,$MaxHeight,$Quality)
{
list($iWidth,$iHeight,$type) = getimagesize($SrcImage);
$ImageScale = min($MaxWidth/$iWidth, $MaxHeight/$iHeight);
$NewWidth = ceil($ImageScale*$iWidth);
$NewHeight = ceil($ImageScale*$iHeight);
$NewCanves = imagecreatetruecolor($NewWidth, $NewHeight);
$imagetype = strtolower(image_type_to_mime_type($type));
switch($imagetype)
{
case 'image/jpeg':
$NewImage = imagecreatefromjpeg($SrcImage);
break;
case 'image/png':
$NewImage = imagecreatefrompng($SrcImage);
break;
default:
return false;
}
//allow transparency for pngs
imagealphablending($NewCanves, false);
imagesavealpha($NewCanves, true);
// Resize Image
if(imagecopyresampled($NewCanves, $NewImage,0, 0, 0, 0, $NewWidth, $NewHeight, $iWidth, $iHeight))
{
switch ($imagetype) {
case 'image/jpeg':
if(imagejpeg($NewCanves,$DestImage,$Quality))
{
imagedestroy($NewCanves);
}
break;
case 'image/png':
if(imagepng($NewCanves,$DestImage,$Quality))
{
imagedestroy($NewCanves);
}
break;
default:
return false;
}
return true;
}
}
Every single png is not working, it just returns a file with 0 bytes and "file type is not supported", even though the type is recognized as .PNG in Windows...
Some JPG's return a weird result as well, see the following screenshot which indicates my issues regarding png's and some jpg's:
1) Do not use getimagesize to verify that the file is a valid image, to mention the manual:
Do not use getimagesize() to check that a given file is a valid image. Use a purpose-built solution such as the Fileinfo extension instead.
$checkValidImage = exif_imagetype($imagePath);
if(file_exists($imagePath) && ($checkValidImage == IMAGETYPE_JPEG || $checkValidImage == IMAGETYPE_PNG))
2) While imagejpeg() accepts quality from 0 to 100, imagepng() wants values between 0 and 9, you could do something like that:
if(imagepng($NewCanves,$DestImage,round(($Quality/100)*9)))
3) Using readdir () you should skip the current directory . and the parent..
while(($file = readdir($dir))!== false){
if ($file == "." || $file == "..")
continue;
edit
Point 2 is particularly important, imagepng () accepts values greater than 9 but then often fails with error in zlib or libpng generating corrupt png files.
I tried resizing some png and jpeg and I didn't encounter any problems with these changes.

Warning : imagecreatefromjpeg()expects parameter 1 to be resource

I have problem with my reszie image (code) when I run this code in localhost the code is work fine, but when I implement in website. the code give a warning.
<br /><b>Warning</b> : imagecreatefromjpeg([-1, [], 17, 1, 18, 1, 19, 23, true, [true, true],26,1,27,1,30,1,33]) expects parameter 1 to be resource, boolean given in <b>fungsi/f_upload_banner.php</b> on line <b>34</b><br />
This is my code for resize
<?php
$target_dir = "../uploads/images/banner/";
$image1 =$_FILES['txtfile']['name'];
$filename1 = stripslashes($_FILES['txtfile']['name']);
$ext1 = substr($image1, strrpos($image1, '.')+1);
$idimg1 = md5(uniqid() . time() . $filename1) . "-1." . $ext1;
$target_file1 = $target_dir . basename($idimg1);
//identify images file
$realImages = imagecreatefromjpeg($target_file1);
$width = imageSX($realImages);
$height = imageSY($realImages);
//save for thumbs size
$thumbWidth = 150;
$thumbHeight = ($thumbWidth / $width) * $height;
//change images size
$thumbImage = imagecreatetruecolor($thumbWidth, $thumbHeight);
imagecopyresampled($thumbImage, $realImages, 0,0,0,0, $thumbWidth, $thumbHeight, $width, $height);
//save thumbnail images
imagejpeg($thumbImage,$target_dir."thumb_".$idimg1);
//remove images object from memory
imagedestroy($realImages);
imagedestroy($thumbImage);
?>
Where is wrong?
You're trying to use the original file name (after mangling) as the source for imagecreatefromjpeg(), when you should be using the temporary name assigned by the upload process: $_FILES['txtfile']['tmp_name']
Do this:
$realImages = imagecreatefromjpeg($_FILES['txtfile']['tmp_name']);
You're also not moving the uploaded file to a permanent location. The temporary version will be deleted when your script terminates and the file will be lost.
Note also that your code is doing no error checking whatsoever, so if your upload fails you won't know about it. See the PHP section on Handling File Upload

php imagecopyresampled - image is empty (all black) after saving it

This script will load an image (jpg, gif or png) and then save a PNG local copy for caching.
I'm trying to find a way to resize the image to 300x300 before saving it as a PNG.
I tried to use the function imagecopyresampled() but the image is still not resized.
2 problems now :
The script saves a resized PNG image in the correct folder, but the image is empty (it's all black)
The first time i will load the image, i will get an error (image cannot be displayed because it contains error) but the image will still be saved as PNG in the cache folder. Second time i load the image, it will be displayed correctly (using the cached version) but it isn't resized.
Here's the full code of my page. The first part is used to cache the image, the second part is used to display the non-cached image (it reads an image from a ZIP file and output the content without extracting anything)
if (empty($_GET['display'])) {
header('Content-Type: image/png');
$imgpochette = $_GET['i'];
$ENABLE_CACHE = true;
$CACHE_TIME_HOURS = 744;
$CACHE_FILE_PATH = "pochette_album/$imgpochette.png";
if($ENABLE_CACHE && file_exists($CACHE_FILE_PATH) && (time() - filemtime($CACHE_FILE_PATH) < ($CACHE_TIME_HOURS * 60 * 60))) {
echo #file_get_contents($CACHE_FILE_PATH);
} else {
// Load the requested image
$imgdisplay = "http://www.pirate-punk.com/pochette.php?i=$imgpochette&display=1";
$image = imagecreatefromstring(file_get_contents($imgdisplay));
$width = "30";
$height = "30";
list($originalWidth, $originalHeight) = getimagesize($CACHE_FILE_PATH);
$new_image = imagecreatetruecolor($width, $height);
imagecopyresampled($new_image, $image, 0, 0, 0, 0, $width, $height, $originalWidth, $originalHeight);
// Send the image
imagepng($new_image, $CACHE_FILE_PATH);
exit();
#file_put_contents($CACHE_FILE_PATH, $output);
echo $output;
}
}
if (!empty($_GET['display'])) {
function showimage($zip_file, $file_name) {
$z = new ZipArchive();
if ($z->open($zip_file) !== true) {
echo "File not found.";
return false;
}
$stat = $z->statName($file_name);
$fp = $z->getStream($file_name);
// search for a path/to/file matching file, returning the index of it
$index = $z->locateName($file_name, ZipArchive::FL_NOCASE|ZipArchive::FL_NODIR);
// get the name of the file based on the index
$full_file_name = $z->getNameIndex($index);
// now get the stream
$fp = $z->getStream($full_file_name);
if(!$fp) {
echo "Could not load image.";
return false;
}
header('Content-Type: image/jpeg');
header('Content-Length: ' . $stat['size']);
fpassthru($fp);
return true;
}
$imgsrcencoded = $_GET['i'];
$imagesrc = base64_decode($imgsrcencoded);
$explodez = explode("#",$imagesrc);
$imgg = utf8_encode($explodez[1]);
$dirnfile = $explodez[0];
$zipp = end((explode('/', $dirnfile)));
$dirr = str_replace($zipp,"",$dirnfile);
$dirr = rtrim($dirr,"/");
$imgg = rtrim($imgg);
chdir($dirr);
if (empty($_GET['debug'])) {
echo showimage($zipp,$imgg);
}
}
Get the solution for .png images

Can not resize multiple images in PHP

I am trying to upload various images into a dynamically created folder on my server, then take each image and resize it while uploading it into the folder as well creating a new image and a new name.. example: image.jpg (original image) and image-resized.jpg (being the thumbnail image).
The thing I can not figure out is how to resize all images. I am not sure if I should put it in a loop. All I need is for each image I upload (could be 5 a time). It loops through and resizes them all and not just a single image. Here is my code any help would be appreciated!
Code to create folders and move picture into those folders:
// Desired folder structure
$structure = './Fotos/'.$newfolder;
// To create the nested structure, the $recursive parameter
// to mkdir() must be specified.
if (!mkdir($structure, 0, true)) {
die('Failed to create folders...');
}else{
$placefoldername = mysql_query("INSERT INTO datefolders (FolderDate) VALUES ('$newfolder')") or die(mysql_error());
echo "<div class=\"success\">El folder fue agregado con exito.<input type=\"button\" name=\"close\" value=\"X\" class=\"close\" /></div>";
}}
// ...
}
if(isset($_POST['upload'])){
$FolderDate = $_POST['fecha-folder'];
$FolderName = $_POST['FolderName'];
$hour = $_POST['hour'];
// Desired folder structure
$structure = './Fotos/'.$FolderDate.'/'.$hour.'/'.$FolderName;
// To create the nested structure, the $recursive parameter
// to mkdir() must be specified.
for($i=0;$i<count($_FILES['fileupload']['name']);$i++) {
$names = $_FILES['fileupload']['name'][$i];
$target_path = "Fotos/".$FolderDate."/".$hour."/".$FolderName."/";
$target_path = $target_path . basename( $_FILES['fileupload']['name'][$i]);
if(move_uploaded_file($_FILES['fileupload']['tmp_name'][$i], $target_path)) {
$success = 1;
Code to create a smaller (resized image) and also place into the already created folder:
$img = $names;
$imgPath = $structure;
function resizeImage($img, $imgPath, $suffix, $by, $quality)
{
//Create a thunbnail image by resizing the picture
// Open the original image.
$original = imagecreatefromjpeg("$imgPath/$img") or die("Error Opening original (<em>$imgPath/$img</em>)");
list($width, $height, $type, $attr) = getimagesize("$imgPath/$img");
// Determine new width and height.
$newWidth = ($width/$by);
$newHeight = ($height/$by);
// Resample the image.
$tempImg = imagecreatetruecolor($newWidth, $newHeight) or die("Cant create temp image");
imagecopyresized($tempImg, $original, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height) or die("Cant resize copy");
// Create the new file name.
$newNameE = explode(".", $img);
$newName = ''. $newNameE[0] .''. $suffix .'.'. $newNameE[1] .'';
// Save the image.
imagejpeg($tempImg, "$imgPath/$newName", $quality) or die("Cant save image");
// Clean up.
imagedestroy($original);
imagedestroy($tempImg);
return true;
}
$resize = resizeImage($img, $imgPath, "-resized", 23, 100);
Why are you defining the function resizeImage in the for loop? It is being redefined every time the loop iterates. This could be part of the problem. Define the function outside the loop and see if that works.
you can try;
when your first image proccess end use imagedestroy() then second image will proccessed.

Resize image before uploading PHP

I have no idea how to resize image in PHP, my code is:
for ($index = 1; $index <= 2; $index++) {
if (!empty($_FILES["pic$index"]["name"])) {
$ext = substr($_FILES["pic$index"]["name"], strrpos($_FILES["pic$index"]["name"], '.') + 1);
$dir = "../gallery/$mkdir";
HERE I NEED THE RESIZE OF THE TMP FILE OF IMAGE
move_uploaded_file($_FILES["pic$index"]["tmp_name"] , "$dir/img-$index.$ext");
}
}
$mkdir = the name of the gallery's folder (there are many galleries).
$dir = where the pics will be placed.
$ext = the type of the image (png, gif or jpg).
foreach loop runs two times because you can upload two pics.
This script is working good, I just need to do resize and I dont have an idea how to do it..
Here is the code I'm using to resize images.
In my case I give to the function the original file name and then the thumbnail file name.
You can adapt it for your case very easily.
public static function GenerateThumbnail($im_filename,$th_filename,$max_width,$max_height,$quality = 0.75)
{
// The original image must exist
if(is_file($im_filename))
{
// Let's create the directory if needed
$th_path = dirname($th_filename);
if(!is_dir($th_path))
mkdir($th_path, 0777, true);
// If the thumb does not aleady exists
if(!is_file($th_filename))
{
// Get Image size info
list($width_orig, $height_orig, $image_type) = #getimagesize($im_filename);
if(!$width_orig)
return 2;
switch($image_type)
{
case 1: $src_im = #imagecreatefromgif($im_filename); break;
case 2: $src_im = #imagecreatefromjpeg($im_filename); break;
case 3: $src_im = #imagecreatefrompng($im_filename); break;
}
if(!$src_im)
return 3;
$aspect_ratio = (float) $height_orig / $width_orig;
$thumb_height = $max_height;
$thumb_width = round($thumb_height / $aspect_ratio);
if($thumb_width > $max_width)
{
$thumb_width = $max_width;
$thumb_height = round($thumb_width * $aspect_ratio);
}
$width = $thumb_width;
$height = $thumb_height;
$dst_img = #imagecreatetruecolor($width, $height);
if(!$dst_img)
return 4;
$success = #imagecopyresampled($dst_img,$src_im,0,0,0,0,$width,$height,$width_orig,$height_orig);
if(!$success)
return 4;
switch ($image_type)
{
case 1: $success = #imagegif($dst_img,$th_filename); break;
case 2: $success = #imagejpeg($dst_img,$th_filename,intval($quality*100)); break;
case 3: $success = #imagepng($dst_img,$th_filename,intval($quality*9)); break;
}
if(!$success)
return 4;
}
return 0;
}
return 1;
}
The return codes are just here to differentiate between different types of errors.
By looking back at that code, I don't like the "magic number" trick. I'm gonna have to change that (by exceptions for example).
if (!empty($_FILES["pic$index"]["name"])) {
$ext = substr($_FILES["pic$index"]["name"], strrpos($_FILES["pic$index"]["name"], '.') + 1);
$dir = "../gallery/$mkdir";
// Move it
if(move_uploaded_file($_FILES["pic$index"]["tmp_name"] , "$dir/img-$index.$ext.tmp"))
{
// Resize it
GenerateThumbnail("$dir/img-$index.$ext.tmp","$dir/img-$index.$ext",600,800,0.80);
// Delete full size
unlink("$dir/img-$index.$ext.tmp");
}
}
Use move_uploaded_file to move it (recommanded) and then you can resize it and send it to it's final destination. You might not even need the ".tmp", you can use.
// Move it
if(move_uploaded_file($_FILES["pic$index"]["tmp_name"] , "$dir/img-$index.$ext"))
// Resize it
GenerateThumbnail("$dir/img-$index.$ext","$dir/img-$index.$ext",600,800);
Keep in mind that the picture you are dealing with is already uploaded on the server. You actualy want to resize picture before storing it in "safe place".
$_FILES["pic$index"]["tmp_name"] is probably /tmp/somepicturesname

Categories