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();
Related
I tried 2 implementations, shown below. Both are working well but when I tried to mix them it is not working anymore.
$output['status']=FALSE;
set_time_limit(0);
$allowedImageType = array("image/gif", "image/jpeg", "image/pjpeg", "image/png", "image/x-png" );
if ($_FILES['image_file_input']["error"] > 0) {
$output['error']= "File Error";
}
elseif (!in_array($_FILES['image_file_input']["type"], $allowedImageType)) {
$output['error']= "Invalid image format";
}
elseif (round($_FILES['image_file_input']["size"] / 1024) > 4096) {
$output['error']= "Maximum file upload size is exceeded";
} else {
$temp_path = $_FILES['image_file_input']['tmp_name'];
$file = pathinfo($_FILES['image_file_input']['name']);
$fileType = $file["extension"];
$photo_name = $productname.'-'.$member_id."_".time();
$fileName1 = $photo_name . '-125x125' . ".jpg";
$fileName2 = $photo_name . '-250x250' . ".jpg";
$fileName3 = $photo_name . '-500x500' . ".jpg";
$small_thumbnail_path = "uploads/large/";
createFolder($small_thumbnail_path);
$small_thumbnail = $small_thumbnail_path . $fileName1;
$medium_thumbnail_path = "uploads/large/";
createFolder($medium_thumbnail_path);
$medium_thumbnail = $medium_thumbnail_path . $fileName2;
$large_thumbnail_path = "uploads/large/";
createFolder($large_thumbnail_path);
$large_thumbnail = $large_thumbnail_path . $fileName3;
$thumb1 = createThumbnail($temp_path, $small_thumbnail,$fileType, 125, 125 );
$thumb2 = createThumbnail($temp_path, $medium_thumbnail, $fileType, 250, 250);
$thumb3 = createThumbnail($temp_path, $large_thumbnail,$fileType, 500, 500);
if($thumb1 && $thumb2 && $thumb3) {
$output['status']=TRUE;
$output['small']= $small_thumbnail;
$output['medium']= $medium_thumbnail;
$output['large']= $large_thumbnail;
}
}
echo json_encode($output);
Function File
function createFolder($path)
{
if (!file_exists($path)) {
mkdir($path, 0755, TRUE);
}
}
function createThumbnail($sourcePath, $targetPath, $file_type, $thumbWidth, $thumbHeight){
$source = imagecreatefromjpeg($sourcePath);
$width = imagesx($source);
$height = imagesy($source);
$tnumbImage = imagecreatetruecolor($thumbWidth, $thumbHeight);
imagecopyresampled($tnumbImage, $source, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $width, $height);
if (imagejpeg($tnumbImage, $targetPath, 90)) {
imagedestroy($tnumbImage);
imagedestroy($source);
return TRUE;
} else {
return FALSE;
}
}
Aspect ratio code, which is another one I tried to mix this code. But I was unsuccessful
$fn = $_FILES['image']['tmp_name'];
$size = getimagesize($fn);
$ratio = $size[0]/$size[1]; // width/height
$photo_name = $productname.'-'.$member_id."_".time();
{
if( $ratio > 1) {
$width1 = 500;
$height1 = 500/$ratio;
}
else {
$width1 = 500*$ratio;
$height1 = 500;
}
$src = imagecreatefromstring(file_get_contents($fn));
$dst = imagecreatetruecolor($width1,$height1);
$fileName3 = $photo_name . '-500x500' . ".jpg";
imagecopyresampled($dst,$src,0,0,0,0,$width1,$height1,$size[0],$size[1]);
imagedestroy($src);
imagepng($dst,$fileName3); // adjust format as needed
imagedestroy($dst);
if( $ratio > 1) {
$width2 = 250;
$height2 = 250/$ratio;
}
else {
$width2 = 250*$ratio;
$height2 = 250;
}
$src = imagecreatefromstring(file_get_contents($fn));
$dst = imagecreatetruecolor($width2,$height2);
$fileName2 = $photo_name . '-250x250' . ".jpg";
imagecopyresampled($dst,$src,0,0,0,0,$width2,$height2,$size[0],$size[1]);
imagedestroy($src);
imagepng($dst,$fileName2); // adjust format as needed
imagedestroy($dst);
}
What I need is to save my image after resizing but in second code there is no condition check, and I can't get image upload folder path. That's why I need to merge these 2 codes.
Basically I need need to save my image in 3 size formats: 500x500,250x250 and 125x125. Width is fixed, but height is set as per aspect ratio and set upload folder and condition in second code block.
Try this thumbnail function, which takes your source image resource and thumbnail size, and returns a new image resource for the thumbnail.
function createThumbnail($src, int $width = 100, int $height = null) {
// Ensure that src is a valid gd resource
if (!(is_resource($src) && 'gd' === get_resource_type($src))) {
throw new InvalidArgumentException(
sprintf("Argument 1 of %s expected type resource(gd), %s supplied", __FUNCTION__, gettype($src))
);
}
// Extract source image width, height and aspect ratio
$source_width = imagesx($src);
$source_height = imagesy($src);
$ratio = $source_width / $source_height;
// We know that width is always supplied, and that height can be null
// We must solve height according to aspect ratio if null is supplied
if (null === $height) {
$height = round($width / $ratio);
}
// Create the thumbnail resampled resource
$thumb = imagecreatetruecolor($width, $height);
imagecopyresampled($thumb, $src, 0, 0, 0, 0, $width, $height, $source_width, $source_height);
return $thumb;
}
Given your code above, you can now use the function like this
// Get uploaded file information as you have
// Create your source resource as you have
$source = imagecreatefromstring(file_get_contents($fn));
// Create thumbnails and save + destroy
$thumb = createThumbnail($source, 500);
imagejpeg($thumb, $thumb500TargetPath, 90);
imagedestroy($thumb);
$thumb = createThumbnail($source, 250);
imagejpeg($thumb, $thumb250TargetPath, 90);
imagedestroy($thumb);
$thumb = createThumbnail($source, 125);
imagejpeg($thumb, $thumb125TargetPath, 90);
imagedestroy($thumb);
// Don't forget to destroy the source resource
imagedestroy($source);
I have a method to resize image, that accepts image string and new dimensions and should return new image string. But it doesn't work
public function putBase64ThumbToFile($base64String){
$fs = new Filesystem();
$TEMP_FOLDER_NAME = "tmpimageupload";
$pos = strpos($base64String, ';');
$type = explode('/', substr($base64String, 0, $pos))[1];
$base64String = str_replace('data:image/'. $type .';base64,', '', $base64String);
$base64String = str_replace(' ', '+', $base64String);
$data = base64_decode($base64String);
$resizedImage = $this->resizeAndCompressImage($data, 100, 100);
$fs->mkdir($TEMP_FOLDER_NAME, 0700);
$tempFilePath = $TEMP_FOLDER_NAME.'/'.uniqid() . '.' . $type;
file_put_contents($tempFilePath, $resizedImage);
}
public function resizeAndCompressImage($data, $w, $h) {
list($width, $height) = getimagesizefromstring($data);
$r = $width / $height;
if ($w/$h > $r) {
$newwidth = $h*$r;
$newheight = $h;
} else {
$newheight = $w/$r;
$newwidth = $w;
}
$src = imagecreatefromstring($data);
$dst = imagecreatetruecolor($newwidth, $newheight);
imagecopyresampled($dst, $src, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
ob_start();
imagepng($src);
$image = ob_get_clean();
return $image;
}
In the result I get same unresized image.
You mistake is on this line:
imagepng($src);
you take the source image and not the destination image:
imagepng($dst);
So, i have been stuck on this for couple of hours. I have tired to google any solutions for this but didn't find solutions. So any help is greatly appreciated.
My Issue:
I am using form to upload multiple images. Due to data being backup on multiple servers i have to stored them on database. And storing the images on folder is not a solution. I thinks I can save the image onto the database but my I need to create a thumbnail of all the images which are being uploaded. So that's my problem, how do i create a thumbnail from those tmp files. I created to use imagecreate its not working, I am not able to fetch the content of that thumbnail and save it onto the database.
This is a code i used to resize that image which doesn't return the contents.
function resize_image($file, $w, $h, $crop=FALSE) {
list($width, $height) = getimagesize($file);
$r = $width / $height;
if ($crop) {
if ($width > $height) {
$width = abs(ceil($width-($width*abs($r-$w/$h))));
} else {
$height = abs(ceil($height-($height*abs($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;
}
This is my code which is used after form is posted: Right now it only displays all the files that are uploaded.
for($i=0;$i< count($_FILES['upload_file']['tmp_name']);$i++)
{
$size = getimagesize($_FILES['upload_file']['tmp_name'][$i]);
$name = $_FILES['upload_file']['name'][$i];
$type = $size['mime'];
$file_size_bits = $size['bits'];
$file_size_width = $size[0];
$file_size_height = $size[1];
$name = $_FILES['upload_file']['name'][$i];
$image_size = $size[3];
$uploadedfile = $_FILES['upload_file']['tmp_name'][$i];
$tmpName = base64_encode(file_get_contents($_FILES['upload_file']['tmp_name'][$i]));
$sImage_ = "data:" . $size["mime"] . ";base64," . $tmpName;
echo '<p>Preview from the data stored on to the database</p><img src="' . $sImage_ . '" alt="Your Image" />';
}
I need to create a thumbnail of those files that are being uploaded. How do i achieve that.
Please advise.
Thanks for your help.
Cheers
This is your big problem:
return $dst;
$dst is the image resource, not the image data.
You should use imagejpeg() or imagepng() to send the image data back instead.
Because those functions output the data stream to browser, we use some output buffer functions to capture the outputted image data instead of send it to the browser.
So,
return $dst;
replace with:
ob_start();
imagejpeg( $dst, NULL, 100); // or imagepng( $dst, NULL, 0 );
$final_image = ob_get_contents();
ob_end_clean();
return $final_image;
I'm experimenting with php script via ajax which uploads an array of images from this source.
While it works excellent I'm trying to enter php code which resizes images to 120px by width or height (whichever is larger).
For my sanity please help how to update code:
$demo_mode = false;
$upload_dir = 'uploads/';
$allowed_ext = array('jpg','jpeg','png','gif');
if(strtolower($_SERVER['REQUEST_METHOD']) != 'post'){
exit_status('Error! Wrong HTTP method!');
}
if(array_key_exists('pic',$_FILES) && $_FILES['pic']['error'] == 0 ){
$pic = $_FILES['pic'];
if(!in_array(get_extension($pic['name']),$allowed_ext)){
exit_status('Only '.implode(',',$allowed_ext).' files are allowed!');
}
if($demo_mode){
// File uploads are ignored. We only log them.
$line = implode(' ', array( date('r'), $_SERVER['REMOTE_ADDR'], $pic['size'], $pic['name']));
file_put_contents('log.txt', $line.PHP_EOL, FILE_APPEND);
exit_status('Uploads are ignored in demo mode.');
}
// Move the uploaded file from the temporary
// directory to the uploads folder:
if(move_uploaded_file($pic['tmp_name'], $upload_dir.$pic['name'])){
exit_status('File was uploaded successfuly!');
}
}
exit_status('Something went wrong with your upload!');
// Helper functions
function exit_status($str){
echo json_encode(array('status'=>$str));
exit;
}
function get_extension($file_name){
$ext = explode('.', $file_name);
$ext = array_pop($ext);
return strtolower($ext);
}
You can install imagemagick on your server:
<?php
function resize_image($file, $w, $h, $crop=FALSE) {
$img = new Imagick($file);
if ($crop) {
$img->cropThumbnailImage($w, $h);
} else {
$img->thumbnailImage($w, $h, TRUE);
}
return $img;
}
resize_image(‘/path/to/some/image.jpg’, 150, 150);
Another way would be using the PHP-GD:
<?php
function resize_image($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;
}
$img = resize_image(‘/path/to/some/image.jpg’, 150, 150);
<?php
// The file
$filename = 'test.jpg';
$percent = 0.5;
// Content type
header('Content-Type: image/jpeg');
// Get new dimensions
list($width, $height) = getimagesize($filename);
$new_width = $width * $percent;
$new_height = $height * $percent;
// Resample
$image_p = imagecreatetruecolor($new_width, $new_height);
$image = imagecreatefromjpeg($filename);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
// Output
imagejpeg($image_p, null, 100);
Find more at php.net
Well, I took an example of "promaty" from this LINK and call from loop:
<?php
$dir = "uploads/*.*";
$images = glob( $dir );
foreach( $images as $file ):
$px = 120;
$prefix = $px . "_";
$dst = "uploads/" . $prefix . basename($file);
$resized = image_resize($file, $dst, $px, $px);
echo "<img src='" . $dst . "' />";
echo "<p>" . basename($dst) . " </p>";
endforeach;
...and thanks for your time.
I've made this piece of code, it will re-size images on the fly, if it can't find the requested image, and then stores it.
The only problem with this is that the output jpg image has a low quality.
I was wondering if there is something I need to change to improve the image quality.
if (isset($_GET['size'])) {
$size = $_GET['size'];
}
if (isset($_GET['name'])) {
$filename = $_GET['name'];
}
$filePath = "files/catalog/" . urldecode($filename);
// Content type
header('Content-Type: image/jpeg');
// Get new sizes
list($width, $height) = getimagesize($filePath);
if ($_GET["name"] && !$size) {
$newwidth = $width * $percent;
$newheight = $height * $percent;
} else if ($_GET["name"] && $size) {
switch ($size) {
case "thumbs":
$newwidth = 192;
$newheight = 248;
break;
case "large":
$newwidth = 425;
$newheight = 550;
break;
}
}
$resizedFileName = $filename;
$resizedFileName = str_replace(".jpg", "", $resizedFileName) . ".jpg";
$resizedFilePath = "files/catalog/" . urldecode($resizedFileName);
if (!file_exists($resizedFilePath)) {
// Load
$thumb = imagecreatetruecolor($newwidth, $newheight);
$source = imagecreatefromjpeg($filePath);
// Resize
imagecopyresized($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
// Output
imagejpeg($thumb, $resizedFilePath);
//file_put_contents($, $binarydata);
$imageContent = file_get_contents($resizedFilePath);
echo $imageContent;
} else {
$imageContent = file_get_contents($resizedFilePath);
echo $imageContent;
}
Instead of imagecopyresized() you must use imagecopyresampled() and imagejpeg() function has third optional parameter and you can specify quality.
Probably because you are using imagejpeg() wrong, the second variable in the functions stands for the quality in percentage!
You want imagecopyresampled(). resize works by throwing away unecessary pixels. resampled() will average things out and produce much smoother results.