13 * @package WordPress |
13 * @package WordPress |
14 * @subpackage Image_Editor |
14 * @subpackage Image_Editor |
15 * @uses WP_Image_Editor Extends class |
15 * @uses WP_Image_Editor Extends class |
16 */ |
16 */ |
17 class WP_Image_Editor_Imagick extends WP_Image_Editor { |
17 class WP_Image_Editor_Imagick extends WP_Image_Editor { |
18 |
18 /** |
19 protected $image = null; // Imagick Object |
19 * @var Imagick |
20 |
20 */ |
21 function __destruct() { |
21 protected $image; // Imagick Object |
|
22 |
|
23 public function __destruct() { |
22 if ( $this->image instanceof Imagick ) { |
24 if ( $this->image instanceof Imagick ) { |
23 // we don't need the original in memory anymore |
25 // we don't need the original in memory anymore |
24 $this->image->clear(); |
26 $this->image->clear(); |
25 $this->image->destroy(); |
27 $this->image->destroy(); |
26 } |
28 } |
117 return true; |
119 return true; |
118 |
120 |
119 if ( ! is_file( $this->file ) && ! preg_match( '|^https?://|', $this->file ) ) |
121 if ( ! is_file( $this->file ) && ! preg_match( '|^https?://|', $this->file ) ) |
120 return new WP_Error( 'error_loading_image', __('File doesn’t exist?'), $this->file ); |
122 return new WP_Error( 'error_loading_image', __('File doesn’t exist?'), $this->file ); |
121 |
123 |
|
124 /** This filter is documented in wp-includes/class-wp-image-editor-imagick.php */ |
122 // Even though Imagick uses less PHP memory than GD, set higher limit for users that have low PHP.ini limits |
125 // Even though Imagick uses less PHP memory than GD, set higher limit for users that have low PHP.ini limits |
123 @ini_set( 'memory_limit', apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT ) ); |
126 @ini_set( 'memory_limit', apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT ) ); |
124 |
127 |
125 try { |
128 try { |
126 $this->image = new Imagick( $this->file ); |
129 $this->image = new Imagick( $this->file ); |
137 catch ( Exception $e ) { |
140 catch ( Exception $e ) { |
138 return new WP_Error( 'invalid_image', $e->getMessage(), $this->file ); |
141 return new WP_Error( 'invalid_image', $e->getMessage(), $this->file ); |
139 } |
142 } |
140 |
143 |
141 $updated_size = $this->update_size(); |
144 $updated_size = $this->update_size(); |
142 if ( is_wp_error( $updated_size ) ) |
145 if ( is_wp_error( $updated_size ) ) { |
143 return $updated_size; |
146 return $updated_size; |
|
147 } |
144 |
148 |
145 return $this->set_quality(); |
149 return $this->set_quality(); |
146 } |
150 } |
147 |
151 |
148 /** |
152 /** |
150 * |
154 * |
151 * @since 3.5.0 |
155 * @since 3.5.0 |
152 * @access public |
156 * @access public |
153 * |
157 * |
154 * @param int $quality Compression Quality. Range: [1,100] |
158 * @param int $quality Compression Quality. Range: [1,100] |
155 * @return boolean|WP_Error |
159 * @return boolean|WP_Error True if set successfully; WP_Error on failure. |
156 */ |
160 */ |
157 public function set_quality( $quality = null ) { |
161 public function set_quality( $quality = null ) { |
158 if ( !$quality ) |
162 $quality_result = parent::set_quality( $quality ); |
159 $quality = $this->quality; |
163 if ( is_wp_error( $quality_result ) ) { |
160 |
164 return $quality_result; |
161 try { |
165 } else { |
162 if( 'image/jpeg' == $this->mime_type ) { |
166 $quality = $this->get_quality(); |
163 $this->image->setImageCompressionQuality( apply_filters( 'jpeg_quality', $quality, 'image_resize' ) ); |
167 } |
|
168 |
|
169 try { |
|
170 if ( 'image/jpeg' == $this->mime_type ) { |
|
171 $this->image->setImageCompressionQuality( $quality ); |
164 $this->image->setImageCompression( imagick::COMPRESSION_JPEG ); |
172 $this->image->setImageCompression( imagick::COMPRESSION_JPEG ); |
165 } |
173 } |
166 else { |
174 else { |
167 $this->image->setImageCompressionQuality( $quality ); |
175 $this->image->setImageCompressionQuality( $quality ); |
168 } |
176 } |
169 } |
177 } |
170 catch ( Exception $e ) { |
178 catch ( Exception $e ) { |
171 return new WP_Error( 'image_quality_error', $e->getMessage() ); |
179 return new WP_Error( 'image_quality_error', $e->getMessage() ); |
172 } |
180 } |
173 |
181 |
174 return parent::set_quality( $quality ); |
182 return true; |
175 } |
183 } |
176 |
184 |
177 /** |
185 /** |
178 * Sets or updates current image size. |
186 * Sets or updates current image size. |
179 * |
187 * |
180 * @since 3.5.0 |
188 * @since 3.5.0 |
181 * @access protected |
189 * @access protected |
182 * |
190 * |
183 * @param int $width |
191 * @param int $width |
184 * @param int $height |
192 * @param int $height |
|
193 * |
|
194 * @return true|WP_Error |
185 */ |
195 */ |
186 protected function update_size( $width = null, $height = null ) { |
196 protected function update_size( $width = null, $height = null ) { |
187 $size = null; |
197 $size = null; |
188 if ( !$width || !$height ) { |
198 if ( !$width || !$height ) { |
189 try { |
199 try { |
204 } |
214 } |
205 |
215 |
206 /** |
216 /** |
207 * Resizes current image. |
217 * Resizes current image. |
208 * |
218 * |
209 * @since 3.5.0 |
219 * At minimum, either a height or width must be provided. |
210 * @access public |
220 * If one of the two is set to null, the resize will |
211 * |
221 * maintain aspect ratio according to the provided dimension. |
212 * @param int $max_w |
222 * |
213 * @param int $max_h |
223 * @since 3.5.0 |
214 * @param boolean $crop |
224 * @access public |
|
225 * |
|
226 * @param int|null $max_w Image width. |
|
227 * @param int|null $max_h Image height. |
|
228 * @param boolean $crop |
215 * @return boolean|WP_Error |
229 * @return boolean|WP_Error |
216 */ |
230 */ |
217 public function resize( $max_w, $max_h, $crop = false ) { |
231 public function resize( $max_w, $max_h, $crop = false ) { |
218 if ( ( $this->size['width'] == $max_w ) && ( $this->size['height'] == $max_h ) ) |
232 if ( ( $this->size['width'] == $max_w ) && ( $this->size['height'] == $max_h ) ) |
219 return true; |
233 return true; |
248 * @access public |
262 * @access public |
249 * |
263 * |
250 * @param array $sizes { |
264 * @param array $sizes { |
251 * An array of image size arrays. Default sizes are 'small', 'medium', 'large'. |
265 * An array of image size arrays. Default sizes are 'small', 'medium', 'large'. |
252 * |
266 * |
|
267 * Either a height or width must be provided. |
|
268 * If one of the two is set to null, the resize will |
|
269 * maintain aspect ratio according to the provided dimension. |
|
270 * |
253 * @type array $size { |
271 * @type array $size { |
254 * @type int $width Image width. |
272 * @type int ['width'] Optional. Image width. |
255 * @type int $height Image height. |
273 * @type int ['height'] Optional. Image height. |
256 * @type bool $crop Optional. Whether to crop the image. Default false. |
274 * @type bool $crop Optional. Whether to crop the image. Default false. |
257 * } |
275 * } |
258 * } |
276 * } |
259 * @return array An array of resized images metadata by size. |
277 * @return array An array of resized images' metadata by size. |
260 */ |
278 */ |
261 public function multi_resize( $sizes ) { |
279 public function multi_resize( $sizes ) { |
262 $metadata = array(); |
280 $metadata = array(); |
263 $orig_size = $this->size; |
281 $orig_size = $this->size; |
264 $orig_image = $this->image->getImage(); |
282 $orig_image = $this->image->getImage(); |
265 |
283 |
266 foreach ( $sizes as $size => $size_data ) { |
284 foreach ( $sizes as $size => $size_data ) { |
267 if ( ! $this->image ) |
285 if ( ! $this->image ) |
268 $this->image = $orig_image->getImage(); |
286 $this->image = $orig_image->getImage(); |
269 |
287 |
270 if ( ! ( isset( $size_data['width'] ) && isset( $size_data['height'] ) ) ) |
288 if ( ! isset( $size_data['width'] ) && ! isset( $size_data['height'] ) ) { |
271 continue; |
289 continue; |
272 |
290 } |
273 if ( ! isset( $size_data['crop'] ) ) |
291 |
|
292 if ( ! isset( $size_data['width'] ) ) { |
|
293 $size_data['width'] = null; |
|
294 } |
|
295 if ( ! isset( $size_data['height'] ) ) { |
|
296 $size_data['height'] = null; |
|
297 } |
|
298 |
|
299 if ( ! isset( $size_data['crop'] ) ) { |
274 $size_data['crop'] = false; |
300 $size_data['crop'] = false; |
|
301 } |
275 |
302 |
276 $resize_result = $this->resize( $size_data['width'], $size_data['height'], $size_data['crop'] ); |
303 $resize_result = $this->resize( $size_data['width'], $size_data['height'], $size_data['crop'] ); |
277 |
304 $duplicate = ( ( $orig_size['width'] == $size_data['width'] ) && ( $orig_size['height'] == $size_data['height'] ) ); |
278 if( ! is_wp_error( $resize_result ) ) { |
305 |
|
306 if ( ! is_wp_error( $resize_result ) && ! $duplicate ) { |
279 $resized = $this->_save( $this->image ); |
307 $resized = $this->_save( $this->image ); |
280 |
308 |
281 $this->image->clear(); |
309 $this->image->clear(); |
282 $this->image->destroy(); |
310 $this->image->destroy(); |
283 $this->image = null; |
311 $this->image = null; |
300 * Crops Image. |
328 * Crops Image. |
301 * |
329 * |
302 * @since 3.5.0 |
330 * @since 3.5.0 |
303 * @access public |
331 * @access public |
304 * |
332 * |
305 * @param string|int $src The source file or Attachment ID. |
|
306 * @param int $src_x The start x position to crop from. |
333 * @param int $src_x The start x position to crop from. |
307 * @param int $src_y The start y position to crop from. |
334 * @param int $src_y The start y position to crop from. |
308 * @param int $src_w The width to crop. |
335 * @param int $src_w The width to crop. |
309 * @param int $src_h The height to crop. |
336 * @param int $src_h The height to crop. |
310 * @param int $dst_w Optional. The destination width. |
337 * @param int $dst_w Optional. The destination width. |
445 // Set correct file permissions |
472 // Set correct file permissions |
446 $stat = stat( dirname( $filename ) ); |
473 $stat = stat( dirname( $filename ) ); |
447 $perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits |
474 $perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits |
448 @ chmod( $filename, $perms ); |
475 @ chmod( $filename, $perms ); |
449 |
476 |
|
477 /** This filter is documented in wp-includes/class-wp-image-editor-gd.php */ |
450 return array( |
478 return array( |
451 'path' => $filename, |
479 'path' => $filename, |
452 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ), |
480 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ), |
453 'width' => $this->size['width'], |
481 'width' => $this->size['width'], |
454 'height' => $this->size['height'], |
482 'height' => $this->size['height'], |
455 'mime-type' => $mime_type, |
483 'mime-type' => $mime_type, |
456 ); |
484 ); |
457 } |
485 } |
458 |
486 |
459 /** |
487 /** |