This is my code, but I dont know why but when I upload a vertical image it is resized and I get two black stripes on the sides. With wide images it works well most of the time but with some images I get black stripes as well. How can I fix it?
My purpose is to crop every image, horizontal just a hint to fit my box, and vertical I want to crop so the width is the same and they are cut no top and bottom.
$thumb_height = 200;
$thumb_width = 300;
$thumb = imagecreatetruecolor($thumb_width, $thumb_height);
if($width >= $height) {
// If image is wider than thumbnail (in aspect ratio sense)
$new_height = $thumb_height;
$new_width = $width / ($height / $thumb_height);
} else {
// If the thumbnail is wider than the image
$new_width = $thumb_width;
$new_height = $height / ($width / $thumb_width);
}
$output_filename_mid = 'uploads/'.IMG_L.$fileName;
imagecopyresampled($thumb,
$image,
0 - ($new_width - $thumb_width) / 2, // Center the image horizontally
0 - ($new_height - $thumb_height) / 2, // Center the image vertically
0, 0,
$new_width, $new_height,
$width, $height);
imagejpeg($thumb, $output_filename_mid, 85);
You're almost there. You've figured out that you need to determine the ratio between the old height and the destination height to resize the side that'll be cropped. However, you need to determine this in relation to the destination ratio.
if(($width / $height) > ($thumb_width / $thumb_height)) {
// If image is wider than thumbnail (in aspect ratio sense)
$new_height = $thumb_height;
$new_width = $width / ($height / $thumb_height);
} else {
// If the thumbnail is wider than the image
$new_width = $thumb_width;
$new_height = $height / ($width / $thumb_width);
}
I'm actually working with this a lot. Here is my code which is VERY similar to yours. Can you find the difference/problem yourself?
My code works 100% and does exactly what you need and ONLY that. Feel free to use it!
Variables explained: $imagewidth and $imageheight are naturally the original pixel sizes of the input image. $crop_ratio_w is crop ratio width and $crop_ratio_h is crop ratio height.
So for my code vs. your code: $crop_ratio_w = $thumb_width and $crop_ratio_h = $thumb_height
//do this if we can start cropping by width (there's enough space on height)
if (($imagewidth * $crop_ratio_h / $crop_ratio_w) < $imageheight){
//count new res
$new_width = $imagewidth;
$new_height = ($imagewidth * $crop_ratio_h / $crop_ratio_w);
//count the height difference, so that new image is cropped in HEIGHT center
$difference = ($imageheight - $new_height);
$y_offset = ($difference / 2);
//create new empty image
$croppedImage = imagecreatetruecolor($new_width, $new_height);
//copy wanted area to the new empty image
imagecopy($croppedImage, $originalImage, 0, 0, 0, $y_offset, $new_width, $new_height);
}
//else on previous condition -- do this if we have to start cropping by height (there's not enough space on height)
else{
//count new res
$new_width = ($imageheight * $crop_ratio_w / $crop_ratio_h);
$new_height = $imageheight;
//count the height difference, so that new image is cropped in WIDTH center
$difference = ($imagewidth - $new_width);
$x_offset = ($difference / 2);
//create new empty image
$croppedImage = imagecreatetruecolor($new_width, $new_height);
//copy wanted area to the new empty image
imagecopy($croppedImage, $originalImage, 0, 0, $x_offset, 0, $new_width, $new_height);
}
Related
I am trying to batch resize images to the size of 250 x 250 in PHP
All source images are way bigger than 250 x 250 so that is helpful.
I want to maintain aspect ratio but make them all 250 x 250. I know that a portion of the image will be cropped off to do this. That is not an issue for me
The problem is that my current script only works on width and makes height according to aspect but sometimes, the image will now end up being let's say, 250 x 166. I can't use that.
In that cause It would need to be resized in the opposite manner (height to width)
How would the script have to look to always make the final image 250 x 250 without stretching. Again, I don't care if there is cropping. I assume there is going to be an else in the somewhere but this is way over my head now. I am more of a front end guy.
Any help would be great.
Below is just the relevant portion of my full script:
$width = 250;
$height = true;
// download and create gd image
$image = ImageCreateFromString(file_get_contents($url));
// calculate resized ratio
// Note: if $height is set to TRUE then we automatically calculate the height based on the ratio
$height = $height === true ? (ImageSY($image) * $width / ImageSX($image)) : $height;
// create image
$output = ImageCreateTrueColor($width, $height);
ImageCopyResampled($output, $image, 0, 0, 0, 0, $width, $height, ImageSX($image), ImageSY($image));
// save image
ImageJPEG($output, $destdir, 100);
$newWidth = 250;
$newHeight = 250;
// download and create gd image
$image = ImageCreateFromString(file_get_contents($url));
$width = ImageSX($image);
$height = ImageSY($image);
$coefficient = $newHeight / $height;
if ($newHeight / $width > $coefficient) {
$coefficient = $newHeight / $width;
}
// create image
$output = ImageCreateTrueColor($newWidth, $newHeight);
ImageCopyResampled($output, $image, 0, 0, 0, 0, $width * $coefficient, $height * $coefficient, $width, $height);
// save image
ImageJPEG($output, $destdir, 100);
I am trying to resize an image to a width of 500px. I want to keep the aspect ratio of the image.
My original image is
When I resized it to size of width 500, it is coming like
I am doing the following code for resizing image.
$target_dir="uploads/reference/".$data['CP_Image'];
move_uploaded_file($tmp_file, $target_dir);
list($w, $h) = getimagesize($target_dir);
$width=500;
$ratio = $width / $h;
$x = ($w - $width / $ratio) / 2;
$height = 500 / $ratio;exit;
$path = "uploads/reference/".$data['CP_Image'];
$thumb = imagecreatetruecolor($width, $height);
$source = imagecreatefromjpeg($target_dir);
// Resize
imagecopyresized($thumb, $source, 0, 0, 0, 0, $width, $height, $w, $h);
// Output and free memory
imagejpeg($thumb,$path);
imagedestroy($thumb);
With this code, the width is changed to 500px but height is not proportional. What I am doing wrong? Can anyone help me to fix it?
Thanks in advance
You're calculating the ratio incorrectly. Instead of dividing the new width by the original height, you want something like this:
list($w, $h) = getimagesize($target_dir);
$width = 500;
$ratio = $w / $h;
$height = $width / $ratio;
I use imagick for thumbnail crop, but sometimes cropped thumbnails are missing top part of the images (hair, eyes).
I was thinking to resize the image then crop it. Also, I need to keep the image size ratio.
Below is the php script I use for crop:
$im = new imagick( "img/20130815233205-8.jpg" );
$im->cropThumbnailImage( 80, 80 );
$im->writeImage( "thumb/th_80x80_test.jpg" );
echo '<img src="thumb/th_80x80_test.jpg">';
Thanks..
This task is not easy as the "important" part may not always be at the same place. Still, using something like this
$im = new imagick("c:\\temp\\523764_169105429888246_1540489537_n.jpg");
$imageprops = $im->getImageGeometry();
$width = $imageprops['width'];
$height = $imageprops['height'];
if($width > $height){
$newHeight = 80;
$newWidth = (80 / $height) * $width;
}else{
$newWidth = 80;
$newHeight = (80 / $width) * $height;
}
$im->resizeImage($newWidth,$newHeight, imagick::FILTER_LANCZOS, 0.9, true);
$im->cropImage (80,80,0,0);
$im->writeImage( "D:\\xampp\\htdocs\\th_80x80_test.jpg" );
echo '<img src="th_80x80_test.jpg">';
(tested)
should work. The cropImage parameters (0 and 0) determine the upper left corner of the cropping area. So playing with these gives you differnt results of what stays in the image.
Based on Martin's answer I made a more general function that resizes and crops Imagick image to fit given width and height (i.e. behaves exactly as CSS background-size: cover declaration):
/**
* Resizes and crops $image to fit provided $width and $height.
*
* #param \Imagick $image
* Image to change.
* #param int $width
* New desired width.
* #param int $height
* New desired height.
*/
function image_cover(Imagick $image, $width, $height) {
$ratio = $width / $height;
// Original image dimensions.
$old_width = $image->getImageWidth();
$old_height = $image->getImageHeight();
$old_ratio = $old_width / $old_height;
// Determine new image dimensions to scale to.
// Also determine cropping coordinates.
if ($ratio > $old_ratio) {
$new_width = $width;
$new_height = $width / $old_width * $old_height;
$crop_x = 0;
$crop_y = intval(($new_height - $height) / 2);
}
else {
$new_width = $height / $old_height * $old_width;
$new_height = $height;
$crop_x = intval(($new_width - $width) / 2);
$crop_y = 0;
}
// Scale image to fit minimal of provided dimensions.
$image->resizeImage($new_width, $new_height, imagick::FILTER_LANCZOS, 0.9, true);
// Now crop image to exactly fit provided dimensions.
$image->cropImage($new_width, $new_height, $crop_x, $crop_y);
}
Hope this may help somebody.
My code. Please vote
// Imagick
$image = new Imagick($img);
// method 1 - resize to max width
if($type==1){
$image->resizeImage($newWidth,0,Imagick::FILTER_LANCZOS,1);
// method 2 - resize to max height
}else if($type==2){
$image->resizeImage(0,$newHeight,Imagick::FILTER_LANCZOS,1);
// method 1 - resize to max width or height
}else if($type==3){
if($image->getImageHeight() <= $image->getImageWidth()){
$image->resizeImage($newWidth,0,Imagick::FILTER_LANCZOS,1);
}else{
$image->resizeImage(0,$newHeight,Imagick::FILTER_LANCZOS,1);
}
// method 4 - resize and crop to center
}else if($type==4){
if($image->getImageHeight() <= $image->getImageWidth()){
$image->resizeImage(0,$newheight,Imagick::FILTER_LANCZOS,1);
}else{
$image->resizeImage($newwidth,0,Imagick::FILTER_LANCZOS,1);
}
$cropWidth = $image->getImageWidth();
$cropHeight = $image->getImageHeight();
$image->cropimage(
$newwidth,
$newheight,
($cropWidth - $newwidth) / 2,
($cropHeight - $newheight) / 2
);
}
$image->setImageFormat("jpeg");
$image->setImageCompression(Imagick::COMPRESSION_JPEG);
$image->writeImages($newImg, true);
$image->clear();
$image->destroy();
I am uploading logos to my system, and they need to fix in a 60x60 pixel box. I have all the code to resize it proportionately, and that's not a problem.
My 454x292px image becomes 60x38. The thing is, I need the picture to be 60x60, meaning I want to pad the top and bottom with white each (I can fill the rectangle with the color).
The theory is I create a white rectangle, 60x60, then I copy the image and resize it to 60x38 and put it in my white rectangle, starting 11px from the top (which adds up to the 22px of total padding that I need.
I would post my code but it's decently long, though I can if requested.
Does anyone know how to do this or can you point me to code/tutorial that does this?
With GD:
$newWidth = 60;
$newHeight = 60;
$img = getimagesize($filename);
$width = $img[0];
$height = $img[1];
$old = imagecreatefromjpeg($filename); // change according to your source type
$new = imagecreatetruecolor($newWidth, $newHeight)
$white = imagecolorallocate($new, 255, 255, 255);
imagefill($new, 0, 0, $white);
if (($width / $height) >= ($newWidth / $newHeight)) {
// by width
$nw = $newWidth;
$nh = $height * ($newWidth / $width);
$nx = 0;
$ny = round(fabs($newHeight - $nh) / 2);
} else {
// by height
$nw = $width * ($newHeight / $height);
$nh = $newHeight;
$nx = round(fabs($newWidth - $nw) / 2);
$ny = 0;
}
imagecopyresized($new, $old, $nx, $ny, 0, 0, $nw, $nh, $width, $height);
// do something with new: like imagepng($new, ...);
imagedestroy($new);
imagedestroy($old);
http://php.net/manual/en/function.imagecopyresampled.php
That's basically the function you want to copy and resize it smoothly.
http://www.php.net/manual/en/function.imagecreatetruecolor.php
With that one you create a new black image.
http://www.php.net/manual/en/function.imagefill.php
That part explains how to fill it white.
The rest follows.
here is the website im talking about
http://makeupbyarpi.com/portfolio.php
you'll notice some of the images are smushed width-wise.
the code i used is this:
$width="500";
$height="636";
$img_src = $_FILES['galleryimg']['tmp_name'];
$thumb = "../gallery/".rand(0,100000).".jpg";
//Create image stream
$image = imagecreatefromjpeg($img_src);
//Gather and store the width and height
list($image_width, $image_height) = getimagesize($img_src);
//Resample/resize the image
$tmp_img = imagecreatetruecolor($width, $height);
imagecopyresampled($tmp_img, $image, 0, 0, 0, 0, $width, $height, $image_width, $image_height);
//Attempt to save the new thumbnail
if(is_writeable(dirname($thumb))){
imagejpeg($tmp_img, $thumb, 100);
}
//Free memory
imagedestroy($tmp_img);
imagedestroy($image);
the images that get uploaded are huge sometimes 3000px by 2000px and i have php crop it down to 500 x 536 and some landscape based images get smushed. is there a formula i can use to crop it carefully so that the image comes out good?
thanks
You could resize and add a letterbox if required. You simply need to resize the width and then calculate the new height (assuming width to height ratio is same as original) then if the height is not equal to the preferred height you need to draw a black rectangle (cover background) and then centre the image.
You could also do a pillarbox, but then you do the exact same as above except that width becomes height and height becomes width.
Edit: Actually, you resize the one that is the biggest, if width is bigger, you resize that and if height is bigger then you resize that. And depending on which one you resize, your script should either letterbox or pillarbox.
EDIT 2:
<?php
// Define image to resize
$img_src = $_FILES['galleryimg']['tmp_name'];
$thumb = "../gallery/" . rand(0,100000) . ".jpg";
// Define resize width and height
$width = 500;
$height = 636;
// Open image
$img = imagecreatefromjpeg($img_src);
// Store image width and height
list($img_width, $img_height) = getimagesize($img_src);
// Create the new image
$new_img = imagecreatetruecolor($width, $height);
// Calculate stuff and resize image accordingly
if (($width/$img_width) < ($height/$img_height)) {
$new_width = $width;
$new_height = ($width/$img_width) * $img_height;
$new_x = 0;
$new_y = ($height - $new_height) / 2;
} else {
$new_width = ($height/$img_height) * $img_width;
$new_height = $height;
$new_x = ($width - $new_width) / 2;
$new_y = 0;
}
imagecopyresampled($new_img, $img, $new_x, $new_y, 0, 0, $new_width, $new_height, $img_width, $img_height);
// Save thumbnail
if (is_writeable(dirname($thumb))) {
imagejpeg($new_img, $thumb, 100);
}
// Free up resources
imagedestroy($new_img);
imagedestroy($img);
?>
Sorry it took a while, I ran across a small bug in the calculation part which I was unable to fix for like 10 minutes =/ This should work.