I have a quick question that I'm not quite sure to set up. I've seen examples elsewhere but nothing specifically like my situation. I would like to resize images using PHP so they're readable and not just wonkily stretched like if you use HTML. If they're not 250 pixels wide, or 160 pixels tall, how can I resize the picture so it's proportionate but fits within that space?
Thanks!
PHP does not manipulate images directly. You will need to use an image manipulation library such as gd or ImageMagick to accomplish this goal.
In ImageMagick, image resizing is accomplished like this:
$thumb = new Imagick('myimage.gif');
$thumb->resizeImage(320,240,Imagick::FILTER_LANCZOS,1);
$thumb->writeImage('mythumb.gif');
With GD, you can do it like this:
<?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);
?>
Ok, so below is an Image object that I use in my store. It maintains scale - requires GD
<?php
class Store_Model_Image extends My_Model_Abstract
{
const PATH = STORE_MODEL_IMAGE_PATH;
const URL = "/store-assets/product-images/";
public function get_image_url($width, $height)
{
$old_file = self::PATH . $this->get_filename();
$basename = pathinfo($old_file, PATHINFO_FILENAME);
$new_name = sprintf("%s_%sx%s.jpg", $basename, $width, $height);
if(file_exists(self::PATH . $new_name))
{
return self::URL . $new_name;
}
else
{
list($width_orig, $height_orig, $image_type) = #getimagesize($old_file);
$img = FALSE;
// Get the image and create a thumbnail
switch($image_type)
{
case 1:
$img = #imagecreatefromgif($old_file);
break;
case 2:
$img = #imagecreatefromjpeg($old_file);
break;
case 3:
$img = #imagecreatefrompng($old_file);
break;
}
if(!$img)
{
throw new Zend_Exception("ERROR: Could not create image handle from path.");
}
// Build the thumbnail
if($width_orig > $height_orig)
{
$width_ratio = $width / $width_orig;
$new_width = $width;
$new_height = $height_orig * $width_ratio;
}
else
{
$height_ratio = $height / $height_orig;
$new_width = $width_orig * $height_ratio;
$new_height = $height;
}
$new_img = #imagecreatetruecolor($new_width, $new_height);
// Fill the image black
if(!#imagefilledrectangle($new_img, 0, 0, $new_width, $new_height, 0))
{
throw new Zend_Exception("ERROR: Could not fill new image");
}
if(!#imagecopyresampled($new_img, $img, 0, 0, 0, 0, $new_width, $new_height, $width_orig, $height_orig))
{
throw new Zend_Exception("ERROR: Could not resize old image onto new bg.");
}
// Use a output buffering to load the image into a variable
ob_start();
imagejpeg($new_img, NULL, 100);
$image_contents = ob_get_contents();
ob_end_clean();
// lastly (for the example) we are writing the string to a file
$fh = fopen(self::PATH . $new_name, "a+");
fwrite($fh, $image_contents);
fclose($fh);
return self::URL . $new_name;
}
}
}
I resize the image at request time, so the first time the page loads an image will be resized to the required size for the template. (this means I don't have to crash a shared host trying to regenerate image thumbnails everytime my design changes)
So in the template you pass your image object, and when you need a image thumb,
<img src="<?php echo $image->get_image_url(100, 100); ?>" />
you now have a 100x100 thumb, which is saved to the Server for reuse at a later date
gd and imagemagick are two tools that may work for you
http://php.net/manual/en/book.image.php
http://php.net/manual/en/book.imagick.php
Here is something I used to use
class cropImage{
var $imgSrc,$myImage,$cropHeight,$cropWidth,$x,$y,$thumb;
function setImage($image,$moduleWidth,$moduleHeight,$cropPercent = "1") {
//Your Image
$this->imgSrc = $image;
//getting the image dimensions
list($width, $height) = getimagesize($this->imgSrc);
//create image from the jpeg
$this->myImage = imagecreatefromjpeg($this->imgSrc) or die("Error: Cannot find image!");
if($width > $height) $biggestSide = $width; //find biggest length
else $biggestSide = $height;
//The crop size will be half that of the largest side
//$cropPercent = 1.55; // This will zoom in to 50% zoom (crop)
if(!$cropPercent) {
$cropPercent = 1.50;
}
$this->cropWidth = $moduleWidth*$cropPercent;
$this->cropHeight = $moduleHeight*$cropPercent;
//$this->cropWidth = $biggestSide*$cropPercent;
//$this->cropHeight = $biggestSide*$cropPercent;
//getting the top left coordinate
$this->x = ($width-$this->cropWidth)/2;
$this->y = ($height-$this->cropHeight)/2;
}
function createThumb($moduleWidth,$moduleHeight){
$thumbSize = 495; // will create a 250 x 250 thumb
$this->thumb = imagecreatetruecolor($moduleWidth, $moduleHeight);
//$this->thumb = imagecreatetruecolor($thumbSize, $thumbSize);
imagecopyresampled($this->thumb, $this->myImage, 0, 0,$this->x, $this->y, $moduleWidth, $moduleHeight, $this->cropWidth, $this->cropHeight);
//imagecopyresampled($this->thumb, $this->myImage, 0, 0,$this->x, $this->y, $thumbSize, $thumbSize, $this->cropWidth, $this->cropHeight);
}
function renderImage(){
header('Content-type: image/jpeg');
imagejpeg($this->thumb);
imagedestroy($this->thumb);
}
}
Call it by using
$image = new cropImage;
$image->setImage($imagepath,$moduleWidth,$moduleHeight,$scaleRelation);
$image->createThumb($moduleWidth,$moduleHeight);
$image->renderImage();
Use GD or ImageMagick. Here you may find a real production example of code (used by MediaWiki) that supports consoled ImageMagick interface (transformImageMagick method), ImageMagick extension interface (transformImageMagickExt method) and GD (transformGd method).
There a simple to use, open source library called PHP Image Magician that will can help you out.
Example of basis usage:
$magicianObj = new imageLib('racecar.jpg');
$magicianObj -> resizeImage(100, 200, 'crop');
$magicianObj -> saveImage('racecar_small.png');
Related
I'm using the following PHP function to resize big images to fit 500 px width:
<?php
function resizeImage($name) {
header('Content-type: image/jpeg');
$filename = "file.jpg";
$new_width = 500;
list($width, $height) = getimagesize($filename);
$new_height = (($height*$new_width)/$width);
$image_p = imagecreatetruecolor($new_width, $new_height);
$image = imagecreatefromjpeg($filename);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
imagejpeg($image_p, "file.jpg", 100);
}
?>
For some reason the colors on the resized image aren't exactly the same as before. They aren't as clear and strong as before. As you can see [picture removed] there's more red color and brilliance in the left (original) photo.
Why that? Is there something wrong with my script? Or is it a normal resizing effect?
This is the working code I have now:
<?php
// Call the function with: resizeImage("INSERT_YOUR_FILE_NAME_INCLUDING_SUFFIX_HERE");
function resizeImage($file_name) {
// File is located at: files/original/
$filename = "files/original/".$file_name;
// The width you want the converted image has
$new_width = 500;
// Calculate right height
list($width, $height) = getimagesize($filename);
$new_height = (($height*$new_width)/$width);
// Get image
$small = new Imagick($filename);
// Resize image, but only if original image is wider what the wanted 500 px
if($width > $new_width) {$small->resizeImage($new_width, $new_height, Imagick::FILTER_LANCZOS, 1);}
// Some code to correct the color profile
$version = $small->getVersion();
$profile = "sRGB_IEC61966-2-1_no_black_scaling.icc";
if((is_array($version) === true) && (array_key_exists("versionString", $version) === true)) {$version = preg_replace("~ImageMagick ([^-]*).*~", "$1", $version["versionString"]);if(is_file(sprintf("/usr/share/ImageMagick-%s/config/sRGB.icm", $version)) === true) {$profile = sprintf("/usr/share/ImageMagick-%s/config/sRGB.icm", $version);}}if(($srgb = file_get_contents($profile)) !== false){$small->profileImage("icc", $srgb);$small->setImageColorSpace(Imagick::COLORSPACE_SRGB);}
// Safe the image to: files/small/
$small->writeImage("files/small/".$file_name);
// Clear all resources associated to the Imagick object
$small->clear();
}
?>
Don't forget to either download the icc file from http://www.color.org/sRGB_IEC61966-2-1_no_black_scaling.icc and save it in the same directory as your resize file or change $profile = "sRGB_IEC61966-2-1_no_black_scaling.icc"; to $profile = "http://www.color.org/sRGB_IEC61966-2-1_no_black_scaling.icc";!
This script below works fine to handle an uploaded image and resize it so that the max height or width (whichever side is longer) is 200px. So it could be 200x200 if it's perfect square image, or 200x140, or 140x200, etc.
if(isset($_FILES['image'])) {
$img = $_FILES['image']['name'];
$tmp = $_FILES['image']['tmp_name'];
// get uploaded file's extension
$ext = strtolower(pathinfo($img, PATHINFO_EXTENSION));
//checking if image exists for this pool and removing if so, before adding new image in its place
if(file_exists("uploads/".$poolid.".png")) {
unlink("uploads/".$poolid.".png");
}
// checks valid format
if(in_array($ext, $valid_extensions)) {
//re-size the image and make it a PNG before sending to server
$final_image = $poolid . ".png";
$path = "uploads/".strtolower($final_image);
$size = getimagesize($tmp);
$ratio = $size[0]/$size[1]; // width/height
if( $ratio > 1) {
$width = 200;
$height = 200/$ratio;
}
else {
$width = 200*$ratio;
$height = 200;
}
$src = imagecreatefromstring(file_get_contents($tmp));
$dst = imagecreatetruecolor($width,$height);
imagecopyresampled($dst,$src,0,0,0,0,$width,$height,$size[0],$size[1]);
imagedestroy($src);
imagepng($dst, $path); // adjust format as needed
imagedestroy($dst);
$_SESSION['image_uploaded']="yes";
echo $path ."?".rand(1,32000);
} else {
echo 'invalid file';
}
}
Now, Facebook sharing using OpenGraph requires an image to be at least 200x200. So a 140x200 image wouldn't work with their sharing functionality.
I don't love non-square images anyway, so I would like to take the image and if it's not already a square, I'd like to add whitespace to the sides (or on the top/bottom) and save it as a perfect 200x200 square every single time.
I tried this below, but it's not working (no image gets created at all). What is wrong with what I tried to do? This doesn't seem overly complicated but clearly I'm missing something.
if(isset($_FILES['image'])) {
$img = $_FILES['image']['name'];
$tmp = $_FILES['image']['tmp_name'];
// get uploaded file's extension
$ext = strtolower(pathinfo($img, PATHINFO_EXTENSION));
//checking if image exists for this pool and removing if so, before adding new image in its place
if(file_exists("uploads/".$poolid.".png")) {
unlink("uploads/".$poolid.".png");
}
// checks valid format
if(in_array($ext, $valid_extensions)) {
//re-size the image and make it a PNG before sending to server
$final_image = $poolid . ".png";
$path = "uploads/".strtolower($final_image);
$size = getimagesize($tmp);
$ratio = $size[0]/$size[1]; // width/height
if( $ratio > 1) {
$width = 200;
$height = 200/$ratio;
}
else {
$width = 200*$ratio;
$height = 200;
}
$src = imagecreatefromstring(file_get_contents($tmp));
$dst = imagecreatetruecolor($width,$height);
$orig_img=imagecopyresampled($dst,$src,0,0,0,0,$width,$height,$size[0],$size[1]);
imagedestroy($src);
// create new image and fill with background colour
$new_img = imagecreatetruecolor($output_w, $output_h);
$bgcolor = imagecolorallocate($new_img, 255, 0, 0); // red
imagefill($new_img, 0, 0, $bgcolor); // fill background colour
// copy and resize original image into center of new image
$final_img=imagecopyresampled($new_img, $orig_img, 0, 0, 0, 0, 200, 200, $width, $height);
imagepng($final_img, $path); // adjust format as needed
imagedestroy($dst);
$_SESSION['image_uploaded']="yes";
echo $path ."?".rand(1,32000);
} else {
echo 'invalid file';
}
}
You don't need a temporary intermediate image. You can paste the resampled source image right into the destination image after you fill it with background. See here:
$src = imagecreatefromstring(file_get_contents($tmp));
// Create new image and fill it with background color
$dst = imagecreatetruecolor($output_w,$output_h);
$bgcolor = imagecolorallocate($dst, 255, 0, 0);
imagefill($dst, 0, 0, $bgcolor);
// Copy resampled src image into dst
if ($ratio > 1)
imagecopyresampled($dst, $src, 0, ($output_h - $height) / 2, 0, 0, $width, $height, $size[0], $size[1]);
else
imagecopyresampled($dst, $src, ($output_w - $width) / 2, 0, 0, 0, $width, $height, $size[0], $size[1]);
imagepng($dst, $path); // adjust format as needed
imagedestroy($src);
imagedestroy($dst);
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.
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;
}
Hey, i am looking for a method to creat temporay thumb file in PHP. Is there any way not to store the image on the server or delete them right after. What I am looking for is a solution like this: http://www.dig2go.com/index.php?shopbilde=772&type=1&size=120
Could some one explain to me how the php code behind this works? For the moment are am using a php code I found on the net for creation of thumb nails:
function createThumb($pathToImage, $pathToThumb, $thumbWidth, $thumbHeight, $saveNameAndPath)
{
if(!file_exists($pathToImage))
return false;
else
{
//Load image and size
$img = imagecreatefromjpeg($pathToImage);
$width = imagesx($img);
$height = imagesy($img);
//Calculate the size of thumb
$new_width = $thumbWidth;
$new_height = $thumbHeight; //floor($height * ($thumbWidth / $width));
//Make the new thumb
$tmp_img = imagecreatetruecolor($new_width, $new_height);
//Copy the old image and calculate the size
imagecopyresized($tmp_img, $img, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
//Save the thumb to jpg
imagejpeg($tmp_img, $saveNameAndPath);
return true;
}
}
function createThumb($pathToImage, $pathToThumb, $thumbWidth, $thumbHeight, $saveNameAndPath)
{
if(!file_exists($pathToImage))
return false;
else
{
//Load image and size
$img = imagecreatefromjpeg($pathToImage);
$width = imagesx($img);
$height = imagesy($img);
//Calculate the size of thumb
$new_width = $thumbWidth;
$new_height = $thumbHeight; //floor($height * ($thumbWidth / $width));
//Make the new thumb
$tmp_img = imagecreatetruecolor($new_width, $new_height);
//Copy the old image and calculate the size
imagecopyresized($tmp_img, $img, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
// sets the header and creates the temporary thumbnail
// ideal for ajax requests / <img> elements
header("Content-type: image/jpeg");
imagejpeg($img);
return true;
}
}
You can use ini_set("memory_limit","12M"); to set memory limit in your script. You can extend it from 12 megabytes to maximum memory you have.
Generally 64M is good.