31 /** |
31 /** |
32 * Checks to see if current environment supports GD. |
32 * Checks to see if current environment supports GD. |
33 * |
33 * |
34 * @since 3.5.0 |
34 * @since 3.5.0 |
35 * |
35 * |
36 * @static |
|
37 * |
|
38 * @param array $args |
36 * @param array $args |
39 * @return bool |
37 * @return bool |
40 */ |
38 */ |
41 public static function test( $args = array() ) { |
39 public static function test( $args = array() ) { |
42 if ( ! extension_loaded('gd') || ! function_exists('gd_info') ) |
40 if ( ! extension_loaded( 'gd' ) || ! function_exists( 'gd_info' ) ) { |
43 return false; |
41 return false; |
|
42 } |
44 |
43 |
45 // On some setups GD library does not provide imagerotate() - Ticket #11536 |
44 // On some setups GD library does not provide imagerotate() - Ticket #11536 |
46 if ( isset( $args['methods'] ) && |
45 if ( isset( $args['methods'] ) && |
47 in_array( 'rotate', $args['methods'] ) && |
46 in_array( 'rotate', $args['methods'] ) && |
48 ! function_exists('imagerotate') ){ |
47 ! function_exists( 'imagerotate' ) ) { |
49 |
48 |
50 return false; |
49 return false; |
51 } |
50 } |
52 |
51 |
53 return true; |
52 return true; |
55 |
54 |
56 /** |
55 /** |
57 * Checks to see if editor supports the mime-type specified. |
56 * Checks to see if editor supports the mime-type specified. |
58 * |
57 * |
59 * @since 3.5.0 |
58 * @since 3.5.0 |
60 * |
|
61 * @static |
|
62 * |
59 * |
63 * @param string $mime_type |
60 * @param string $mime_type |
64 * @return bool |
61 * @return bool |
65 */ |
62 */ |
66 public static function supports_mime_type( $mime_type ) { |
63 public static function supports_mime_type( $mime_type ) { |
67 $image_types = imagetypes(); |
64 $image_types = imagetypes(); |
68 switch( $mime_type ) { |
65 switch ( $mime_type ) { |
69 case 'image/jpeg': |
66 case 'image/jpeg': |
70 return ($image_types & IMG_JPG) != 0; |
67 return ( $image_types & IMG_JPG ) != 0; |
71 case 'image/png': |
68 case 'image/png': |
72 return ($image_types & IMG_PNG) != 0; |
69 return ( $image_types & IMG_PNG ) != 0; |
73 case 'image/gif': |
70 case 'image/gif': |
74 return ($image_types & IMG_GIF) != 0; |
71 return ( $image_types & IMG_GIF ) != 0; |
75 } |
72 } |
76 |
73 |
77 return false; |
74 return false; |
78 } |
75 } |
79 |
76 |
83 * @since 3.5.0 |
80 * @since 3.5.0 |
84 * |
81 * |
85 * @return bool|WP_Error True if loaded successfully; WP_Error on failure. |
82 * @return bool|WP_Error True if loaded successfully; WP_Error on failure. |
86 */ |
83 */ |
87 public function load() { |
84 public function load() { |
88 if ( $this->image ) |
85 if ( $this->image ) { |
89 return true; |
86 return true; |
90 |
87 } |
91 if ( ! is_file( $this->file ) && ! preg_match( '|^https?://|', $this->file ) ) |
88 |
92 return new WP_Error( 'error_loading_image', __('File doesn’t exist?'), $this->file ); |
89 if ( ! is_file( $this->file ) && ! preg_match( '|^https?://|', $this->file ) ) { |
|
90 return new WP_Error( 'error_loading_image', __( 'File doesn’t exist?' ), $this->file ); |
|
91 } |
93 |
92 |
94 // Set artificially high because GD uses uncompressed images in memory. |
93 // Set artificially high because GD uses uncompressed images in memory. |
95 wp_raise_memory_limit( 'image' ); |
94 wp_raise_memory_limit( 'image' ); |
96 |
95 |
97 $this->image = @imagecreatefromstring( file_get_contents( $this->file ) ); |
96 $this->image = @imagecreatefromstring( file_get_contents( $this->file ) ); |
98 |
97 |
99 if ( ! is_resource( $this->image ) ) |
98 if ( ! is_resource( $this->image ) ) { |
100 return new WP_Error( 'invalid_image', __('File is not an image.'), $this->file ); |
99 return new WP_Error( 'invalid_image', __( 'File is not an image.' ), $this->file ); |
|
100 } |
101 |
101 |
102 $size = @getimagesize( $this->file ); |
102 $size = @getimagesize( $this->file ); |
103 if ( ! $size ) |
103 if ( ! $size ) { |
104 return new WP_Error( 'invalid_image', __('Could not read image size.'), $this->file ); |
104 return new WP_Error( 'invalid_image', __( 'Could not read image size.' ), $this->file ); |
|
105 } |
105 |
106 |
106 if ( function_exists( 'imagealphablending' ) && function_exists( 'imagesavealpha' ) ) { |
107 if ( function_exists( 'imagealphablending' ) && function_exists( 'imagesavealpha' ) ) { |
107 imagealphablending( $this->image, false ); |
108 imagealphablending( $this->image, false ); |
108 imagesavealpha( $this->image, true ); |
109 imagesavealpha( $this->image, true ); |
109 } |
110 } |
147 * @param int|null $max_h Image height. |
150 * @param int|null $max_h Image height. |
148 * @param bool $crop |
151 * @param bool $crop |
149 * @return true|WP_Error |
152 * @return true|WP_Error |
150 */ |
153 */ |
151 public function resize( $max_w, $max_h, $crop = false ) { |
154 public function resize( $max_w, $max_h, $crop = false ) { |
152 if ( ( $this->size['width'] == $max_w ) && ( $this->size['height'] == $max_h ) ) |
155 if ( ( $this->size['width'] == $max_w ) && ( $this->size['height'] == $max_h ) ) { |
153 return true; |
156 return true; |
|
157 } |
154 |
158 |
155 $resized = $this->_resize( $max_w, $max_h, $crop ); |
159 $resized = $this->_resize( $max_w, $max_h, $crop ); |
156 |
160 |
157 if ( is_resource( $resized ) ) { |
161 if ( is_resource( $resized ) ) { |
158 imagedestroy( $this->image ); |
162 imagedestroy( $this->image ); |
159 $this->image = $resized; |
163 $this->image = $resized; |
160 return true; |
164 return true; |
161 |
165 |
162 } elseif ( is_wp_error( $resized ) ) |
166 } elseif ( is_wp_error( $resized ) ) { |
163 return $resized; |
167 return $resized; |
164 |
168 } |
165 return new WP_Error( 'image_resize_error', __('Image resize failed.'), $this->file ); |
169 |
166 } |
170 return new WP_Error( 'image_resize_error', __( 'Image resize failed.' ), $this->file ); |
167 |
171 } |
168 /** |
172 |
169 * |
173 /** |
170 * @param int $max_w |
174 * @param int $max_w |
171 * @param int $max_h |
175 * @param int $max_h |
172 * @param bool|array $crop |
176 * @param bool|array $crop |
173 * @return resource|WP_Error |
177 * @return resource|WP_Error |
174 */ |
178 */ |
175 protected function _resize( $max_w, $max_h, $crop = false ) { |
179 protected function _resize( $max_w, $max_h, $crop = false ) { |
176 $dims = image_resize_dimensions( $this->size['width'], $this->size['height'], $max_w, $max_h, $crop ); |
180 $dims = image_resize_dimensions( $this->size['width'], $this->size['height'], $max_w, $max_h, $crop ); |
177 if ( ! $dims ) { |
181 if ( ! $dims ) { |
178 return new WP_Error( 'error_getting_dimensions', __('Could not calculate resized image dimensions'), $this->file ); |
182 return new WP_Error( 'error_getting_dimensions', __( 'Could not calculate resized image dimensions' ), $this->file ); |
179 } |
183 } |
180 list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dims; |
184 list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dims; |
181 |
185 |
182 $resized = wp_imagecreatetruecolor( $dst_w, $dst_h ); |
186 $resized = wp_imagecreatetruecolor( $dst_w, $dst_h ); |
183 imagecopyresampled( $resized, $this->image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ); |
187 imagecopyresampled( $resized, $this->image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ); |
230 |
234 |
231 if ( ! isset( $size_data['crop'] ) ) { |
235 if ( ! isset( $size_data['crop'] ) ) { |
232 $size_data['crop'] = false; |
236 $size_data['crop'] = false; |
233 } |
237 } |
234 |
238 |
235 $image = $this->_resize( $size_data['width'], $size_data['height'], $size_data['crop'] ); |
239 $image = $this->_resize( $size_data['width'], $size_data['height'], $size_data['crop'] ); |
236 $duplicate = ( ( $orig_size['width'] == $size_data['width'] ) && ( $orig_size['height'] == $size_data['height'] ) ); |
240 $duplicate = ( ( $orig_size['width'] == $size_data['width'] ) && ( $orig_size['height'] == $size_data['height'] ) ); |
237 |
241 |
238 if ( ! is_wp_error( $image ) && ! $duplicate ) { |
242 if ( ! is_wp_error( $image ) && ! $duplicate ) { |
239 $resized = $this->_save( $image ); |
243 $resized = $this->_save( $image ); |
240 |
244 |
241 imagedestroy( $image ); |
245 imagedestroy( $image ); |
242 |
246 |
243 if ( ! is_wp_error( $resized ) && $resized ) { |
247 if ( ! is_wp_error( $resized ) && $resized ) { |
244 unset( $resized['path'] ); |
248 unset( $resized['path'] ); |
245 $metadata[$size] = $resized; |
249 $metadata[ $size ] = $resized; |
246 } |
250 } |
247 } |
251 } |
248 |
252 |
249 $this->size = $orig_size; |
253 $this->size = $orig_size; |
250 } |
254 } |
267 * @return bool|WP_Error |
271 * @return bool|WP_Error |
268 */ |
272 */ |
269 public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ) { |
273 public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ) { |
270 // If destination width/height isn't specified, use same as |
274 // If destination width/height isn't specified, use same as |
271 // width/height from source. |
275 // width/height from source. |
272 if ( ! $dst_w ) |
276 if ( ! $dst_w ) { |
273 $dst_w = $src_w; |
277 $dst_w = $src_w; |
274 if ( ! $dst_h ) |
278 } |
|
279 if ( ! $dst_h ) { |
275 $dst_h = $src_h; |
280 $dst_h = $src_h; |
|
281 } |
276 |
282 |
277 $dst = wp_imagecreatetruecolor( $dst_w, $dst_h ); |
283 $dst = wp_imagecreatetruecolor( $dst_w, $dst_h ); |
278 |
284 |
279 if ( $src_abs ) { |
285 if ( $src_abs ) { |
280 $src_w -= $src_x; |
286 $src_w -= $src_x; |
281 $src_h -= $src_y; |
287 $src_h -= $src_y; |
282 } |
288 } |
283 |
289 |
284 if ( function_exists( 'imageantialias' ) ) |
290 if ( function_exists( 'imageantialias' ) ) { |
285 imageantialias( $dst, true ); |
291 imageantialias( $dst, true ); |
|
292 } |
286 |
293 |
287 imagecopyresampled( $dst, $this->image, 0, 0, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ); |
294 imagecopyresampled( $dst, $this->image, 0, 0, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ); |
288 |
295 |
289 if ( is_resource( $dst ) ) { |
296 if ( is_resource( $dst ) ) { |
290 imagedestroy( $this->image ); |
297 imagedestroy( $this->image ); |
291 $this->image = $dst; |
298 $this->image = $dst; |
292 $this->update_size(); |
299 $this->update_size(); |
293 return true; |
300 return true; |
294 } |
301 } |
295 |
302 |
296 return new WP_Error( 'image_crop_error', __('Image crop failed.'), $this->file ); |
303 return new WP_Error( 'image_crop_error', __( 'Image crop failed.' ), $this->file ); |
297 } |
304 } |
298 |
305 |
299 /** |
306 /** |
300 * Rotates current image counter-clockwise by $angle. |
307 * Rotates current image counter-clockwise by $angle. |
301 * Ported from image-edit.php |
308 * Ported from image-edit.php |
304 * |
311 * |
305 * @param float $angle |
312 * @param float $angle |
306 * @return true|WP_Error |
313 * @return true|WP_Error |
307 */ |
314 */ |
308 public function rotate( $angle ) { |
315 public function rotate( $angle ) { |
309 if ( function_exists('imagerotate') ) { |
316 if ( function_exists( 'imagerotate' ) ) { |
310 $transparency = imagecolorallocatealpha( $this->image, 255, 255, 255, 127 ); |
317 $transparency = imagecolorallocatealpha( $this->image, 255, 255, 255, 127 ); |
311 $rotated = imagerotate( $this->image, $angle, $transparency ); |
318 $rotated = imagerotate( $this->image, $angle, $transparency ); |
312 |
319 |
313 if ( is_resource( $rotated ) ) { |
320 if ( is_resource( $rotated ) ) { |
314 imagealphablending( $rotated, true ); |
321 imagealphablending( $rotated, true ); |
315 imagesavealpha( $rotated, true ); |
322 imagesavealpha( $rotated, true ); |
316 imagedestroy( $this->image ); |
323 imagedestroy( $this->image ); |
317 $this->image = $rotated; |
324 $this->image = $rotated; |
318 $this->update_size(); |
325 $this->update_size(); |
319 return true; |
326 return true; |
320 } |
327 } |
321 } |
328 } |
322 return new WP_Error( 'image_rotate_error', __('Image rotate failed.'), $this->file ); |
329 return new WP_Error( 'image_rotate_error', __( 'Image rotate failed.' ), $this->file ); |
323 } |
330 } |
324 |
331 |
325 /** |
332 /** |
326 * Flips current image. |
333 * Flips current image. |
327 * |
334 * |
328 * @since 3.5.0 |
335 * @since 3.5.0 |
329 * |
336 * |
330 * @param bool $horz Flip along Horizontal Axis |
337 * @param bool $horz Flip along Horizontal Axis. |
331 * @param bool $vert Flip along Vertical Axis |
338 * @param bool $vert Flip along Vertical Axis. |
332 * @return true|WP_Error |
339 * @return true|WP_Error |
333 */ |
340 */ |
334 public function flip( $horz, $vert ) { |
341 public function flip( $horz, $vert ) { |
335 $w = $this->size['width']; |
342 $w = $this->size['width']; |
336 $h = $this->size['height']; |
343 $h = $this->size['height']; |
337 $dst = wp_imagecreatetruecolor( $w, $h ); |
344 $dst = wp_imagecreatetruecolor( $w, $h ); |
338 |
345 |
339 if ( is_resource( $dst ) ) { |
346 if ( is_resource( $dst ) ) { |
340 $sx = $vert ? ($w - 1) : 0; |
347 $sx = $vert ? ( $w - 1 ) : 0; |
341 $sy = $horz ? ($h - 1) : 0; |
348 $sy = $horz ? ( $h - 1 ) : 0; |
342 $sw = $vert ? -$w : $w; |
349 $sw = $vert ? -$w : $w; |
343 $sh = $horz ? -$h : $h; |
350 $sh = $horz ? -$h : $h; |
344 |
351 |
345 if ( imagecopyresampled( $dst, $this->image, 0, 0, $sx, $sy, $w, $h, $sw, $sh ) ) { |
352 if ( imagecopyresampled( $dst, $this->image, 0, 0, $sx, $sy, $w, $h, $sw, $sh ) ) { |
346 imagedestroy( $this->image ); |
353 imagedestroy( $this->image ); |
347 $this->image = $dst; |
354 $this->image = $dst; |
348 return true; |
355 return true; |
349 } |
356 } |
350 } |
357 } |
351 return new WP_Error( 'image_flip_error', __('Image flip failed.'), $this->file ); |
358 return new WP_Error( 'image_flip_error', __( 'Image flip failed.' ), $this->file ); |
352 } |
359 } |
353 |
360 |
354 /** |
361 /** |
355 * Saves current in-memory image to file. |
362 * Saves current in-memory image to file. |
356 * |
363 * |
378 * @return WP_Error|array |
385 * @return WP_Error|array |
379 */ |
386 */ |
380 protected function _save( $image, $filename = null, $mime_type = null ) { |
387 protected function _save( $image, $filename = null, $mime_type = null ) { |
381 list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type ); |
388 list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type ); |
382 |
389 |
383 if ( ! $filename ) |
390 if ( ! $filename ) { |
384 $filename = $this->generate_filename( null, null, $extension ); |
391 $filename = $this->generate_filename( null, null, $extension ); |
|
392 } |
385 |
393 |
386 if ( 'image/gif' == $mime_type ) { |
394 if ( 'image/gif' == $mime_type ) { |
387 if ( ! $this->make_image( $filename, 'imagegif', array( $image, $filename ) ) ) |
395 if ( ! $this->make_image( $filename, 'imagegif', array( $image, $filename ) ) ) { |
388 return new WP_Error( 'image_save_error', __('Image Editor Save Failed') ); |
396 return new WP_Error( 'image_save_error', __( 'Image Editor Save Failed' ) ); |
389 } |
397 } |
390 elseif ( 'image/png' == $mime_type ) { |
398 } elseif ( 'image/png' == $mime_type ) { |
391 // convert from full colors to index colors, like original PNG. |
399 // convert from full colors to index colors, like original PNG. |
392 if ( function_exists('imageistruecolor') && ! imageistruecolor( $image ) ) |
400 if ( function_exists( 'imageistruecolor' ) && ! imageistruecolor( $image ) ) { |
393 imagetruecolortopalette( $image, false, imagecolorstotal( $image ) ); |
401 imagetruecolortopalette( $image, false, imagecolorstotal( $image ) ); |
394 |
402 } |
395 if ( ! $this->make_image( $filename, 'imagepng', array( $image, $filename ) ) ) |
403 |
396 return new WP_Error( 'image_save_error', __('Image Editor Save Failed') ); |
404 if ( ! $this->make_image( $filename, 'imagepng', array( $image, $filename ) ) ) { |
397 } |
405 return new WP_Error( 'image_save_error', __( 'Image Editor Save Failed' ) ); |
398 elseif ( 'image/jpeg' == $mime_type ) { |
406 } |
399 if ( ! $this->make_image( $filename, 'imagejpeg', array( $image, $filename, $this->get_quality() ) ) ) |
407 } elseif ( 'image/jpeg' == $mime_type ) { |
400 return new WP_Error( 'image_save_error', __('Image Editor Save Failed') ); |
408 if ( ! $this->make_image( $filename, 'imagejpeg', array( $image, $filename, $this->get_quality() ) ) ) { |
401 } |
409 return new WP_Error( 'image_save_error', __( 'Image Editor Save Failed' ) ); |
402 else { |
410 } |
403 return new WP_Error( 'image_save_error', __('Image Editor Save Failed') ); |
411 } else { |
|
412 return new WP_Error( 'image_save_error', __( 'Image Editor Save Failed' ) ); |
404 } |
413 } |
405 |
414 |
406 // Set correct file permissions |
415 // Set correct file permissions |
407 $stat = stat( dirname( $filename ) ); |
416 $stat = stat( dirname( $filename ) ); |
408 $perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits |
417 $perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits |
409 @ chmod( $filename, $perms ); |
418 @ chmod( $filename, $perms ); |
410 |
419 |
411 /** |
420 /** |
412 * Filters the name of the saved image file. |
421 * Filters the name of the saved image file. |