How to save new image dimensions after scaling during upload? - php

QUESTION EDITED
Below is a simple script to allow users upload pictures. Once the upload is done, the pictures are displayed as a 170px(h) x 150px(w) thumbnail.
Most of the pictures look distorted once resized, so I guess I need to scale them too.
I'm stuck at saving the new image dimensions. See TODO.
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST")
{
$maxWidth = 150;
$maxHeight = 170;
$name = $_FILES ['image'] ['name'];
$type = $_FILES ["image"] ["type"];
$size = $_FILES ["image"] ["size"];
$tmp_name = $_FILES ['image'] ['tmp_name'];
list($originalWidth, $originalHeight) = getimagesize($tmp_name);
if ($originalWidth > $maxWidth || $originalHeight > $maxHeight)
{
if ($originalWidth / $maxWidth > $originalHeight / $maxHeight)
{
// width is the limiting factor
$width = $maxWidth;
$height = floor($width * $originalHeight / $originalWidth);
} else {
// height is the limiting factor
$height = $maxHeight;
$width = floor($height * $originalWidth / $originalHeight);
}
// Resample
$image_p = imagecreatetruecolor($maxwidth, $maxheight);
$image = imagecreatefromjpeg($filename);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $maxwidth, $maxheight,
$originalWidth, $originalHeight);
TODO: how do I save the new dimensions to $location ?
//start upload process
$RandomNumber = uniqid();
$location = "uploads/$RandomNumber";
move_uploaded_file($tmp_name, $location);
query("UPDATE users SET profilepic = '".$location."' WHERE id = '$id'");
}
?>
Some of my code is inspired from this question:
Distorted image resize with PHP

As for you question: "How can I get the initial dimensions of the picture the user wants to upload?"
From the manual:
list($width, $height, $type, $attr) = getimagesize("img/flag.jpg");
With that in mind, you may be able to replace the file path in the above example with $_FILES["image"] to get the dimensions data.
Once you have the original dimensions, you can adjust the image to be smaller while preserving the original aspect ratio.
For error checking, you would probably want to either check that there is only one file in $_FILES["image"], or loop through an array in the event you allow for multiple image uploads using the same name for each image's HTML input tag.

I have a custom class that helps me do this in projects. Feel free to use my code:
https://gist.github.com/695Multimedia/7117003

Related

Resizing Images PHP

I'm using a url link to resize images, such as:
image.php?name=butterfly&size=1100x1100
for example:
<img src="image.php?name=butterfly&size=1100x1100">
The code I'm using is:
<?php
if(isset($_GET['name'])){ //name
$image['name'] = $_GET['name'];
} else {
$image['name'] = null;
}
if(isset($_GET['size'])){ //dimensions
$image['size'] = $_GET['size'];
$size = explode('x', $image['size']);
$image['width'] = $size[0];
$image['height'] = $size[1];
} else {
$image['size'] = null;
}
if(isset($_GET['text'])){ //text
$image['text'] = $_GET['text'];
} else {
$image['text'] = null;
}
// File and new size
$filename = 'images/'.$image["name"].'.jpeg';
// Content type
header('Content-Type: image/jpeg');
// Output
imagecreatefromjpeg($filename);
// Set a maximum height and width
$width = $image['width'];
$height = $image['height'];
// Get new dimensions
list($width_orig, $height_orig) = getimagesize($filename);
$ratio_orig = $width_orig/$height_orig;
if ($width/$height > $ratio_orig) {
$width = $height*$ratio_orig;
} else {
$height = $width/$ratio_orig;
}
// Resample
$image_p = imagecreatetruecolor($width, $height);
$image = imagecreatefromjpeg($filename);
imagecopyresized($image_p, $image, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig);
// Output
imagejpeg($image_p, null, 100);
?>
My code works only for one part, which is the width, the image is resized to it's width but not height. Also when I resize my window, the picture get smaller every time. Thank you for your time and sorry for any bad explanation.
First of all, what is the question? I didn't get it.
One reason why the code changes only the width it may be because of this part of the code:
`if ($width/$height > $ratio_orig) {
$width = $height*$ratio_orig;
} else {
$height = $width/$ratio_orig;
}`
only one of the sizes will change. Also, another reasons why is changing only the width could be that you have as original image and quadratic resolution (e.g. 800x600 - ratio 1,34) and then you keep changing it to a wider one (e.g. 1280x720 - ratio 1,77).
Hope this helps!
As per your code logic, at any given time either your height or your width will change.
I tried it at my local host, width & height of my image was 600 X 400 and I passed 100X100 as parameter, it resized the image to 100X66, so the height did changed.

Create Perfect thumbnail

The following code is working without any error, but my problem is when i create a thumbnail some times thumbnail are non understandable one ( some conditions such as width is very larger than height ) i also tried a code for calculate height automatically.But it won't perfectly works. I want a code which creates a understandable thumbnail every time.(cropped thumbnail can be generated )
function make_thumb($src, $dest, $desired_width)
{
$source_image = imagecreatefromjpeg($src);
$width = imagesx($source_image);
$height = imagesy($source_image);
//even if height is calculated automatically using
$desired_height = floor($height * ($desired_width / $width));
$virtual_image = imagecreatetruecolor($desired_width, $desired_height);
imagecopyresampled($virtual_image, $source_image, 0, 0, 0, 0, $desired_width, $desired_height, $width, $height);
imagejpeg($virtual_image, $dest);
}
You can use the Class SimpleImage, like:
// Usage:
// Load the original image
$image = new SimpleImage('lemon.jpg');
// Resize the image to 600px width and the proportional height
$image->resizeToWidth(600);
$image->save('lemon_resized.jpg');
You can find this class here on github https://gist.github.com/miguelxt/908143
I've written a script to make thumb of landscape or portrait images. May be this will help you
<?php
$thumbWidth = 200; // can change it to whatever required
$thumbHeight = 200; // can change it to whatever required
$img = imagecreatefromstring(file_get_contents('SAM_1883.JPG'));
$imgWidth = imagesx($img);
$imgHeight = imagesy($img);
$imgStart_x = 0;
$imgStart_y = 0;
$imgEnd_x = $imgWidth;
$imgEnd_y = $imgHeight;
if($imgWidth > $imgHeight){
$diff = $imgWidth - $imgHeight;
$imgStart_x = $diff / 2;
$imgEnd_x = $imgWidth - $diff;
}else{
$diff = $imgHeight - $imgWidth;
$imgEnd_y = $imgHeight - $diff;
}
$dest = imagecreatetruecolor($thumbHeight,$thumbHeight);
imagecopyresized($dest, $img, 0, 0, $imgStart_x, $imgStart_y, $thumbWidth, $thumbHeight, $imgEnd_x, $imgEnd_y);
imagePNG($dest,'abc'.rand(0,9999).'.png');
?>
However you can change the source, thumbWidth, thumbHeight and destination of thumb as per your requirement.
https://github.com/lencioni/SLIR can resize your image on the fly. It will cache the image on the server as well as make it cacheable on the browser and proxy servers. The resizing happens when loading the image, not when loading HTML so your HTML is loading faster.

Generated thumbnails are all black when uploading

I'm generating thumbnail images from the original jpeg files when they are being uploaded. I could actually create and move those thumbnail files to another directory, but the problem is that those thumbnail files displays only the black color while uploading.
My code.
if(isset($_POST['upload'])){
$img = $_FILES['origin']['name'];
move_uploaded_file($_FILES['origin']['tmp_name'], 'image/'.$img);
define("SOURCE", 'image/');
define("DEST", 'thumb/');
define("MAXW", 120);
define("MAXH", 90);
$jpg = SOURCE.$img;
if($jpg){
list($width, $height, $type) = getimagesize($jpg); //$type will return the type of the image
if(MAXW >= $width && MAXH >= $height){
$ratio = 1;
}elseif($width > $height){
$ratio = MAXW / $width;
}else{
$ratio = MAXH / $height;
}
$thumb_width = round($width * $ratio); //get the smaller value from cal # floor()
$thumb_height = round($height * $ratio);
$thumb = imagecreatetruecolor($thumb_width, $thumb_height);
$path = DEST.$img."_thumb.jpg";
imagejpeg($thumb, $path);
echo "<img src='".$path."' alt='".$path."' />";
}
imagedestroy($thumb);
}
and the thumbnail file looks like this:
From php manual:
imagecreatetruecolor() returns an image identifier representing a black image of the specified size.
So the problem is that you actually create this black image and save it.
$thumb = imagecreatetruecolor($thumb_width, $thumb_height);
For solution on resizing, please refer to this question on stackoverflow.
Hmm, I just found my bug right now. The problem is that I use $jpg = SOURCE.$img; instead of $jpg = imagecreatefromjpeg($jpg); and also I need to copy the sample image to the new thumbnail image using
imagecopyresampled( $thumb, $jpg, 0, 0, 0, 0, $thumb_width, $thumb_height, $width, $height );
Then it works!!!
Thanks Alex for your answer which lead me to this solution.

Display a newly created thumbnail without saving first?

I am testing a thumbnail image creator script which creates a thumbnail that can be displayed in the web browser without saving it first.
Currently I have to use the following code to display the image:
include('image.inc.php');
header('Content-Type: image/png');
create_thumbnail('me.jpg', false, 200, 200);
But how can I display the dynamically generated thumbnail image on a standard webpage along side html mark-up?
create_thumbnail function:
function create_thumbnail($path, $save, $width, $height){
// Get the width[0] and height[1] of image in an array
$info = getimagesize($path);
// Create a new array that just contains the width and height
$size = array($info[0], $info[1]);
// Check what file type the image is
if($info['mime'] == 'image/png'){
$src = imagecreatefrompng($path);
}else if($info['mime'] == 'image/jpeg'){
$src = imagecreatefromjpeg($path);
}else if($info['mime'] == 'image/gif'){
$src = imagecreatefromgif($path);
}else{
// If it isn't a good file type don't do anything
return false;
}
// Create a thumbnail with the passed dimensions
$thumb = imagecreatetruecolor($width, $height);
$src_aspect = $size[0] / $size[1];
$thumb_aspect = $width / $height;
if($src_aspect < $thumb_aspect){
// Image is tall
$scale = $width / $size[0];
$new_size = array($width, $width / $src_aspect);
$src_pos = array(0, ($size[1] * $scale - $height) / $scale / 2);
}else if($src_aspect > $thumb_aspect){
// Image is wide
$scale = $height / $size[1];
$new_size = array($height * $src_aspect, $height);
$src_pos = array(($size[0] * $scale - $width) / $scale /2, 0);
}else{
// Image is square
$new_size = array($width, $height);
$src_pos = array(0, 0);
}
// Stop the new dimensions being less than 1 (this stops it breaking the code). Takes which ever value is higher.
$new_size[0] = max($new_size[0], 1);
$new_size[1] = max($new_size[1], 1);
// Copy the image into the new thumbnail
// Newly created thumbnail, image copying from, starting x-coord of thumbnail, starting y-coord of thumbnail(0,0 will fill up entire thumbnail), x-coord of original image, y-coord of original image, width of new thumbnail, height of new thumbnail, width of original image, height of original image
imagecopyresampled($thumb, $src, 0, 0, $src_pos[0], $src_pos[1], $new_size[0], $new_size[1], $size[0], $size[1]);
if($save === false){
return imagepng($thumb);
}else{
// Create the png image and save it to passed location
return imagepng($thumb, $save);
}
If I understand your question correctly, you just need to insert an img tag and set its src attribute to your php script.
Something like:
<img src="thumbnailgenerator.php?image_path=me.jpg">
Convert it to base64 (using base64_encode) and then display it with:
<img src="data:image/jpg;base64,iVBORw0KGgoAAAANS==" />

Cropping image in PHP

I'd like crop an image in PHP and save the file. I know your supposed to use the GD library but i'm not sure how. Any ideas?
Thanks
You could use imagecopy to crop a required part of an image. The command goes like this:
imagecopy (
resource $dst_im - the image object ,
resource $src_im - destination image ,
int $dst_x - x coordinate in the destination image (use 0) ,
int $dst_y - y coordinate in the destination image (use 0) ,
int $src_x - x coordinate in the source image you want to crop ,
int $src_y - y coordinate in the source image you want to crop ,
int $src_w - crop width ,
int $src_h - crop height
)
Code from PHP.net - a 80x40 px image is cropped from a source image
<?php
// Create image instances
$src = imagecreatefromgif('php.gif');
$dest = imagecreatetruecolor(80, 40);
// Copy
imagecopy($dest, $src, 0, 0, 20, 13, 80, 40);
// Output and free from memory
header('Content-Type: image/gif');
imagegif($dest);
imagedestroy($dest);
imagedestroy($src);
?>
This function will crop image maintaining image aspect ratio :)
function resize_image_crop($image, $width, $height)
{
$w = #imagesx($image); //current width
$h = #imagesy($image); //current height
if ((!$w) || (!$h)) { $GLOBALS['errors'][] = 'Image couldn\'t be resized because it wasn\'t a valid image.'; return false; }
if (($w == $width) && ($h == $height)) { return $image; } //no resizing needed
$ratio = $width / $w; //try max width first...
$new_w = $width;
$new_h = $h * $ratio;
if ($new_h < $height) { //if that created an image smaller than what we wanted, try the other way
$ratio = $height / $h;
$new_h = $height;
$new_w = $w * $ratio;
}
$image2 = imagecreatetruecolor ($new_w, $new_h);
imagecopyresampled($image2,$image, 0, 0, 0, 0, $new_w, $new_h, $w, $h);
if (($new_h != $height) || ($new_w != $width)) { //check to see if cropping needs to happen
$image3 = imagecreatetruecolor ($width, $height);
if ($new_h > $height) { //crop vertically
$extra = $new_h - $height;
$x = 0; //source x
$y = round($extra / 2); //source y
imagecopyresampled($image3,$image2, 0, 0, $x, $y, $width, $height, $width, $height);
} else {
$extra = $new_w - $width;
$x = round($extra / 2); //source x
$y = 0; //source y
imagecopyresampled($image3,$image2, 0, 0, $x, $y, $width, $height, $width, $height);
}
imagedestroy($image2);
return $image3;
} else {
return $image2;
}
}
To crop an image using GD you need to use a combination of GD methods, and if you look at "Example #1" on PHP's documentation of the imagecopyresampled method, it shows you how to crop and output an image, you would just need to add some code to that to capture and write the output to a file...
http://us2.php.net/manual/en/function.imagecopyresampled.php
There are also other options, including Image Magick which, if installed on your server, can be accessed directly using PHP's exec method (or similar) or you can install the PHP Imagick extension, which yields higher quality images and, in my opinion, is a little more intuitive and flexible to work with.
Finally, I've used the open source PHPThumb class library, which has a pretty simple interface and can work with multiple options depending on what's on your server, including ImageMagick and GD.
I use this script in some projects and it's pretty easy to use:
http://shiftingpixel.com/2008/03/03/smart-image-resizer/
The script requires PHP 5.1.0 (which is out since 2005-11-24 - time to upgrade if not yet at this version) and GD (which is rarely missing from good Web hosts).
Here is an example of it's use in your HTML:
<img src="/image.php/coffee-bean.jpg?width=200&height=200&image=/wp-content/uploads/2008/03/coffee-bean.jpg" alt="Coffee Bean" />
I just created this function and it works for my needs, creating a centered and cropped thumbnail image. It is streamlined and doesn't require multiple imagecopy calls like shown in webGautam's answer.
Provide the image path, the final width and height, and optionally the quality of the image. I made this for creating thumbnails, so all images are saved as JPGs, you can edit it to accommodate other image types if you require them. The main point here is the math and method of using imagecopyresampled to produce a thumbnail. Images are saved using the same name, plus the image size.
function resize_crop_image($image_path, $end_width, $end_height, $quality = '') {
if ($end_width < 1) $end_width = 100;
if ($end_height < 1) $end_height = 100;
if ($quality < 1 || $quality > 100) $quality = 60;
$image = false;
$dot = strrpos($image_path,'.');
$file = substr($image_path,0,$dot).'-'.$end_width.'x'.$end_height.'.jpg';
$ext = substr($image_path,$dot+1);
if ($ext == 'jpg' || $ext == 'jpeg') $image = #imagecreatefromjpeg($image_path);
elseif($ext == 'gif') $image = #imagecreatefromgif($image_path);
elseif($ext == 'png') $image = #imagecreatefrompng($image_path);
if ($image) {
$width = imagesx($image);
$height = imagesy($image);
$scale = max($end_width/$width, $end_height/$height);
$new_width = floor($scale*$width);
$new_height = floor($scale*$height);
$x = ($new_width != $end_width ? ($width - $end_width) / 2 : 0);
$y = ($new_height != $end_height ? ($height - $end_height) / 2 : 0);
$new_image = #imagecreatetruecolor($new_width, $new_height);
imagecopyresampled($new_image,$image,0,0,$x,$y,$new_width,$new_height,$width - $x,$height - $y);
imagedestroy($image);
imagejpeg($new_image,$file,$quality);
imagedestroy($new_image);
return $file;
}
return false;
}
You can use below method to crop image,
/*parameters are
$image =source image name
$width = target width
$height = height of image
$scale = scale of image*/
function resizeImage($image,$width,$height,$scale) {
//generate new image height and width of source image
$newImageWidth = ceil($width * $scale);
$newImageHeight = ceil($height * $scale);
//Create a new true color image
$newImage = imagecreatetruecolor($newImageWidth,$newImageHeight);
//Create a new image from file
$source = imagecreatefromjpeg($image);
//Copy and resize part of an image with resampling
imagecopyresampled($newImage,$source,0,0,0,0,$newImageWidth,$newImageHeight,$width,$height);
//Output image to file
imagejpeg($newImage,$image,90);
//set rights on image file
chmod($image, 0777);
//return crop image
return $image;
}

Categories