I really don’t have a shorter description for this. I was working on a personal project the other day and realized that this might be a nifty function. Basically, you know all those snippets to make cropped thumbnails (squares and the like), and how most of them either center or crop to the top of an image. I wanted a new function that would crop to most any size I desired and any position on the image I desired without the need to change any code, only parameters. And thus img_resize_crop was born.
Function code is below, try out a demo at http://rrbits.com/resizer/ (Demo code is available here: http://rrbits.com/resizer.zip )
Right now it’s pure GD (uses a sharpening convolution matrix to get over GD’s resizing blurryness), though could probably be converted to ImageMagick by someone who knows more about ImageMagick than I. (Plus more patience, no desire to port it right now.)
<?php /** * img_resize_crop * Resizes an image to a specific size, cropping if necessary, allows center-weighting. * * @param Resource $src - GD Resource Image to use. * @param Integer $twidth - Thumbnail width * @param Integer $theight - Thumbnail height * @param Integer $center_x - The x value of the target center location, leaving it at -1 autocalculates. [Default: -1] * @param Integer $center_y - The y value of the target center location, leaving it at -1 autocalculates. [Default: -1] * @param String $method - Method to use for the resize. [Default:suggest] * 'suggest' (provided center coordinate is only guaranteed to be in the picture.) * 'force' (The provided coordinate is forced into being the center, additional data is trimmed to ensure this.) * 'onlycrop' (Not sure why you would use this, but only performs cropping.) * @param Boolean $sharpen - Specify whether or not to sharpen the resultant thumbnail [Default:true] * @param Int $evil_threshold - Maximum thumbnail width/height to prevent attempts at evil. [Default:1024] */ function img_resize_crop($src, $twidth, $theight, $center_x = -1, $center_y = -1, $method = 'suggest', $sharpen = true, $evil_threshold = 1024) { /*Set defaults if they are not provided.*/ if($center_x == -1 || ($method == 'force' && $center_x == 0)) { $center_x = floor(imagesx($src)/2); } if($center_y == -1 || ($method == 'force' && $center_y == 0)) { $center_y = floor(imagesy($src)/2); } /* Prevent evil */ if($twidth > $evil_threshold) $twidth = $evil_threshold; if($theight > $evil_threshold) $theight = $evil_threshold; /* The ratio of the thumbnail and the ratio of the original image.*/ $t_ratio = $twidth / $theight; $o_ratio = imagesx($src) / imagesy($src); $new = imagecreatetruecolor($twidth, $theight); /*Ideally, we'll want to grab as much of the source image as possible. So we need to figure out how much to grab based on the ratios of the desired thumbnail and the original image.*/ if($t_ratio > $o_ratio) { $i_width = imagesx($src); $i_height = floor($i_width / $t_ratio); } else { $i_height = imagesy($src); $i_width = floor($i_height * $t_ratio); } /*Calculate the upper-left corner of the source image grab area. These will be adjusted differently based on the method selected.*/ $s_x = $center_x - floor($i_width/2); $s_y = $center_y - floor($i_height/2); switch($method) { case 'onlycrop': $i_width = (imagesx($src) > $twidth) ? $twidth : imagesx($src); $i_height = (imagesy($src) > $theight) ? $theight : imagesy($src); $s_x = $center_x - floor($i_width/2); $s_y = $center_y - floor($i_height/2); /*Make sure we're inside the left and top boundaries.*/ $s_x = ($s_x < 0) ? 0 : $s_x; $s_y = ($s_y < 0) ? 0 : $s_y; /*Make sure we're inside the bottom and right boundaries.*/ $s_x = ($center_x + ceil($i_width/2) > imagesx($src)) ? imagesx($src) - $i_width : $s_x; $s_y = ($center_y + ceil($i_height/2) > imagesy($src)) ? imagesy($src) - $i_height : $s_y; break; default: case 'suggest': /*Condition: Crop is thinner (ratio-wise) than the original image.*/ if($t_ratio <= $o_ratio) { $s_y = 0; $s_x = ($s_x < 0) ? 0 : $s_x; $s_x = ($center_x + ceil($i_width/2) > imagesx($src)) ? imagesx($src) - $i_width : $s_x; } else /*Condition: Crop is wider (ratio-wise) than the original image.*/ { $s_x = 0; $s_y = ($s_y < 0) ? 0 : $s_y; $s_y = ($center_y + ceil($i_height/2) > imagesy($src)) ? imagesy($src) - $i_height : $s_y; } break; case 'force': /*Condition: Crop is thinner (ratio-wise) than the original image.*/ if($t_ratio <= $o_ratio) { /*Find the maximum possible height with the requested center_y.*/ $i_height = ($center_y > floor(imagesy($src)/2)) ? (imagesy($src) - $center_y) * 2 : $center_y * 2; $i_width = floor($i_height * $t_ratio); /*Height for said width.*/ /*If that puts the source box out of bounds, we'll need to proportionally scale down.*/ if($center_x - floor($i_width/2) < 0 || $center_x + floor($i_width/2) > imagesx($src)) { /*Minimum width.*/ $i_width = ($center_x > floor(imagesx($src)/2)) ? (imagesx($src) - $center_x) * 2 : $center_x * 2; $i_height = floor($i_width / $t_ratio); } /*Recalculate source x and y*/ $s_x = $center_x - floor($i_width/2); $s_y = $center_y - floor($i_height/2); } else /*Condition: Crop is wider (ratio-wise) than the original image.*/ { /*Find the maximum possible width with the requested center_x.*/ $i_width = ($center_x > floor(imagesx($src)/2)) ? (imagesx($src) - $center_x) * 2 : $center_x * 2; $i_height = floor($i_width / $t_ratio); /*Height for said width.*/ /*If that puts the source box out of bounds, we'll need to proportionally scale down.*/ if($center_y - floor($i_height/2) < 0 || $center_y + floor($i_height/2) > imagesy($src)) { /*Minimum height.*/ $i_height = ($center_y > floor(imagesy($src)/2)) ? (imagesy($src) - $center_y) * 2 : $center_y * 2; $i_width = $i_height * $t_ratio; } /*Recalculate source x and y*/ $s_x = $center_x - floor($i_width/2); $s_y = $center_y - floor($i_height/2); } break; } imagecopyresampled($new, $src, /*Destination Coords*/ 0,0, /*Source Coords*/ $s_x,$s_y, /*Destination Geometry*/ $twidth, $theight, /*Source Geometry*/ $i_width, $i_height ); if($sharpen) { $sharpen_matrix = array(array(-1,-1,-1),array(-1,16,-1),array(-1,-1,-1)); $divisor = 8; $offset = 0; imageconvolution($new, $sharpen_matrix, $divisor, $offset); } return $new; }
Related posts:
- PHP: Get zipcode for an Address I needed a small php function that could take an...
- Get the Bounding Box of an SVG Path There may be times you need to find the bounding...
Related posts brought to you by WordPress MU Related Posts Plugin.