SHOW:
|
|
- or go back to the newest paste.
| 1 | <?php | |
| 2 | - | /* Original code from: |
| 2 | + | /* |
| 3 | - | * http://bradt.ca/archives/image-crop-position-in-wordpress/ |
| 3 | + | |
| 4 | * | |
| 5 | - | * Modified to WordPress Answers: |
| 5 | + | |
| 6 | - | * http://wordpress.stackexchange.com/q/51920/12615 |
| 6 | + | |
| 7 | */ | |
| 8 | - | * Check the function bt_image_make_intermediate_size |
| 8 | + | |
| 9 | - | * That's where the Thumbnails renaming occurs and all added images must be inserted |
| 9 | + | |
| 10 | * bt_add_image_size( 'product-screenshot', 300, 300, array( 'left', 'top' ) ); | |
| 11 | * bt_add_image_size( 'product-feature', 460, 345, array( 'center', 'top' ) ); | |
| 12 | */ | |
| 13 | ||
| 14 | add_filter( 'intermediate_image_sizes_advanced', 'bt_intermediate_image_sizes_advanced' ); | |
| 15 | add_filter( 'wp_generate_attachment_metadata', 'bt_generate_attachment_metadata', 10, 2 ); | |
| 16 | ||
| 17 | /** | |
| 18 | * Registers a new image size with cropping positions | |
| 19 | * | |
| 20 | * The $crop parameter works as in the 'add_image_size' function taking true or | |
| 21 | * false values. If set to true, the default cropping position is 'center', 'center'. | |
| 22 | * | |
| 23 | * The $crop parameter also takes an array of the format | |
| 24 | * array( x_crop_position, y_crop_position ) | |
| 25 | * x_crop_position can be 'left', 'center', 'right' | |
| 26 | * y_crop_position can be 'top', 'center', 'bottom' | |
| 27 | * | |
| 28 | * @param string $name Image size identifier. | |
| 29 | * @param int $width Image width. | |
| 30 | * @param int $height Image height. | |
| 31 | * @param bool|array $crop Optional, default is false. Whether to crop image to specified height and width or resize. An array can specify positioning of the crop area. | |
| 32 | * @return bool|array False, if no image was created. Metadata array on success. | |
| 33 | */ | |
| 34 | function bt_add_image_size( $name, $width = 0, $height = 0, $crop = false ) {
| |
| 35 | global $_wp_additional_image_sizes; | |
| 36 | $_wp_additional_image_sizes[$name] = array( 'width' => absint( $width ), 'height' => absint( $height ), 'crop' => $crop ); | |
| 37 | } | |
| 38 | ||
| 39 | ||
| 40 | /** | |
| 41 | * Returning no sizes (an empty array) will force | |
| 42 | * wp_generate_attachment_metadata to skip creating intermediate image sizes on | |
| 43 | * upload, then we can run our own resizing functions by hooking into the | |
| 44 | * 'wp_generate_attachment_metadata' filter | |
| 45 | */ | |
| 46 | function bt_intermediate_image_sizes_advanced( $sizes ) {
| |
| 47 | return array(); | |
| 48 | } | |
| 49 | ||
| 50 | ||
| 51 | function bt_generate_attachment_metadata( $metadata, $attachment_id ) {
| |
| 52 | $attachment = get_post( $attachment_id ); | |
| 53 | ||
| 54 | $uploadPath = wp_upload_dir(); | |
| 55 | $file = path_join($uploadPath['basedir'], $metadata['file']); | |
| 56 | ||
| 57 | if ( !preg_match('!^image/!', get_post_mime_type( $attachment )) || !file_is_displayable_image( $file ) ) return $metadata;
| |
| 58 | ||
| 59 | global $_wp_additional_image_sizes; | |
| 60 | ||
| 61 | foreach ( get_intermediate_image_sizes() as $s ) {
| |
| 62 | $sizes[$s] = array( 'width' => '', 'height' => '', 'crop' => FALSE ); | |
| 63 | if ( isset( $_wp_additional_image_sizes[$s]['width'] ) ) | |
| 64 | $sizes[$s]['width'] = intval( $_wp_additional_image_sizes[$s]['width'] ); // For theme-added sizes | |
| 65 | else | |
| 66 | $sizes[$s]['width'] = get_option( "{$s}_size_w" ); // For default sizes set in options
| |
| 67 | if ( isset( $_wp_additional_image_sizes[$s]['height'] ) ) | |
| 68 | $sizes[$s]['height'] = intval( $_wp_additional_image_sizes[$s]['height'] ); // For theme-added sizes | |
| 69 | else | |
| 70 | $sizes[$s]['height'] = get_option( "{$s}_size_h" ); // For default sizes set in options
| |
| 71 | if ( isset( $_wp_additional_image_sizes[$s]['crop'] ) ) | |
| 72 | $sizes[$s]['crop'] = $_wp_additional_image_sizes[$s]['crop']; | |
| 73 | else | |
| 74 | $sizes[$s]['crop'] = get_option( "{$s}_crop" );
| |
| 75 | } | |
| 76 | ||
| 77 | foreach ( $sizes as $size => $size_data ) {
| |
| 78 | $resized = bt_image_make_intermediate_size( $file, $size_data['width'], $size_data['height'], $size_data['crop'] ); | |
| 79 | if ( $resized ) | |
| 80 | - | $resized = bt_image_make_intermediate_size( $file, $size_data['width'], $size_data['height'], $size_data['crop'], $size ); |
| 80 | + | |
| 81 | } | |
| 82 | ||
| 83 | return $metadata; | |
| 84 | } | |
| 85 | ||
| 86 | ||
| 87 | /** | |
| 88 | * Resize an image to make a thumbnail or intermediate size. | |
| 89 | * | |
| 90 | * The returned array has the file size, the image width, and image height. The | |
| 91 | * filter 'image_make_intermediate_size' can be used to hook in and change the | |
| 92 | * values of the returned array. The only parameter is the resized file path. | |
| 93 | * | |
| 94 | * @param string $file File path. | |
| 95 | * @param int $width Image width. | |
| 96 | * @param int $height Image height. | |
| 97 | * @param bool|array $crop Optional, default is false. Whether to crop image to specified height and width or resize. An array can specify positioning of the crop area. | |
| 98 | * @return bool|array False, if no image was created. Metadata array on success. | |
| 99 | */ | |
| 100 | function bt_image_make_intermediate_size( $file, $width, $height, $crop = false ) {
| |
| 101 | if ( $width || $height ) {
| |
| 102 | - | function bt_image_make_intermediate_size( $file, $width, $height, $crop = false, $size ) {
|
| 102 | + | $resized_file = bt_image_resize( $file, $width, $height, $crop, null, null, 90 ); |
| 103 | if ( !is_wp_error( $resized_file ) && $resized_file && $info = getimagesize( $resized_file ) ) {
| |
| 104 | - | switch($size) {
|
| 104 | + | |
| 105 | - | case 'thumbnail': |
| 105 | + | |
| 106 | - | $suffix = 't'; |
| 106 | + | |
| 107 | - | break; |
| 107 | + | |
| 108 | - | case 'medium': |
| 108 | + | |
| 109 | - | $suffix = 'm'; |
| 109 | + | |
| 110 | - | break; |
| 110 | + | |
| 111 | - | case 'large': |
| 111 | + | |
| 112 | - | $suffix = 'l'; |
| 112 | + | |
| 113 | - | break; |
| 113 | + | |
| 114 | - | default: |
| 114 | + | |
| 115 | - | $suffix = null; |
| 115 | + | |
| 116 | - | break; |
| 116 | + | |
| 117 | /** | |
| 118 | - | $resized_file = bt_image_resize( $file, $width, $height, $crop, $suffix, null, 90 ); |
| 118 | + | |
| 119 | * | |
| 120 | * Calculate dimensions and coordinates for a resized image that fits within a | |
| 121 | * specified width and height. If $crop is true, the largest matching central | |
| 122 | * portion of the image will be cropped out and resized to the required size. | |
| 123 | * | |
| 124 | * @param int $orig_w Original width. | |
| 125 | * @param int $orig_h Original height. | |
| 126 | * @param int $dest_w New width. | |
| 127 | * @param int $dest_h New height. | |
| 128 | * @param bool $crop Optional, default is false. Whether to crop image or resize. | |
| 129 | * @return bool|array False, on failure. Returned array matches parameters for imagecopyresampled() PHP function. | |
| 130 | */ | |
| 131 | function bt_image_resize_dimensions($orig_w, $orig_h, $dest_w, $dest_h, $crop = false) {
| |
| 132 | ||
| 133 | if ($orig_w <= 0 || $orig_h <= 0) | |
| 134 | return false; | |
| 135 | // at least one of dest_w or dest_h must be specific | |
| 136 | if ($dest_w <= 0 && $dest_h <= 0) | |
| 137 | return false; | |
| 138 | ||
| 139 | if ( $crop ) {
| |
| 140 | // crop the largest possible portion of the original image that we can size to $dest_w x $dest_h | |
| 141 | $aspect_ratio = $orig_w / $orig_h; | |
| 142 | $new_w = min($dest_w, $orig_w); | |
| 143 | $new_h = min($dest_h, $orig_h); | |
| 144 | ||
| 145 | if ( !$new_w ) {
| |
| 146 | $new_w = intval($new_h * $aspect_ratio); | |
| 147 | } | |
| 148 | ||
| 149 | if ( !$new_h ) {
| |
| 150 | $new_h = intval($new_w / $aspect_ratio); | |
| 151 | } | |
| 152 | ||
| 153 | $size_ratio = max($new_w / $orig_w, $new_h / $orig_h); | |
| 154 | ||
| 155 | $crop_w = round($new_w / $size_ratio); | |
| 156 | $crop_h = round($new_h / $size_ratio); | |
| 157 | ||
| 158 | if ( !is_array( $crop ) || count( $crop ) != 2 ) {
| |
| 159 | $crop = apply_filters( 'image_resize_crop_default', array( 'center', 'center' ) ); | |
| 160 | } | |
| 161 | ||
| 162 | switch ( $crop[0] ) {
| |
| 163 | case 'left': $s_x = 0; break; | |
| 164 | case 'right': $s_x = $orig_w - $crop_w; break; | |
| 165 | default: $s_x = floor( ( $orig_w - $crop_w ) / 2 ); | |
| 166 | } | |
| 167 | ||
| 168 | switch ( $crop[1] ) {
| |
| 169 | case 'top': $s_y = 0; break; | |
| 170 | case 'bottom': $s_y = $orig_h - $crop_h; break; | |
| 171 | default: $s_y = floor( ( $orig_h - $crop_h ) / 2 ); | |
| 172 | } | |
| 173 | } else {
| |
| 174 | // don't crop, just resize using $dest_w x $dest_h as a maximum bounding box | |
| 175 | $crop_w = $orig_w; | |
| 176 | $crop_h = $orig_h; | |
| 177 | ||
| 178 | $s_x = 0; | |
| 179 | $s_y = 0; | |
| 180 | ||
| 181 | list( $new_w, $new_h ) = wp_constrain_dimensions( $orig_w, $orig_h, $dest_w, $dest_h ); | |
| 182 | } | |
| 183 | ||
| 184 | // if the resulting image would be the same size or larger we don't want to resize it | |
| 185 | if ( $new_w >= $orig_w && $new_h >= $orig_h ) | |
| 186 | return false; | |
| 187 | ||
| 188 | // the return array matches the parameters to imagecopyresampled() | |
| 189 | // int dst_x, int dst_y, int src_x, int src_y, int dst_w, int dst_h, int src_w, int src_h | |
| 190 | return array( 0, 0, (int) $s_x, (int) $s_y, (int) $new_w, (int) $new_h, (int) $crop_w, (int) $crop_h ); | |
| 191 | ||
| 192 | } | |
| 193 | ||
| 194 | ||
| 195 | /** | |
| 196 | * Scale down an image to fit a particular size and save a new copy of the image. | |
| 197 | * | |
| 198 | * The PNG transparency will be preserved using the function, as well as the | |
| 199 | * image type. If the file going in is PNG, then the resized image is going to | |
| 200 | * be PNG. The only supported image types are PNG, GIF, and JPEG. | |
| 201 | * | |
| 202 | * Some functionality requires API to exist, so some PHP version may lose out | |
| 203 | * support. This is not the fault of WordPress (where functionality is | |
| 204 | * downgraded, not actual defects), but of your PHP version. | |
| 205 | * | |
| 206 | * @since 2.5.0 | |
| 207 | * | |
| 208 | * @param string $file Image file path. | |
| 209 | * @param int $max_w Maximum width to resize to. | |
| 210 | * @param int $max_h Maximum height to resize to. | |
| 211 | * @param bool $crop Optional. Whether to crop image or resize. | |
| 212 | * @param string $suffix Optional. File Suffix. | |
| 213 | * @param string $dest_path Optional. New image file path. | |
| 214 | * @param int $jpeg_quality Optional, default is 90. Image quality percentage. | |
| 215 | * @return mixed WP_Error on failure. String with new destination path. | |
| 216 | */ | |
| 217 | function bt_image_resize( $file, $max_w, $max_h, $crop = false, $suffix = null, $dest_path = null, $jpeg_quality = 90 ) {
| |
| 218 | ||
| 219 | $image = wp_load_image( $file ); | |
| 220 | if ( !is_resource( $image ) ) | |
| 221 | return new WP_Error( 'error_loading_image', $image, $file ); | |
| 222 | ||
| 223 | $size = @getimagesize( $file ); | |
| 224 | if ( !$size ) | |
| 225 | return new WP_Error('invalid_image', __('Could not read image size'), $file);
| |
| 226 | list($orig_w, $orig_h, $orig_type) = $size; | |
| 227 | ||
| 228 | // Rotate if EXIF 'Orientation' is set | |
| 229 | // This code is from the reverted patch at | |
| 230 | // http://core.trac.wordpress.org/changeset/11746/trunk/wp-includes/media.php | |
| 231 | $rotate = false; | |
| 232 | if ( is_callable( 'exif_read_data' ) && in_array( $orig_type, apply_filters( 'wp_read_image_metadata_types', array( IMAGETYPE_JPEG, IMAGETYPE_TIFF_II, IMAGETYPE_TIFF_MM ) ) ) ) {
| |
| 233 | $exif = @exif_read_data( $file, null, true ); | |
| 234 | if ( $exif && isset( $exif['IFD0'] ) && is_array( $exif['IFD0'] ) && isset( $exif['IFD0']['Orientation'] ) ) {
| |
| 235 | if ( 6 == $exif['IFD0']['Orientation'] ) | |
| 236 | $rotate = 90; | |
| 237 | elseif ( 8 == $exif['IFD0']['Orientation'] ) | |
| 238 | $rotate = 270; | |
| 239 | } | |
| 240 | } | |
| 241 | ||
| 242 | if ( $rotate ) | |
| 243 | list($max_h,$max_w) = array($max_w,$max_h); | |
| 244 | ||
| 245 | $dims = bt_image_resize_dimensions($orig_w, $orig_h, $max_w, $max_h, $crop); | |
| 246 | if ( !$dims ) | |
| 247 | return new WP_Error( 'error_getting_dimensions', __('Could not calculate resized image dimensions') );
| |
| 248 | list($dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) = $dims; | |
| 249 | ||
| 250 | $newimage = wp_imagecreatetruecolor( $dst_w, $dst_h ); | |
| 251 | ||
| 252 | if ( $rotate ) | |
| 253 | list($src_y,$src_x) = array($src_x,$src_y); | |
| 254 | ||
| 255 | imagecopyresampled( $newimage, $image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h); | |
| 256 | ||
| 257 | // convert from full colors to index colors, like original PNG. | |
| 258 | if ( IMAGETYPE_PNG == $orig_type && function_exists('imageistruecolor') && !imageistruecolor( $image ) )
| |
| 259 | imagetruecolortopalette( $newimage, false, imagecolorstotal( $image ) ); | |
| 260 | ||
| 261 | // we don't need the original in memory anymore | |
| 262 | imagedestroy( $image ); | |
| 263 | ||
| 264 | // $suffix will be appended to the destination filename, just before the extension | |
| 265 | if ( !$suffix ) {
| |
| 266 | if ( $rotate ) | |
| 267 | $suffix = "{$dst_h}x{$dst_w}";
| |
| 268 | else | |
| 269 | $suffix = "{$dst_w}x{$dst_h}";
| |
| 270 | } | |
| 271 | ||
| 272 | $info = pathinfo($file); | |
| 273 | $dir = $info['dirname']; | |
| 274 | $ext = $info['extension']; | |
| 275 | $name = wp_basename($file, ".$ext"); | |
| 276 | ||
| 277 | if ( !is_null($dest_path) and $_dest_path = realpath($dest_path) ) | |
| 278 | $dir = $_dest_path; | |
| 279 | $destfilename = "{$dir}/{$name}-{$suffix}.{$ext}";
| |
| 280 | ||
| 281 | if ( IMAGETYPE_GIF == $orig_type ) {
| |
| 282 | if ( !imagegif( $newimage, $destfilename ) ) | |
| 283 | return new WP_Error('resize_path_invalid', __( 'Resize path invalid' ));
| |
| 284 | } elseif ( IMAGETYPE_PNG == $orig_type ) {
| |
| 285 | if ( !imagepng( $newimage, $destfilename ) ) | |
| 286 | return new WP_Error('resize_path_invalid', __( 'Resize path invalid' ));
| |
| 287 | } else {
| |
| 288 | if ( $rotate ) {
| |
| 289 | $newimage = _rotate_image_resource( $newimage, 360 - $rotate ); | |
| 290 | } | |
| 291 | ||
| 292 | // all other formats are converted to jpg | |
| 293 | $destfilename = "{$dir}/{$name}-{$suffix}.jpg";
| |
| 294 | $return = imagejpeg( $newimage, $destfilename, apply_filters( 'jpeg_quality', $jpeg_quality, 'image_resize' ) ); | |
| 295 | if ( !$return ) | |
| 296 | return new WP_Error('resize_path_invalid', __( 'Resize path invalid' ));
| |
| 297 | } | |
| 298 | ||
| 299 | imagedestroy( $newimage ); | |
| 300 | ||
| 301 | // Set correct file permissions | |
| 302 | $stat = stat( dirname( $destfilename )); | |
| 303 | $perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits | |
| 304 | @ chmod( $destfilename, $perms ); | |
| 305 | ||
| 306 | return $destfilename; | |
| 307 | } |