I'm trying to write a simple file uploader which can resize an image if needed and copy it into the server's file system. That works if I pass the file directly but I also want to be able to pass a URL via a GET parameter. And somehow imagecopyresampled seems to fail with the URL.
Here is my code:
if(isset($_FILES["file"]))
$fn = $_FILES['file']['tmp_name'];
else
$fn = urldecode($_GET['url']);
$fileMD5 = md5_file($fn);
$target = $basedir . $fileMD5 . ".png";
list($width, $height, $imgtype) = getimagesize($fn);
if ($imgtype == IMAGETYPE_PNG)
$img = imagecreatefrompng($fn);
else if ($imgtype == IMAGETYPE_JPEG)
$img = imagecreatefromjpeg($fn);
else if ($imgtype == IMAGETYPE_GIF)
$img = imagecreatefromgif($fn);
else if ($imgtype == IMAGETYPE_BMP)
$img = imagecreatefromwbmp($fn);
else {
echo "unsupported file format";
return;
}
// image resize
if($width > $maxwidth && $width >= $height) {
$newwidth = $maxwidth;
$newheight = ($height / $width) * $newwidth;
} else if($height > $maxheight) {
$newheight = $maxheight;
$newwidth = ($width / $height) * $newheight;
}
$tmp = imagecreatetruecolor($newwidth, $newheight);
imagecopyresampled($tmp, $img, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
imagepng($tmp, $target);
Everything seems to work fine until imagecopyresampled. I get the correct IMAGETYPE and also, something is created with imagecreatetruecolor. But imagecopyresampled returns false. I'm pretty confused since the script seems to be able to actually read the image and get it's first bits to determine the type of it.
Any suspections what's going wrong?
Thanks in advance.
Your resize section seems to leave out some situations that could lead to an undefined $newheight and $newwidth.
Are you sure about imagecreatetruecolor returning an image?
Related
I've got an issue which potentially could be a really easy fix, but I'm struggling to figure it out. So here's the issue:
When I upload a high definition photo in my upload script, the thumbnail returns blurry. For example:
The original photo below of our future supreme leader Elon musk looks like this:
https://i.stack.imgur.com/T91t4.jpg
The thumbnail returns something like this:
https://i.stack.imgur.com/9Vb6B.jpg
As you can see, the thumbnail is so blurry where I wouldn't wanna display it on a webpage. I'll leave a snippet of the PHP code to create the thumbnail:
mkdir($_SERVER["DOCUMENT_ROOT"]."/threads/$id/thumbnails/", 0755);
$filepath = "/threads/$id/".$fileName;
$filepath_thumb = "/threads/$id/thumbnails/".$fileName;
if($fileType == "image/jpeg")
{
$imagecreate = "imagecreatefromjpeg";
$imageformat = "imagejpeg";
}
if($fileType == "image/png")
{
$imagecreate = "imagecreatefrompng";
$imageformat = "imagepng";
}
if($fileType == "image/gif")
{
$imagecreate= "imagecreatefromgif";
$imageformat = "imagegif";
}
// Adjust size of thumbnail
$maxwidth = 250;
$maxheight = 250;
if ($fileheight > $filewidth)
{
$ratio = $maxheight / $fileheight;
$newheight = $maxheight;
$newwidth = $filewidth * $ratio;
}
else
{
$ratio = $maxwidth / $filewidth;
$newwidth = $maxwidth;
$newheight = $fileheight * $ratio;
}
$image = $imagecreate($_SERVER["DOCUMENT_ROOT"]."$filepath");
$image_p = imagecreatetruecolor($newwidth, $newheight);
imagecopyresized($image_p, $image, 0, 0, 0, 0, $newwidth, $newheight, $filewidth, $fileheight);
$imageformat($image_p, $_SERVER["DOCUMENT_ROOT"]."$filepath_thumb"); // Thumbnail Folder
If you don't pass quality parameters to imagejpeg or imagepng, they default to sub-optimal quality settings. So you need to know if you are you are processing a JPG or PNG, and handle accordingly.
$outputPath = $_SERVER["DOCUMENT_ROOT"]."$filepath_thumb";
if($fileType == "image/jpeg")
{
$imageformat($image_p, $outputPath, 100);
}
elseif($fileType == "image/png")
{
$imageformat($image_p, $outputPath, 9);
}
else
{
$imageformat($image_p, $outputPath);
}
You also may have better results with imagecopyresampled rather than imagecopyresized. I have always use imagecopyresampled for thumbnails, I seem to recall that it produces better results when reducing size.
The code below used to work flawlessly to crop an image that was already uploaded (via JQuery JCrop). As soon as I configured CloudFlare, it fails to crop the image (but still uploads successfully). Any ideas on how to fix this?
My current PHP Version is 7.0, and I am using DigitalOcean as my web host.
<?php
require_once('auth.php');
require_once('connection.php');
if ($_SERVER['REQUEST_METHOD'] == 'POST')
{
$targ_w = 150;
$targ_h = 200;
$src = mysqli_real_escape_string($bd,$_POST['src']);
$dst_r = ImageCreateTrueColor( $targ_w, $targ_h );
$img = resize_image($src, $_POST['imgWidth'], $_POST['imgHeight']);
imagecopyresampled($dst_r,$img,0,0,$_POST['x'],$_POST['y'],150,200,$_POST['w'],$_POST['h']);
imagejpeg($dst_r,$src,90);
//Cropping complete, move to next page
//header("location: profileSetup.php");
exit;
}
function isPNG($file){
return preg_match('/'.quotemeta('PNG').'/i', file_get_contents($file));
}
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*abs($r-$w/$h)));
} else {
$height = 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;
}
}
$dst = imagecreatetruecolor($newwidth, $newheight);
if(exif_imagetype($file) != IMAGETYPE_JPEG){
$src = imagecreatefrompng($file);
}
else{
$src = imagecreatefromjpeg($file);
}
imagecopyresampled($dst, $src, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
return $dst;
}
?>
I finally solved this issue for myself. There was nothing wrong with the PHP code. CloudFlare was caching the images, and all I had to do was add a random integer into the new image name to prevent this from occurring!
I'm creating thumnails of uploaded file.
if image width and height are greater than 200 than then i re size them to 200px.
Here is code i used to do that:
if (file_exists($old_file)) {
$path_parts = pathinfo($old_file);
$extension = $path_parts['extension'];
$filename_path = $filepath . $filename;
$destination_path = $filename_path;
if (strtolower($extension) == "jpg" || strtolower($extension) == "jpeg") {
$uploadedfile = $old_file;
$src = imagecreatefromjpeg($uploadedfile);
} else if (strtolower($extension) == "png") {
$uploadedfile = $old_file;
$src = imagecreatefrompng($uploadedfile);
} else {
$uploadedfile = $old_file;
$src = imagecreatefromgif($uploadedfile);
}
list($width, $height) = getimagesize($uploadedfile);
$newwidth = $Size['width'];
$newheight = $Size['height'];
if ($width <= $newwidth && $height <= $newheight) {
$newwidth = $width;
$newheight = $height;
$tmp = imagecreatetruecolor($width, $height);
} else {
if ($width > $height) {
$newheight = ($height / $width) * $newwidth;
$tmp = imagecreatetruecolor($newwidth, $newheight);
} else {
$newwidth = ($width / $height) * $newheight;
$tmp = imagecreatetruecolor($newwidth, $newheight);
}
}
if ((strtolower($extension) == "png") OR (strtolower($extension) == "gif")) {
imagealphablending($tmp, false);
imagesavealpha($tmp, true);
$transparent = imagecolorallocatealpha($tmp, 255, 255, 255, 127);
imagefilledrectangle($tmp, 0, 0, $newwidth, $newheight, $transparent);
}
imagecopyresampled($tmp, $src, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
if (strtolower($extension) == "jpg" || strtolower($extension) == "jpeg") {
imagejpeg($tmp, $destination_path, 100);
} elseif (strtolower($extension) == "png") {
imagepng($tmp, $destination_path, 5);
} else {
imagegif($tmp, $destination_path);
}
chmod($destination_path, 0777);
imagedestroy($src);
imagedestroy($tmp);
ob_flush();
flush();
ob_end_flush();
return true;
} else {
return false;
}
it re size the large images to 200px by 200px but image size is increased in (byte and kb etc increased).
I tried uploading 8kb png file, and new thumbnail file size was 28kb?
Tried googling but didn't find anything helpful
Thanks.
Your source image is compressed, after parsing it you get a true color image, which is uncompressed. Then you save it with a compression level of 5 (in the case of PNG), which is pretty low compression, thus a higher filesize.
Try a higher compression, like 9, for example. Also try adding a combination of filters to decrease filesize (http://us3.php.net/manual/en/image.constants.php look for PNG_FILTER_*).
See: http://us3.php.net/manual/en/function.imagepng.php
http://en.wikipedia.org/wiki/Portable_Network_Graphics#Compression
http://en.wikipedia.org/wiki/Portable_Network_Graphics#File_size_factors
The GD library doesn't appear to provide any interfaces to let you in on low-level PNG data, but you can theoretically find out the source compression level and filters, by using other bindings or trying to read it manually.
http://www.libpng.org/pub/png/spec/1.2/PNG-Compression.html
http://www.libpng.org/pub/png/spec/1.2/PNG-Filters.html
The same may happen with JPG and GIF.
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.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Can anybody suggest the best image resize script in php?
I'm still a newbie regarding image handling or file handling for that matter in PHP.
Would appreciate any input regarding the following
I post an image file using a simple html form and upload it via php.
When i try and alter my code to accomodate larger files (i.e. resize) I get an error.
Have been searching online but cant find anything really simple.
$size = getimagesize($_FILES['image']['tmp_name']);
//compare the size with the maxim size we defined and print error if bigger
if ($size == FALSE)
{
$errors=1;
}else if($size[0] > 300){ //if width greater than 300px
$aspectRatio = 300 / $size[0];
$newWidth = round($aspectRatio * $size[0]);
$newHeight = round($aspectRatio * $size[1]);
$imgHolder = imagecreatetruecolor($newWidth,$newHeight);
}
$newname= ROOTPATH.LOCALDIR."/images/".$image_name; //image_name is generated
$copy = imagecopyresized($imgHolder, $_FILES['image']['tmp_name'], 0, 0, 0, 0, $newWidth, $newHeight, $size[0], $size[1]);
move_uploaded_file($copy, $newname); //where I want to move the file to the location of $newname
The error I get is:
imagecopyresized(): supplied argument
is not a valid Image resource in
Thanks in advance
Thanks for all your input, i've changed it to this
$oldImage = imagecreatefromstring(file_get_contents($_FILES['image']['tmp_name']));
$copy = imagecopyresized($imgHolder, $oldImage, 0, 0, 0, 0, $newWidth, $newHeight, $size[0], $size[1]);
if(!move_uploaded_file($copy, $newname)){
$errors=1;
}
Not getting a PHP log error but its not saving :(
Any ideas?
Thanks again
Result
Following works.
$oldImage = imagecreatefromjpeg($img);
$imageHolder = imagecreatetruecolor($newWidth, $newHeight);
imagecopyresized($imageHolder, $oldImage, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
imagejpeg($imageHolder, $newname, 100);
Thanks for everyones help
imagecopyresized takes an image resource as its second parameter, not a file name. You'll need to load the file first. If you know the file type, you can use imagecreatefromFILETYPE to load it. For example, if it's a JPEG, use imagecreatefromjpeg and pass that the file name - this will return an image resource.
If you don't know the file type, all is not lost. You can read the file in as a string and use imagecreatefromstring (which detects file types automatically) to load it as follows:
$oldImage = imagecreatefromstring(file_get_contents($_FILES['image']['tmp_name']));
$_FILES['image']['tmp_name'] is path not image resource. You have to use one of imagecreatefrom*() functions to create resource.
Here is my implementation of saving a thumbnail picture:
Resize and save function:
function SaveThumbnail($imagePath, $saveAs, $max_x, $max_y)
{
ini_set("memory_limit","32M");
$im = imagecreatefromjpeg ($imagePath);
$x = imagesx($im);
$y = imagesy($im);
if (($max_x/$max_y) < ($x/$y))
{
$save = imagecreatetruecolor($x/($x/$max_x), $y/($x/$max_x));
}
else
{
$save = imagecreatetruecolor($x/($y/$max_y), $y/($y/$max_y));
}
imagecopyresized($save, $im, 0, 0, 0, 0, imagesx($save), imagesy($save), $x, $y);
imagejpeg($save, $saveAs);
imagedestroy($im);
imagedestroy($save);
}
Usage:
$thumb_dir = "/path/to/thumbnaildir/"
$thumb_name = "thumb.jpg"
$muf = move_uploaded_file($_FILES['imgfile']['tmp_name'], "/tmp/test.jpg")
if($muf)
{
SaveThumbnail("/tmp/test.jpg", $thumb_dir . $thumb_name, 128, 128);
}
I use ImageMagick for stuff like that. Look how much simpler it is!
An example from one of my scripts:
$target= //destination path
move_uploaded_file($_FILES['item']['tmp_name'],$target);
$image = new imagick($target);
$image->setImageColorspace(imagick::COLORSPACE_RGB);
$image->scaleImage(350,0);
$image->writeImage($target);
You could then use getImageGeometry() to obtain the width and height.
For example:
$size=$image->getImageGeometry();
if($size['width'] > 300){ //if width greater than
$image->scaleImage(300,0);
}
Also, using scaleImage(300,0) means that ImageMagick automatically calculates the height based on the aspect ratio.
I was working on sth similar. I tried Ghostscript and ImageMagic. They are good tools but takes a but of time to set up. I ended up using 'sips' on a Snow Leopard server. Not sure if it's built in to Linux server but it's the faster solution I have found if you need sth done quick.
function resizeImage($file){
define ('MAX_WIDTH', 1500);//max image width
define ('MAX_HEIGHT', 1500);//max image height
define ('MAX_FILE_SIZE', 10485760);
//iamge save path
$path = 'storeResize/';
//size of the resize image
$new_width = 128;
$new_height = 128;
//name of the new image
$nameOfFile = 'resize_'.$new_width.'x'.$new_height.'_'.basename($file['name']);
$image_type = $file['type'];
$image_size = $file['size'];
$image_error = $file['error'];
$image_file = $file['tmp_name'];
$image_name = $file['name'];
$image_info = getimagesize($image_file);
//check image type
if ($image_info['mime'] == 'image/jpeg' or $image_info['mime'] == 'image/jpg'){
}
else if ($image_info['mime'] == 'image/png'){
}
else if ($image_info['mime'] == 'image/gif'){
}
else{
//set error invalid file type
}
if ($image_error){
//set error image upload error
}
if ( $image_size > MAX_FILE_SIZE ){
//set error image size invalid
}
switch ($image_info['mime']) {
case 'image/jpg': //This isn't a valid mime type so we should probably remove it
case 'image/jpeg':
$image = imagecreatefromjpeg ($image_file);
break;
case 'image/png':
$image = imagecreatefrompng ($image_file);
break;
case 'image/gif':
$image = imagecreatefromgif ($image_file);
break;
}
if ($new_width == 0 && $new_height == 0) {
$new_width = 100;
$new_height = 100;
}
// ensure size limits can not be abused
$new_width = min ($new_width, MAX_WIDTH);
$new_height = min ($new_height, MAX_HEIGHT);
//get original image h/w
$width = imagesx ($image);
$height = imagesy ($image);
//$align = 'b';
$zoom_crop = 1;
$origin_x = 0;
$origin_y = 0;
//TODO setting Memory
// generate new w/h if not provided
if ($new_width && !$new_height) {
$new_height = floor ($height * ($new_width / $width));
} else if ($new_height && !$new_width) {
$new_width = floor ($width * ($new_height / $height));
}
// scale down and add borders
if ($zoom_crop == 3) {
$final_height = $height * ($new_width / $width);
if ($final_height > $new_height) {
$new_width = $width * ($new_height / $height);
} else {
$new_height = $final_height;
}
}
// create a new true color image
$canvas = imagecreatetruecolor ($new_width, $new_height);
imagealphablending ($canvas, false);
if (strlen ($canvas_color) < 6) {
$canvas_color = 'ffffff';
}
$canvas_color_R = hexdec (substr ($canvas_color, 0, 2));
$canvas_color_G = hexdec (substr ($canvas_color, 2, 2));
$canvas_color_B = hexdec (substr ($canvas_color, 2, 2));
// Create a new transparent color for image
$color = imagecolorallocatealpha ($canvas, $canvas_color_R, $canvas_color_G, $canvas_color_B, 127);
// Completely fill the background of the new image with allocated color.
imagefill ($canvas, 0, 0, $color);
// scale down and add borders
if ($zoom_crop == 2) {
$final_height = $height * ($new_width / $width);
if ($final_height > $new_height) {
$origin_x = $new_width / 2;
$new_width = $width * ($new_height / $height);
$origin_x = round ($origin_x - ($new_width / 2));
} else {
$origin_y = $new_height / 2;
$new_height = $final_height;
$origin_y = round ($origin_y - ($new_height / 2));
}
}
// Restore transparency blending
imagesavealpha ($canvas, true);
if ($zoom_crop > 0) {
$src_x = $src_y = 0;
$src_w = $width;
$src_h = $height;
$cmp_x = $width / $new_width;
$cmp_y = $height / $new_height;
// calculate x or y coordinate and width or height of source
if ($cmp_x > $cmp_y) {
$src_w = round ($width / $cmp_x * $cmp_y);
$src_x = round (($width - ($width / $cmp_x * $cmp_y)) / 2);
} else if ($cmp_y > $cmp_x) {
$src_h = round ($height / $cmp_y * $cmp_x);
$src_y = round (($height - ($height / $cmp_y * $cmp_x)) / 2);
}
// positional cropping!
if ($align) {
if (strpos ($align, 't') !== false) {
$src_y = 0;
}
if (strpos ($align, 'b') !== false) {
$src_y = $height - $src_h;
}
if (strpos ($align, 'l') !== false) {
$src_x = 0;
}
if (strpos ($align, 'r') !== false) {
$src_x = $width - $src_w;
}
}
// positional cropping!
imagecopyresampled ($canvas, $image, $origin_x, $origin_y, $src_x, $src_y, $new_width, $new_height, $src_w, $src_h);
} else {
imagecopyresampled ($canvas, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
}
//Straight from Wordpress core code. Reduces filesize by up to 70% for PNG's
if ( (IMAGETYPE_PNG == $image_info[2] || IMAGETYPE_GIF == $image_info[2]) && function_exists('imageistruecolor') && !imageistruecolor( $image ) && imagecolortransparent( $image ) > 0 ){
imagetruecolortopalette( $canvas, false, imagecolorstotal( $image ) );
}
$quality = 100;
$nameOfFile = 'resize_'.$new_width.'x'.$new_height.'_'.basename($file['name']);
if (preg_match('/^image\/(?:jpg|jpeg)$/i', $image_info['mime'])){
imagejpeg($canvas, $path.$nameOfFile, $quality);
} else if (preg_match('/^image\/png$/i', $image_info['mime'])){
imagepng($canvas, $path.$nameOfFile, floor($quality * 0.09));
} else if (preg_match('/^image\/gif$/i', $image_info['mime'])){
imagegif($canvas, $path.$nameOfFile);
}
}