php- compressing a base64 decoded image fails - php

I get images as base64 encoded string front end and I have to decode them and save them as images in server. Image can be of any format- png,gif or jpeg.
This part works fine. But sometimes the images uploaded by the users can be of very large size, so I'm trying to compress them from backend and this part failed miserably.
I have two functions. One for converting base64 string to image and other one for compressing it.
This is the function that converts the string to an image.
function uploadTimelineImage($base64Img)
{
$data= array();
$upAt=date('YmdHis');
if (strpos($base64Img, 'data:image/png;base64') !== false)
{
$img = str_replace('data:image/png;base64,', '', $base64Img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
$extension= 'png';
}
if (strpos($base64Img, 'data:image/gif;base64') !== false)
{
$img = str_replace('data:image/gif;base64,', '', $base64Img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
$extension= 'gif';
}
if (strpos($base64Img, 'data:image/jpeg;base64') !== false)
{
$img = str_replace('data:image/jpeg;base64,', '', $base64Img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
$extension= 'jpeg';
}
$fileName = 'img'.$upAt.$extension;
$filePath = 'foldername/'.'img'.$upAt.$extension;
//upload image to folder
$success = file_put_contents($filePath, $data);
$result = $success ? 1 : 0;
//call to compression function
$compressThisImg= $filePath;
$d = compress($compressThisImg, $fileName, 80);
if($result==1)
{
return $fileName;
}
else
{
return null;
}
}
And this is the function that does compressing:
//Function to compress an image
function compress($source, $destination, $quality)
{
$info = getimagesize($source);
if ($info['mime'] == 'image/jpeg')
$image = imagecreatefromjpeg($source);
elseif ($info['mime'] == 'image/gif')
$image = imagecreatefromgif($source);
elseif ($info['mime'] == 'image/png')
$image = imagecreatefrompng($source);
imagejpeg($image, $destination, $quality);
return $destination;
}
But the above function does not do any compression, it throws error:
failed to open stream: No such file or directory
and my function uploads the original image.

Why you dont use this function for create any type of image form base64 edncoded image string?
function uploadTimelineImage($base64Img,$h,$w)
{
$im = imagecreatefromstring($base64Img);
if ($im !== false) {
$width = imagesx($im);
$height = imagesy($im);
$r = $width / $height; // ratio of image
// calculating new size for maintain ratio of image
if ($w/$h > $r) {
$newwidth = $h*$r;
$newheight = $h;
} else {
$newheight = $w/$r;
$newwidth = $w;
}
$dst = imagecreatetruecolor($newwidth, $newheight);
imagecopyresampled($dst, $im, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
imagedestroy($im);
$fileName = 'img'.date('Ymd').'.jpeg';
$filepath = 'folder/'.$fileName ;
imagejpeg($dst,$filepath);
imagedestroy($dst);
return $fileName;
}
else
{
return "";
}
}

Related

How to set aspect ratio in below code using PHP

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);

Image compression seems to create black image for PNG

I have a basic image upload/compression script on my website and most images seem to work fine. Having an issue with PNG for some reason, whenever I try to add a PNG image, the actual image is uploaded but the compressed image is saved as a full black square?
I can't seem to find what could be wrong with this script? The images were saving without a filetype, so I did edit the code to upload all as JPG to try to fix the error, it did fix what they were being saved as but the black images remain the same?
Can anybody point me in the right direction here?
if(isset($_POST['upload_images'])){
if(count($_FILES['upload']['name']) > 0){
//Loop through each file
for($i=0; $i<count($_FILES['upload']['name']); $i++) {
//Get the temp file path
$tmpFilePath = $_FILES['upload']['tmp_name'][$i];
//Make sure we have a filepath
if($tmpFilePath != ""){
//save the filename
$shortname = $_FILES['upload']['name'][$i];
//save the url and the file
$dirname = "galleries/".$portfolio_ref."/";
$filePath = $dirname.$_FILES['upload']['name'][$i];
$new_filename = date('dmYHis').rand(100000,9999999);
$new_filename2 = $dirname.$new_filename.'.jpg';
//Upload the file into the temp dir
if(move_uploaded_file($tmpFilePath, $new_filename2)) {
$file = $new_filename2;
$data = $filePath;
$cut_name = substr($data, strpos($data, "/") + 1);
$cut_name = explode('/',$cut_name);
$cut_name = end($cut_name);
$newfile = $dirname.'thb_'.$new_filename.'.jpg';
$info = getimagesize($file);
list($width, $height) = getimagesize($file);
$max_width = 300;
$max_height = 400;
//try max width first...
$ratio = $max_width / $width;
$new_width = $max_width;
$new_height = $height * $ratio;
//if that didn't work
if ($new_height > $max_height) {
$ratio = $max_height / $height;
$new_height = $max_height;
$new_width = $width * $ratio;
}
if ($info['mime'] == 'image/jpeg') $image = imagecreatefromjpeg($file);
elseif ($info['mime'] == 'image/gif') $image = imagecreatefromgif($file);
elseif ($info['mime'] == 'image/png') $image = imagecreatefrompng($file);
elseif ($info['mime'] == 'image/jpg') $image = imagecreatefromjpeg($file);
elseif ($info['mime'] == 'image/JPEG') $image = imagecreatefromjpeg($file);
elseif ($info['mime'] == 'image/PNG') $image = imagecreatefrompng($file);
elseif ($info['mime'] == 'image/GIF') $image = imagecreatefromgif($file);
elseif ($info['mime'] == 'image/JPG') $image = imagecreatefromjpeg($file);
$image = imagecreatetruecolor($new_width, $new_height);
$photo = imagecreatefromjpeg($file);
imagecopyresampled($image, $photo, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
imagejpeg($image, $newfile, 70);
$origional_image = $file;
$compressed_image = $newfile;
$digit_date = date("dmy");
$upload_date = date("Y-m-d");
$imgid = $digit_date.$i.rand();
mysqli_query($conn,"INSERT INTO umsikzw_images (image_id,portfolio_ref,thumb_link,full_link,image_name,date) VALUES ('$imgid','$portfolio_ref','$compressed_image','$origional_image','No Information','$upload_date')");
}
}
}
}
}

PHP script is not resizing image

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);

Why does he method imagecreatefromjpeg($src) return false in my method?

I am new to php and I am trying to make thumbnails
$src is the path to the image
$thumbWidth is the desired width
$imageName is not important it is needed to be passed to a function that generates the html code for the thumbnail.
the problem is on line 174 which I commented out if the image is a jpeg file the function returns false and then $source_image is false can anyone explain why?
here is my method:
function makeThumb( $src, $thumbWidth, $imageName )
{
$count = 0;
$len = strlen($src);
$indexlen = $len - 1;
$sourceArray = str_split($src);
for($i = $indexlen; $i > -1; $i--)
{
if($sourceArray[$i] == '.')
{
$count = $count + 1;
if($count == 1)
{
$hold = $i;
}
}
}
$ending = substr($src, $hold, $len);
if($ending === '.gif')
{
$type = '.gif';
$source_image = imagecreatefromgif($src);
}
if($ending === '.jpeg' || $ending === '.pjpeg' || $ending === '.jpg')
{
$type = '.jpg';
$source_image = imagecreatefromjpeg($src);
}
if($ending === '.png')
{
$type = '.png';
$source_image = imagecreatefrompng($src);
}
else
{
//throw new Exception('This file is not in JPG, GIF, or PNG format!');
$type = null;
}
/* read the source image */
if($ending = null)
{ return null; }
$width = imagesx($src);
$height = imagesy($src);
$newWidth = $thumbWidth;
/* find the "desired height" of this thumbnail, relative to the desired width */
$newHeight = floor($height * ($newWidth / $width));
/* create a new, "virtual" image */
$tempImg = imagecreatetruecolor($desired_width, $desired_height);
$pic = formatImage($tempImg, $imageName);
return $pic;
/* copy source image at a resized size */
//imagecopyresampled($virtual_image, $source_image, 0, 0, 0, 0, $desired_width, $desired_height, $width, $height);
/* create the physical thumbnail image to its destination */
//imagejpeg($virtual_image, $dest);
}
Are you sure that the image is a valid jpeg image?
You check the type of the image by extension. You can check get the extension in a much simpler way. You should also check if the file exists:
function makeThumb( $src, $thumbWidth, $imageName )
{
if(!file_exists($src))
throw new Exception('The file '.$src.' does not exist.');
$ext = pathinfo($src, PATHINFO_EXTENSION);
But checking the type of an image using extension is not reliable. There is another way to check that using the getimagesize function:
function makeThumb( $src, $thumbWidth, $imageName )
{
if(!file_exists($src))
throw new Exception('The file '.$src.' does not exist.');
$info = getimagesize($src);
if($info === false)
throw new Exception('This file is not a valid image');
$type = $info[2];
$width = $info[0]; // you don't need to use the imagesx and imagesy functions
$height = $info[1];
switch($type) {
case IMAGETYPE_JPEG:
$source_image = imagecreatefromjpeg($src);
break;
case IMAGETYPE_GIF:
$source_image = imagecreatefromgif($src);
break;
case IMAGETYPE_PNG:
$source_image = imagecreatefrompng($src);
break;
default:
throw new Exception('This file is not in JPG, GIF, or PNG format!');
}
$newWidth = $thumbWidth;
// ..and here goes the rest of your code
Please note - I did not check the rest of your code since your problem is related to the first part of the function.

How to resize image in this PHP script?

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.

Categories