How to crop image with dimensions (without quality loss) in PHP? - php

I need to crop the image with PHP by using the dimensions.
And save it into the local with JPEG format.
Dimensions that i receive is,
{"left":82.5,"top":48.875,"width":660,"height":371.25}
I need to crop from Original size of the image.
Ex. image is 1200x800, then the result image dimension from the actual size, not resizing or any. Because the quality should be same.
How could i use these params to crop the image ?
Is it possible ?

Use the built-in imagick class:
$image = realpath("/path/to/your/image.extension");
$cropped = realpath("/path/to/your/output/image.png");
$imObj = new Imagick();
$imObj->cropImage($width, $height, $offset_x, $offset_y);
$imObj->setImageFormat("png"); // this is unnesesary, you can force an image format with the extension of the output filename.
$imObj->writeImage($cropped);
As for lossless output, use an image format with lossless encoding. PNG is perfect for the job, since it was designed for network transfer (hence the "Adam-7" interlacing).
Check this related question about lossless image formats on graphic design stack:
What are lossless image formats?

You can use imageCopyResampled function which was designed pretty much exactly for this.
$image = imagecreatefromjpeg($imageFileURL);
/***
* resize values (imported)
***/
$left = 82;
$top = 49;
$width = 660;
$height = 371;
/***
* Create destination image
***/
$newImage = imagecreatetruecolor($width,$height);
$saveToFile = "destintion filespace of image file.jpg"
if(imagecopyresampled($newImage, $image, //dest/source images
0, 0, // dest coordinates
$left, $top, // source coordinates
$width, $height, // size of area to paste to
$width, $height // size of area to copy from
)){
imagejpeg($newImage,$saveToFile,100); //zero compression saved to file
print "image resized ok!!";
}
The new fileimage will be the size specified with $width,$height and will be offset from the original image by the values given in $left and $top. From your question this looks like what you want. This will not resize or change the compression of the image (until you save the file and then possibly set these details yourself).

Related

Calculate nearest possible dimension value PHP (keeping ratio)

I am trying to implement API for image resizing. It is created not exactly for image processing, this is only one part/feature of API.
What I want to implement.
I have url for retrieving image from server it looks like
mywebpage.com/api/product/42/image
This url will return URL to full image of product with id 42.
Everything is ok.
We can specify desired size with GET parameters like this
mywebpage.com/api/product/42/image?width=200&height=300
It also looks fine
But my question if following.
As we can have different images on server with different dimension and aspect ratio, I need to keep this ratio while resizing.
For example I need image to fit 200x300 container but I have 1024x576 (16:9) image on the server. I need to resize this image but keep initial aspect ratio(16:9) but to fit desired container.
How can I efficiently calculate new image size to return depending on incoming desired dimension and current image aspect ratio.
I want to thank everyone in advance for any help or advises.
Here is a script I used to make similar thing. Quite old , so may be not up to date.
<?php
if( isset($_GET["width"]) && is_numeric($_GET["width"]))
$target_width = intval($_GET["width"]);
else
$target_width= 200;//default value
if( isset($_GET["height"]) && is_numeric($_GET["height"]))
$target_height = intval($_GET["width"]);
else
$target_height= 300;//default value
if( isset($_GET["id"]) && is_numeric($_GET["id"]))//prevent any unwanted filesystem access
$original_image_path = "img/products/$id.jpg";
else
$original_image_path = "placeholder.png"
//http://php.net/manual/fr/function.getimagesize.php
$image_size = getimagesize($original_image_path);
//get the ratio of the original image
$image_ratio= $image_size[1]/ $image_size[0];
$original_image = imagecreatefromjpeg($original_image_path);
$new_image = imagecreatetruecolor($target_width, $image_ratio * $target_width);
//paints the image in white
//http://php.net/manual/en/function.imagefill.php
//http://php.net/manual/en/function.imagecolorallocatealpha.php
imagefill( $new_image, 0, 0, imagecolorallocatealpha($new_image, 255,255,255,127) );
imagesavealpha($new_image, TRUE);
/*
Copies the original to the new, preserving the ratio.
The original image fills all the width of the new,
and is placed on the top of the new.
http://php.net/manual/en/function.imagecopyresized.php
*/
imagecopyresized(
$new_image,$original_image,
0,0,
0,0,
$target_width,$image_ratio * $target_width,
$image_size[0],$image_size[1]
);
//image is returned in response to the request
header ("Content-type: image/png");
imagepng( $new_image );
?>
Well if you need to always fit a container of 200x300 (or what ever is passed through the URL), you may not because able to simply resize it because as you are aware it will affect the images aspect ratio.
If this is the case what you can do is resize the image to the closest size then crop the remainder of the image.
I assume you will be using imagemagick for this. Have you checked out the documentation? The cropThumbnailImage method does what I just explained.
Example usage:
/* Read the image */
$im = new imagick( "test.png" );
/* create the thumbnail */
$im->cropThumbnailImage( 80, 80 );
/* Write to a file */
$im->writeImage( "th_80x80_test.png" );
http://php.net/manual/en/imagick.cropthumbnailimage.php

cropping image propery from a specific portion using GD library

I am not able to crop the image bellow properly using this code. I am not sure about the problem but some of the jpg are cropped correctly with this code.
For coordinate selection i am using Image Cropper in front end.
For the image i have attached bellow, cropping doesn't happen according to starting point x and y, and it starts from different position for some images like the one bellow.
Cropping width and height is ok but starting point is not though i have provided x and y value.
$sourceFile = 'test.jpg';
$destinationFile = 'dest/test.jpg';
$jsonData = '{"x": 142, "y":233, "width":372, "height":209}';
$dataCropValue = json_decode($jsonData);
$src_img = imagecreatefromjpeg($sourceFile);
list($width, $height) = getimagesize($sourceFile);
$dst_img = imagecreatetruecolor($dataCropValue->width, $dataCropValue->height);
imagecopyresampled($dst_img, $src_img, 0, 0 , $dataCropValue->x , $dataCropValue->y ,
$dataCropValue->width, $dataCropValue->height ,
$dataCropValue->width, $dataCropValue->height);
imagejpeg($dst_img, $destinationFile);

Is it possible to rotate an image that is saved as BLOB in PHP - without using imagerotate?

When I retrieve a blob (an image) from the database, is there any way to rotate this image in PHP without imagerotate()?
Can this be done on the binary level? Like switching positions of all pixels?
Is there a shorter way than creating a temporary image and calling imagerotate()?
Thinking of JPG and PNG ... they are compressed... maybe then it is not possible? However, it might work for BMP.
Just for information, this is how I do the rotation of the blob image if JPG currently:
$degrees = -90;
$source_image = imagecreatefromstring($blob['content']);
$rotate_image = imagerotate($source_image, $degrees, 0);
ob_start();
imagejpeg($rotate_image, null, 100);
$image_bin = ob_get_contents();
ob_end_clean();
qa_db_query_sub( 'UPDATE blobs SET content=$
WHERE blobid=#', $image_bin, $rotateBlobId );
// free the memory
imagedestroy($source_image);
imagedestroy($rotate_image);

PHP GD Image Library change image color - gif works but jpegs wont

Thanks for taking the time to read my problem:
I'm using the following code to get an image and then change the color 201,2,255 (r,g,b) - which is a shade of purple then output the image.
$imgname = "input.gif";
$im = imagecreatefromgif ($imgname);
$index = imagecolorclosest ( $im, 201,2,255 ); // get White COlor
imagecolorset($im,$index,60,140,48); // SET NEW COLOR
$imgname = "output.gif";
imagegif($im, $imgname ); // save image as gif
imagedestroy($im);
This works perfectly which can be seen here : http://www.office-desks.co.uk/cache_images/test.php (top 2 images)
The problem is when I try todo exactly the same but using a jpeg instead it doesn't work.. (bottom 2 images)
$imgname = "input.jpg";
$im = imagecreatefromjpeg ($imgname);
$index = imagecolorclosest ( $im, 201,2,255 ); // get pink/purple COlor
imagecolorset($im,$index,60,140,48); // SET NEW DECENT COLOR
$imgname = "output.jpg";
imagejpeg($im, $imgname ); // save image as gif
imagedestroy($im);
If anyone could help me shed some light on the problem, would be much appreciated. Thanks in advance all.
A bit late, but I think that has to do with the 'artifacts' (compression errors) generated by JPG. Zoom in on a JPG and you see 'grains' of pixels that won't match the neighbors. This means big planes of a single color will become many colors and not 1 single value.
Stick with lossless image formats like gif or png.

How to merge two images and save in php at Run Time?

i want to make a picture upload in frame and save both image and frame as a single image ,main thing is whatever the size of image in frame,it should be appear exactly same in a final resulting image after merging.
Here is part of my code:
$imgframe = $_GET['imgframe'];
$imgphoto = $_GET['imgphoto'];
$imgwidth = $_GET['imgwidth'];
$imgheight = $_GET['imgheight'];
$imgleft = substr($_GET['imgleft'],0,-2);
$imgtop = substr($_GET['imgtop'],0, -2);
$src = imagecreatefromjpeg($imgphoto);//'image.jpg'
$dest = imagecreatefrompng($imgframe);//clip_image002.png
imagealphablending($dest, false);
imagesavealpha($dest, true);
imagecopyresampled(
$dest, $src, $imgleft, $imgtop, $imgleft, $imgtop,
$imgwidth, $imgheight, $imgwidth, $imgheight
);
As per your comment below the question, you are using the wrong function.
The PHP manual page for imagecopymerge states that it copies a part of an image onto another. It states that you can specify the origin coordinates, width and height of the region to copy from the source, and the coordinates in the destination in which to place that region.
In other words, it takes a rectangular area of a given size from the source image and puts it on top of the destination, at the given location. It does NOT ask for the size of the region into which you are copying it, only the location. Therefore, it does not resize the copied region, but copies it pixel-for-pixel.
The function you actually need is imagecopyresampled, which allows you to specify the size of the destination region, and will smoothly scale the source region to fit.
EDIT
You are still having a problem because you are using the same coordinates and the same dimensions in the source and the destination parameters. Same dimensions == no resizing.
$imgframe = $_GET['imgframe'];
$imgphoto = $_GET['imgphoto'];
// I am assuming these specify the area of the imgphoto which
// should be placed in the frame?
$imgwidth = $_GET['imgwidth'];
$imgheight = $_GET['imgheight'];
$imgleft = substr($_GET['imgleft'],0,-2);
$imgtop = substr($_GET['imgtop'],0, -2);
// now you also need to get the size of the frame so that
// you can resize the photo correctly:
$frameSize = getimagesize($imgframe);
$src = imagecreatefromjpeg($imgphoto);//'image.jpg'
$dest = imagecreatefrompng($imgframe);//clip_image002.png
imagealphablending($dest, false);
imagesavealpha($dest, true);
imagecopyresampled(
$dest, $src,
0, 0, // these two specify where in the DESTINATION you want to place the source. You might want these to be offset by the width of the frame
$imgleft, $imgtop, // the origin of area of the source you want to copy
$frameSize[0], $frameSize[1], // These specify the size of the area that you want to copy IN TO (i.e., the size in the destination), again you might want to reduce these to take into account the width of the frame
$imgwidth, $imgheight // the size of the area to copy FROM
);

Categories