View difference between Paste ID: uyqmG6vX and B4cHwm3Y
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
}