php resize image then crop image problem - php

I want to reduce a picture size from 600px * 500px to 60px * 50px size, then crop it become 50px *50px. I have two groups of codes, 1 is to reduce the size of image, other 1 is to crop the image. The problem is they works separately, how to combine this two groups of codes to make them work together? Below is my codes :
<?php
//codes of group A - Reduce the size of image from 600px * 500px to 60px * 50px
$save2 = "images/users/" . $image_name_2; //This is the new file you saving
list($width2, $height2) = getimagesize($file) ;
$modwidth2 = 50;
$diff2 = $width2 / $modwidth2;
$modheight2 = $height2 / $diff2;
$tn2 = imagecreatetruecolor($modwidth2, $modheight2) ;
$image2 = imagecreatefromjpeg($file) ;
imagecopyresampled($tn2, $image2, 0, 0, 0, 0, $modwidth2, $modheight2, $width2, $height2) ;
imagejpeg($tn2, $save2, 100) ;
//codes of group B - Crop the image from 60px * 50px to 50px * 50px
$save3 = "images/users/" . $image_name_3;
list($width3, $height3) = getimagesize($file) ;
$modwidth3 = 60;
$diff3 = $width3 / $modwidth3;
$modheight3 = $height3 / $diff3;
$left = 0;
$top = 0;
$cropwidth = 50; //thumb size
$cropheight = 50;
$tn3 = imagecreatetruecolor($cropwidth, $cropheight) ;
$image3 = imagecreatefromjpeg($file) ;
imagecopyresampled($tn3, $image3, 0, 0, $left, $top, $cropwidth, $cropheight, $modwidth3, $modheight3) ;
imagejpeg($tn3, $save3, 100) ; //save the cropped image
?>
As you can see from 2 groups of codes above, 1st group resize the pic then save it to a folder. 2nd group of codes crop the pic then save it into the folder too. My question is ... After 1st group of codes resize the picture, is it necessary to save it into folder before I can crop it? If it is necessary, then I need to write new lines of codes to retrieve the resized pic from the folder for 2nd group of codes to crop it? If it is not necessary, after resizing the pic, how do I pass the pic to 2nd group of codes to crop it?

Here you are #zac1987.
Full PHP code generating square thumbnail of desired size without stretching image. The code supports both png and jpg/jpeg image extensions. Simply change settings part to desired one. You can copy paste the code and test it on your web server.
<?php
// SETTINGS
$image_name = 'file.jpg'; // Full path and image name with extension
$thumb_name = 'thumbnail'; // Generated thumbnail name without extension
$thumb_side = 100; // Desired thumbnail side size
// END OF SETTINGS
$image_extension = explode('.', $image_name); // I assume that images are named only following 'imagename.ext' pattern
if (preg_match('/jpg|jpeg/', $image_extension[1])) {
$src_image = imagecreatefromjpeg($image_name);
$image_extension = 'jpg';
} else if (preg_match('/png/', $image_extension[1])) {
$src_image = imagecreatefrompng($image_name);
$image_extension = 'png';
}
$src_width = imageSX($src_image); // Width of the original image
$src_height = imageSY($src_image); // Height of the original image
$min_side = min($src_width, $src_height);
/*********** If you need this part uncomment it
$ratio = $min_side / $thumb_width;
$new_width = floor($src_width / $ratio);
$new_height = floor($src_height / $ratio);
**********************************************/
$dst_image = imagecreatetruecolor($thumb_side, $thumb_side);
imagecopyresampled($dst_image, $src_image, 0, 0, 0, 0, $thumb_side, $thumb_side, $min_side, $min_side);
switch ($image_extension)
{
case 'jpg':
imagejpeg($dst_image, $thumb_name . '.jpg', 100);
break;
case 'png':
imagepng($dst_image, $thumb_name . '.jpg', 100);
break;
}
imagedestroy($src_image);
imagedestroy($dst_image);
?>

$modwidth3 = 500; //I resize the picture width to smaller as 60px.
$diff3 = $width3 / $modwidth3;
$modheight3 = $height3 / $diff3; //I resize the picture height to smaller.
$left = 1; //getting the left and top coordinate
$top = 1;
$cropwidth = 50; //thumb size
$cropheight = 50;
imagecopyresampled($tn3, $image3, 0, 0, $left, $top, $cropwidth, $cropheight, $modwidth3, $modheight3) ;
$modwidth3 and $modheight3 need to correspond to the width and height of the image you want to crop. Also $top and $left should match the top left coordinate of the area you want to crop. If the original image is 600x500 px and you want to resize and crop to 50x50, you should set $top to 0 and $left to 50 (px). Both $modwidth and $modheight should be set to 500. That keeps the full height of the original image and cuts away 50px from the left hand side and 50px from the right hand side. The remaining 500px is cropped to 50px.

link to a blog article i wrote about how to resize any size image to any arbitrary size. includes options for letterboxing and crop-to-fit.
http://www.spotlesswebdesign.com/blog.php?id=1

Related

image manipulation width and height setting

in my project i just do image watermarking or image combine it's working fine and code for that.
<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<?php
if(isset($_POST['submit']))
{
// Give the Complete Path of the folder where you want to save the image
$folder="uploads/";
move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], "$folder".$_FILES["fileToUpload"]["name"]);
$file='uploads/'.$_FILES["fileToUpload"]["name"];
$uploadimage=$folder.$_FILES["fileToUpload"]["name"];
$newname= time();
$ext = pathinfo($_FILES["fileToUpload"]["name"], PATHINFO_EXTENSION);
// Set the thumbnail name
$thumbnail = $folder.$newname.".".$ext;
$imgname=$newname.".".$ext;
// Load the mian image
if ($ext=="png" || $ext=="PNG") {
$source = imagecreatefrompng($uploadimage);
}
else if ($ext=="gif" || $ext=="GIF") {
$source = imagecreatefromgif($uploadimage);
}
else if ($ext=="bmp" || $ext=="BMP") {
$source = imagecreatefrombmp($uploadimage);
}
else{
$source = imagecreatefromjpeg($uploadimage);
}
// load the image you want to you want to be watermarked
$watermark = imagecreatefrompng('uploads/logo1.png');
// get the width and height of the watermark image
$water_width = imagesx($source)/2;
$water_height = imagesy($watermark);
// get the width and height of the main image image
$main_width = imagesx($source);
$main_height = imagesy($source);
$im_middle_w = $main_width/2;
$im_middle_h = $main_height/2;
// Set the dimension of the area you want to place your watermark we use 0
// from x-axis and 0 from y-axis
$dime_x = $im_middle_w - $water_width/2;
$dime_y = $im_middle_h - $water_height/2;
// copy both the images
imagecopy($source, $watermark, $dime_x, $dime_y, 0, 0, $water_width, $water_height);
// Final processing Creating The Image
imagejpeg($source, $thumbnail, 100);
unlink($file);
}
?>
<img src='uploads/<?php echo $imgname;?>'>
</body>
</html>
but problem with setting $water_width and i want set as half of my source image. but when i have source image of less width or more width compare to $water_width it's set it like that. see image when source image width is more.
and when width is less.
so my problem is how to set $water_width as half of source image width?
by Alex your answer it's came up like this.
This will resize watermark to half-width of original image and put it in the centre:
// load the image you want to you want to be watermarked
$watermark = imagecreatefrompng('uploads/logo1.png');
// get the width and height of the watermark image
$water_width = imagesx($watermark);
$water_height = imagesy($watermark);
// get the width and height of the main image image
$main_width = imagesx($source);
$main_height = imagesy($source);
// resize watermark to half-width of the image
$new_height = round($water_height * $main_width / $water_width / 2);
$new_width = round($main_width / 2);
$new_watermark = imagecreatetruecolor($new_width, $new_height);
// keep transparent background
imagealphablending( $new_watermark, false );
imagesavealpha( $new_watermark, true );
imagecopyresampled($new_watermark, $watermark, 0, 0, 0, 0, $new_width, $new_height, $water_width, $water_height);
// Set the dimension of the area you want to place your watermark we use 0
// from x-axis and 0 from y-axis
$dime_x = round(($main_width - $new_width)/2);
$dime_y = round(($main_height - $new_height)/2);
// copy both the images
imagecopy($source, $new_watermark, $dime_x, $dime_y, 0, 0, $new_width, $new_height);
// Final processing Creating The Image
imagejpeg($source, $thumbnail, 100);
imagedestroy($source);
imagedestroy($watermark);
imagedestroy($new_watermark);
You can try imagettftext method, if you don't want any such high perfection in transparency. You can have try of this code. You have to save a font file in your directory, here I used arial.ttf.
$im = imagecreatefrompng("png.png"); //create image data
$font = 'arial.ttf'; //font file name
$randomString = "example.com"; //string need to be shown
$main_width = imagesx($im); //finding width and height
$main_height = imagesy($im);
$posx= $main_width/2; //finding center
$posy = $main_height/2;
$color = imagecolorallocate($im, 200, 200, 200); //Creating color
$size = ($main_width/25)+1; //determine size of font. +1 to avoid 0
$temp = $size*5;
$posx = $posx-$temp; //adjust to average center
imagettftext($im,$size,0, $posx, $posy, $color, $font , $randomString); //apply a text
You have to adjust posx and posy for your text position. Size also can be adjusted with some logics.
$color = imagecolorallocate($im, 0, 0, 0);= black
and $color = imagecolorallocate($im, 255, 255, 255); = white.
You have to adjust this for your required text color.

PHP Imagick - Center Cropped image on top of another

I am just starting with PHP's Imageick library.
I start by cropping a users image like so:
$img_path = 'image.jpg';
$img = new Imagick($img_path);
$img_d = $img->getImageGeometry();
$img_w = $img_d['width'];
$img_h = $img_d['height'];
$crop_w = 225;
$crop_h = 430;
$crop_x = ($img_w - $crop_w) / 2;
$crop_y = ($img_h - $crop_h) / 2;
$img->cropImage($img_w, $img_h, $crop_x, $crop_y);
I now need to place the cropped image of 225 x 430 onto a new image at 500px x 500px in the center. The new image must have a transparent background. Like so (the grey border is visual only):
How can I do so? I have tried 2 options:
compositeImage()
$trans = '500x500_empty_transparent.png';
$holder = new Imagick($trans);
$holder->compositeImage($img, imagick::COMPOSITE_DEFAULT, 0, 0);
By making a transparent png with nothing on it at 500x500px i was hoping i could use compositeImage to put the image on top of that. It does this but doesn't keep the original size of the $holder but uses the 225x430 size
frameImage()
$frame_w = (500 - $w) / 2;
$frame_h = (500 - $h) / 2;
$img->frameimage('', $frame_w, $frame_h, 0, 0);
I create a border that makes up the remaining pixels of the image to make 500 x500px. I was hoping by leaving the first colour parameter blank it would be transparent but it creates a light grey background so isn't transparent.
How can I achieve this?
If you only want a transparent background you don't need a separate image file. Just crop the image and resize it.
<?php
header('Content-type: image/png');
$path = 'image.jpg';
$image = new Imagick($path);
$geometry = $image->getImageGeometry();
$width = $geometry['width'];
$height = $geometry['height'];
$crop_width = 225;
$crop_height = 430;
$crop_x = ($width - $crop_width) / 2;
$crop_y = ($height - $crop_height) / 2;
$size = 500;
$image->cropImage($crop_width, $crop_height, $crop_x, $crop_y);
$image->setImageFormat('png');
$image->setImageBackgroundColor(new ImagickPixel('transparent'));
$image->extentImage($size, $size, -($size - $crop_width) / 2, -($size - $crop_height) / 2);
echo $image;
Use setImageFormat to convert the image to PNG (to allow transparency), then set a transparent background with setImageBackgroundColor. Finally, use extentImage to resize it.

PHP GD not sizing down image by a certain percentage

I have the below script, it all works fine, apart from if I enter a value into the function arguments for the percentage, the overlay's are too large, they should scale down by #% of the max size.
Here is an example:
But then if I change the "80" to "0" in the function call I get this:
If I change the same value to lets say "20" to scale the overlay down by 20%, I simply get the same as above...
Any ideas as to why it isn't scaling the overlay down by inputted %?
<?php
session_start();
//Set the content-type
header('Content-Type: image/png');
//Overlay URLS
$overlay_url = $_SESSION['ROOT_PATH']."images/logos/overlay.png";
$logo_url = $_SESSION['ROOT_PATH']."images/logos/".$_GET['logo'].".png";
//How much of the image will the overlays take up
$logo_percent = 0.60;
$overlay_percent = 0.90;
//Get the image size first
$size = explode(",",$_GET['size']);
$width = (int)$size[0];
$height = (int)$size[1];
$background = imagecreatetruecolor($width,$height);
$bg_color = imagecolorallocate($background,20,100,255);
imagefill($background, 0, 0, $bg_color);
//Apply company logo first
$company_logo = apply_watermark($background,$overlay_url,80,0,0,90);
//Now venue logo
imagepng(apply_watermark($company_logo,$logo_url,80,1,0,90));
//background(url/resource), watermarl(url), size percent, left0/right1, padding(px),rotate
function apply_watermark($bg,$wt,$p,$lr,$pad=0,$rt=false) {
//Load background image into memory,can apply more watermarks to same image
if (gettype($bg) == "resource") {
$background = $bg;
} else {
$background = imagecreatefromjpeg($bg);
}
//Get the width and height and generate watermark max size
$bx = imagesx($background);
$by = imagesy($background);
$overlay_max = (($bx > $by) ? $bx : $by) / 100 * $p;
//Create container for image
$imagecontainer = imagecreatetruecolor($bx,$by);
//Allow alpha channels to be saved and fill it with alpha
imagesavealpha($imagecontainer,true);
$alphacolor = imagecolorallocatealpha($imagecontainer,0,0,0,127);
imagefill($imagecontainer,0,0,$alphacolor);
//Copy background image into the container
imagecopyresampled($imagecontainer,$background,0,0,0,0,$bx,$by,$bx,$by);
//Load the watermark
$overlay = imagecreatefrompng($wt);
if($rt != false){$overlay = imagerotate($overlay,$rt,0);}
//get the watermark width and height and generate the aspect ratio
$ratio = $overlay_max / imagesx($overlay);
if ($ratio > ($bx / $by)) {
$scale = imagesx($overlay) / $bx;
} else {
$scale = imagesy($overlay) / $by;
}
$newwidth = (int)(imagesx($overlay) / $scale);
$newheight = (int)(imagesy($overlay) / $scale);
//Create container for the watermark and apply alpha to it
$newoverlay = imagecreatetruecolor($newwidth,$newheight);
imagesavealpha($newoverlay,true);
imagefill($newoverlay,0,0,$alphacolor);
//Copy the watermark to the watermark container with alpha
imagecopyresized($newoverlay, $overlay, 0, 0, 0, 0, $newwidth, $newheight, imagesx($overlay), imagesy($overlay));
//Copy the watermark to the background image container, choose left or right
if ($lr == 0) {
imagecopyresampled($imagecontainer,$newoverlay,0+$pad,($by-$newheight-$pad),0,0,$newwidth,$newheight,$newwidth,$newheight);
} elseif ($lr == 1) {
imagecopyresampled($imagecontainer,$newoverlay,($bx-$newwidth-$pad),($by-$newheight-$pad),0,0,$newwidth,$newheight,$newwidth,$newheight);
}
//Return the generated image back to the function call to further handle
return $imagecontainer;
}
?>

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.

php gd: when i crop images through php some images come out smushed

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.

Categories