I am using PHP GD library to flip an image and then save that flipped image. However I am able to flip image successfully but I don’t know how to save it with another name in a folder. My code is
$filename = '324234234234.jpg';
header('Content-type: image/jpeg');
$im = imagecreatefromjpeg($filename);
imageflip($im, IMG_FLIP_VERTICAL);
imagejpeg($im);
You need to pass a second parameter to imagejpeg($im) call with the path to the file you want to store.
imagejpeg($im, 'path/to/new/file.jpg');
http://php.net/manual/en/function.imagejpeg.php
Look at the documentation for imagejpeg where it explains the second parameter relates to $filename:
bool imagejpeg ( resource $image [, string $filename [, int $quality ]] )
The path to save the file to. If not set or NULL, the raw image stream will be outputted directly.
So just add the new filename as a second parameter like this; assuming the name of the new name is new_filename.jpg. Also comment out or completely remove the header line so you are not outputting the image to the browser, but rather saving it to a file so the header isn’t needed:
$filename = '324234234234.jpg';
// header('Content-type: image/jpeg');
$im = imagecreatefromjpeg($filename);
imageflip($im, IMG_FLIP_VERTICAL);
imagejpeg($im, 'new_filename.jpg');
Also note that while imageflip is nice to use it is only available in PHP 5.5 & higher; it won’t be available in PHP 5.4 or lower:
(PHP 5 >= 5.5.0)
image flip — Flips an image using a given mode
So if you want to use it in PHP 5.4 or lower, you need to create the logic to flip it on your own in the code or use a function like this. It only flips horizontally so you would have to adjust it to flip vertically, but posting here so you have something to explore & work with if needed:
/**
* Flip (mirror) an image left to right.
*
* #param image resource
* #param x int
* #param y int
* #param width int
* #param height int
* #return bool
* #require PHP 3.0.7 (function_exists), GD1
*/
function imageflip(&$image, $x = 0, $y = 0, $width = null, $height = null)
{
if ($width < 1) $width = imagesx($image);
if ($height < 1) $height = imagesy($image);
// Truecolor provides better results, if possible.
if (function_exists('imageistruecolor') && imageistruecolor($image))
{
$tmp = imagecreatetruecolor(1, $height);
}
else
{
$tmp = imagecreate(1, $height);
}
$x2 = $x + $width - 1;
for ($i = (int) floor(($width - 1) / 2); $i >= 0; $i--)
{
// Backup right stripe.
imagecopy($tmp, $image, 0, 0, $x2 - $i, $y, 1, $height);
// Copy left stripe to the right.
imagecopy($image, $image, $x2 - $i, $y, $x + $i, $y, 1, $height);
// Copy backuped right stripe to the left.
imagecopy($image, $tmp, $x + $i, $y, 0, 0, 1, $height);
}
imagedestroy($tmp);
return true;
}
Related
I'm trying to make a web app which has an admin site where you can upload an image. I'm already using imagecopy() to make a square photo. But when the image is too big I'm trying to resize with imagecopyresized(). I've already used this code:
$file = $_FILES['img']['tmp_name'];
$filename = $_FILES['img']['name'];
$size = 400;
$destino = imagecreatetruecolor($size, $size);
list($width, $height) = getimagesize($file);
$correction = $size / 2;
$widths = $width / 2 - $correction;
$heights = $height / 2 - $correction;
$origen = imagecreatefromjpeg($file);
$overflow = $size + 200;
if($width > $overflow){
$modified = $origen;
$ratio = $width / $height;
$growth = $width / $overflow;
$final = $overflow / $growth;
if($ratio > 1){
$newwidth = $final * $ratio;
}else{
$newwidth = $final / $ratio;
}
imagecopyresized($origen, $modified, 0, 0, 0, 0, $final, $newwidth, $width, $height);
}
imagecopy($destino, $origen, 0, 0, $widths, $heights, $size, $size);
The issue here is that there's no modification to the image that is bigger than $overflow.
$ratio is to keep the original dimensions of the photos and prevent deform.
$growth is an index that while bigger the image is, the smallest it will be copied.
$final is the final width taking the growth index as a count.
You've made some incorrect assumptions about how PHP handles resources and how the GD functions work.
$modified = $origen;
The above line does not give you two separate image resources; it gives you two variables pointing to the same image resource in memory. This means any operation on one will be reflected in the other.
This causes you to make two mistakes with the following line:
imagecopyresized($origen, $modified, 0, 0, 0, 0, $final, $newwidth, $width, $height);
This function doesn't resize the destination image ($origen) or the source image ($modified); it resizes the part of the image it copies from the source image (i.e., the specified part of $modified in your code).
Because $origen and $modified point to the same resource the function pastes the resized copy of the image on top of itself, like this:
Lastly you call:
imagecopy($destino, $origen, 0, 0, $widths, $heights, $size, $size);
A problem here is that $widths and $heights are calculated before the $origen resize, but in effect the problem is hidden because (as explained above) $origen isn't resized!
The result of all the above is to give you a square 'cut' from the middle of the original image, like this:
Here is how I would resize the input image to fit within 400x400px and centre it in the output:
$file = $_FILES['img']['tmp_name'];
$maxW = $maxH = 400;
list($srcW, $srcH) = getimagesize($file);
$ratio = $srcW / $srcH;
$src = imagecreatefromjpeg($file);
$dest = imagecreatetruecolor($maxW, $maxH);
if ($ratio > 1) {
// landscape.
$destH = ($maxH / $ratio);
imagecopyresized($dest, $src, 0, ($maxH / 2) - ($destH / 2), 0, 0, $maxW, $destH, $srcW, $srcH);
} else {
// portrait (or square).
$destW = ($maxW * $ratio);
imagecopyresized($dest, $src, ($maxW / 2) - ($destW / 2), 0, 0, 0, $destW, $maxH, $srcW, $srcH);
}
// now do whatever you want with $dest...
Note that this will result in black bars on the top/bottom (of a landscape image) or left/right (of a portrait image) of the output. You can just fill $dest with a colour, or transparency, before the imagecopyresized call to change this.
Whenever I am trying to use the function imageflip(), it shows me the following message
Fatal error: Call to undefined function imageflip() in D:\xampp\htdocs\temp1\image_flip.php on line 6
Once I have called the imap_open function, even though, I already installed the imap extension and configured all. However, it still shows the same message.
imageflip() is only available after PHP 5.5. However, you can still define it yourself, as explained here (although if you plan to upgrade to PHP 5.5, it is not recommended to implement yours, or at least change the name to avoid duplication problems). For the sake of stackoverflow, I'll paste the code here:
<?php
/**
* Flip (mirror) an image left to right.
*
* #param image resource
* #param x int
* #param y int
* #param width int
* #param height int
* #return bool
* #require PHP 3.0.7 (function_exists), GD1
*/
function imageflip(&$image, $x = 0, $y = 0, $width = null, $height = null)
{
if ($width < 1) $width = imagesx($image);
if ($height < 1) $height = imagesy($image);
// Truecolor provides better results, if possible.
if (function_exists('imageistruecolor') && imageistruecolor($image))
{
$tmp = imagecreatetruecolor(1, $height);
}
else
{
$tmp = imagecreate(1, $height);
}
$x2 = $x + $width - 1;
for ($i = (int) floor(($width - 1) / 2); $i >= 0; $i--)
{
// Backup right stripe.
imagecopy($tmp, $image, 0, 0, $x2 - $i, $y, 1, $height);
// Copy left stripe to the right.
imagecopy($image, $image, $x2 - $i, $y, $x + $i, $y, 1, $height);
// Copy backuped right stripe to the left.
imagecopy($image, $tmp, $x + $i, $y, 0, 0, 1, $height);
}
imagedestroy($tmp);
return true;
}
And to use it:
<?php
$image = imagecreate(190, 60);
$background = imagecolorallocate($image, 100, 0, 0);
$color = imagecolorallocate($image, 200, 100, 0);
imagestring($image, 5, 10, 20, "imageflip() example", $color);
imageflip($image);
header("Content-Type: image/jpeg");
imagejpeg($image);
I haven't tried it, and the code isn't mine at all, but with some tricks you could adapt it to your needs.
I'm trying to create thumbnail and resize image at the same time, so to be more clear here is the image that i'm trying to crop:
And i would like to cut out that red area.
Now my problem is that i'm resizing my image with html before croping so when i submit data to php i get incorrect values, like y = 100 when realy it could be y = 200 so i need to find a way to calculate my values.
I am using imagecopyresampled, maybe there is something better then this command?
Also my closest soliution was this:
imagecopyresampled(
$thumb, //Destination image link resource.
$src, //Source image link resource.
0, //x-coordinate of destination point.
0, //y-coordinate of destination point.
0, //x-coordinate of source point.
0, //y-coordinate of source point.
120, //Destination width.
160, //Destination height.
$image_width/2, //Source width.
$image_height/2 //Source height.
);
In this case it would cut out left corner but size would be not the same as my red box.
So i guess i need to get source width and source height right and everything else should fit perfectly, anyways i hope i make any sense here :)
EDIT Sorry i forgot to mention, $image_width and $image_height is the original image size
EDIT 2 To be more clear this is what i get when i resize with this code
$dimensions = getimagesize('testas.jpg');
$img = imagecreatetruecolor(120, 160);
$src = imagecreatefromjpeg('testas.jpg');
imagecopyresampled($img, $src, 0, 0, 0, 0, 120, 160, $dimensions[0]/2, $dimensions[1]/2);
imagejpeg($img, 'test.jpg');
Resized image size is correct, but as you can it doesn't look right.
I use something like this to scale images:
public static function scaleProportional($img_w,$img_h,$max=50)
{
$w = 0;
$h = 0;
$img_w > $img_h ? $w = $img_w / $img_h : $w = 1;
$img_h > $img_w ? $h = $img_h / $img_w : $h = 1;
$ws = $w > $h ? $ws = ($w / $w) * $max : $ws = (1 / $h) * $max;
$hs = $h > $w ? $hs = ($h / $h) * $max : $hs = (1 / $w) * $max;
return array(
'width'=>$ws,
'height'=>$hs
);
}
usage:
$getScale = Common::scaleProportional($prevWidth,$prevHeight,$scaleArray[$i][1]);
$targ_w = $getScale['width'];
$targ_h = $getScale['height'];
$jpeg_quality = 100;
$src = $prevdest;
$img_r = imagecreatefromjpeg($src);
$dst_r = ImageCreateTrueColor( $targ_w, $targ_h );
//imagecopyresampled(dest_img,src_img,dst_x,dst_y,src_x,src_y,dst_w,dst_h,src_w,src_h);
imagecopyresampled($dst_r,$img_r,0,0,0,0,$targ_w,$targ_h,$prevWidth,$prevHeight);
imagejpeg($dst_r, 'assets/images/'.$scaleArray[$i][0].'/'.$filename, $jpeg_quality);
$complete[] = $scaleArray[$i][0];
When you say 'resizing with HTML', do you mean specifying the size using the width and height attributes of the img element? If so, this won't affect the dimensions of the file on the server, and you can still get those using getimagesize.
Something like this will return the source width and height of the image:
function get_source_size($the_file_path)
{
$imagesize = getimagesize($the_file_path);
return array('width' => $imagesize[0], 'height' => $imagesize[1]);
}
So after some time i was able to do it with my friend help, this is the script i used, maybe some one will need it in the future :)
private function crop($user, $post){
//get original image size
$dimensions = getimagesize($post['image_src']);
//get crop box dimensions
$width = $post['w'] * ($dimensions[0] / $post['img_width']);
$height = $post['h'] * ($dimensions[1] / $post['img_height']);
//get crop box offset
$y = $post['y'] * ($dimensions[1] / $post['img_height']);
$x = $post['x'] * ($dimensions[0] / $post['img_width']);
//create image 120x160
$img = imagecreatetruecolor(120, 160);
$src = imagecreatefromjpeg($post['image_src']);
imagecopyresampled($img, $src, 0, 0, $x, $y, 120, 160, $width, $height);
//and save the image
return imagejpeg($img, 'uploads/avatars/'.$user->id.'/small/'.$post['image_name'].".jpg" , 100);
}
This function cropit, which I shamelessly stole off the internet, crops a 90x60 area from an existing image.
In this code, when I use the function for more than one item (image) the one will display on top of the other (they come to occupy the same output space).
I think this is because the function has the same (static) name ($dest) for the destination of the image when it's created (imagecopy).
I tried, as you can see to include a second argument to the cropit function which would serve as the "name" of the $dest variable, but it didn't work.
In the interest of full disclosure I have 22 hours of PHP experience (incidentally the same number of hours since the last I slept) and I am not that smart to begin with.
Even if there's something else at work here entirely, seems to me that generally it must be useful to have a way to secure that a variable is always given a unique name.
<?php
function cropit($srcimg, $dest) {
$im = imagecreatefromjpeg($srcimg);
$img_width = imagesx($im);
$img_height = imagesy($im);
$width = 90;
$height = 60;
$tlx = floor($img_width / 2) - floor ($width / 2);
$tly = floor($img_height / 2) - floor ($height / 2);
if ($tlx < 0)
{
$tlx = 0;
}
if ($tly < 0)
{
$tly = 0;
}
if (($img_width - $tlx) < $width)
{
$width = $img_width - $tlx;
}
if (($img_height - $tly) < $height)
{
$height = $img_height - $tly;
}
$dest = imagecreatetruecolor ($width, $height);
imagecopy($dest, $im, 0, 0, $tlx, $tly, $width, $height);
imagejpeg($dest);
imagedestroy($dest);
}
$img = "imagefolder\imageone.jpg";
$img2 = "imagefolder\imagetwo.jpg";
cropit($img, $i1);
cropit($img2, $i2);
?>
In this code, when I use the function for more than one item (image) the one will display on top of the other (they come to occupy the same output space).
You are creating the raw image data: you cannot serve multiple images at once in an HTTP request (you could save an unlimited amount to file ofcourse, imagejpg can take more parameters), no decent browser would know what to make of it.
If you want to overlay one image on another, look at imagecopyresampled()
I think this is because the function has the same (static) name ($dest) for the destination of the image when it's created (imagecopy).
This is not the case, as soon as your function exits $dest doesn't exist anymore (it only existed within the function scope. See http://php.net/manual/en/language.variables.scope.php
I hope I understood you. You want to save the cropped image to a filename you have in the variables $i1 and $i2?
Then the last part is probably wrong. It should be like this:
<?php
function cropit($srcimg, $filename) {
$im = imagecreatefromjpeg($srcimg);
$img_width = imagesx($im);
$img_height = imagesy($im);
$width = 90;
$height = 60;
$tlx = floor($img_width / 2) - floor ($width / 2);
$tly = floor($img_height / 2) - floor ($height / 2);
if ($tlx < 0)
{
$tlx = 0;
}
if ($tly < 0)
{
$tly = 0;
}
if (($img_width - $tlx) < $width)
{
$width = $img_width - $tlx;
}
if (($img_height - $tly) < $height)
{
$height = $img_height - $tly;
}
$dest = imagecreatetruecolor ($width, $height);
imagecopy($dest, $im, 0, 0, $tlx, $tly, $width, $height);
imagejpeg($dest, $filename); // Second parameter
imagedestroy($dest);
}
imagejpeg has a second parameter which takes the filename it should be saved as.
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;
}