13 */ |
13 */ |
14 abstract class WP_Image_Editor { |
14 abstract class WP_Image_Editor { |
15 protected $file = null; |
15 protected $file = null; |
16 protected $size = null; |
16 protected $size = null; |
17 protected $mime_type = null; |
17 protected $mime_type = null; |
|
18 protected $output_mime_type = null; |
18 protected $default_mime_type = 'image/jpeg'; |
19 protected $default_mime_type = 'image/jpeg'; |
19 protected $quality = false; |
20 protected $quality = false; |
20 protected $default_quality = 82; |
21 |
|
22 // Deprecated since 5.8.1. See get_default_quality() below. |
|
23 protected $default_quality = 82; |
21 |
24 |
22 /** |
25 /** |
23 * Each instance handles a single file. |
26 * Each instance handles a single file. |
24 * |
27 * |
25 * @param string $file Path to the file to load. |
28 * @param string $file Path to the file to load. |
91 * @abstract |
94 * @abstract |
92 * |
95 * |
93 * @param int|null $max_w Image width. |
96 * @param int|null $max_w Image width. |
94 * @param int|null $max_h Image height. |
97 * @param int|null $max_h Image height. |
95 * @param bool $crop |
98 * @param bool $crop |
96 * @return bool|WP_Error |
99 * @return true|WP_Error |
97 */ |
100 */ |
98 abstract public function resize( $max_w, $max_h, $crop = false ); |
101 abstract public function resize( $max_w, $max_h, $crop = false ); |
99 |
102 |
100 /** |
103 /** |
101 * Resize multiple images from a single source. |
104 * Resize multiple images from a single source. |
127 * @param int $src_w The width to crop. |
130 * @param int $src_w The width to crop. |
128 * @param int $src_h The height to crop. |
131 * @param int $src_h The height to crop. |
129 * @param int $dst_w Optional. The destination width. |
132 * @param int $dst_w Optional. The destination width. |
130 * @param int $dst_h Optional. The destination height. |
133 * @param int $dst_h Optional. The destination height. |
131 * @param bool $src_abs Optional. If the source crop points are absolute. |
134 * @param bool $src_abs Optional. If the source crop points are absolute. |
132 * @return bool|WP_Error |
135 * @return true|WP_Error |
133 */ |
136 */ |
134 abstract public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ); |
137 abstract public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ); |
135 |
138 |
136 /** |
139 /** |
137 * Rotates current image counter-clockwise by $angle. |
140 * Rotates current image counter-clockwise by $angle. |
138 * |
141 * |
139 * @since 3.5.0 |
142 * @since 3.5.0 |
140 * @abstract |
143 * @abstract |
141 * |
144 * |
142 * @param float $angle |
145 * @param float $angle |
143 * @return bool|WP_Error |
146 * @return true|WP_Error |
144 */ |
147 */ |
145 abstract public function rotate( $angle ); |
148 abstract public function rotate( $angle ); |
146 |
149 |
147 /** |
150 /** |
148 * Flips current image. |
151 * Flips current image. |
150 * @since 3.5.0 |
153 * @since 3.5.0 |
151 * @abstract |
154 * @abstract |
152 * |
155 * |
153 * @param bool $horz Flip along Horizontal Axis |
156 * @param bool $horz Flip along Horizontal Axis |
154 * @param bool $vert Flip along Vertical Axis |
157 * @param bool $vert Flip along Vertical Axis |
155 * @return bool|WP_Error |
158 * @return true|WP_Error |
156 */ |
159 */ |
157 abstract public function flip( $horz, $vert ); |
160 abstract public function flip( $horz, $vert ); |
158 |
161 |
159 /** |
162 /** |
160 * Streams current image to browser. |
163 * Streams current image to browser. |
161 * |
164 * |
162 * @since 3.5.0 |
165 * @since 3.5.0 |
163 * @abstract |
166 * @abstract |
164 * |
167 * |
165 * @param string $mime_type The mime type of the image. |
168 * @param string $mime_type The mime type of the image. |
166 * @return bool|WP_Error True on success, WP_Error object or false on failure. |
169 * @return true|WP_Error True on success, WP_Error object on failure. |
167 */ |
170 */ |
168 abstract public function stream( $mime_type = null ); |
171 abstract public function stream( $mime_type = null ); |
169 |
172 |
170 /** |
173 /** |
171 * Gets dimensions of image. |
174 * Gets dimensions of image. |
222 * |
225 * |
223 * @param int $quality Compression Quality. Range: [1,100] |
226 * @param int $quality Compression Quality. Range: [1,100] |
224 * @return true|WP_Error True if set successfully; WP_Error on failure. |
227 * @return true|WP_Error True if set successfully; WP_Error on failure. |
225 */ |
228 */ |
226 public function set_quality( $quality = null ) { |
229 public function set_quality( $quality = null ) { |
|
230 // Use the output mime type if present. If not, fall back to the input/initial mime type. |
|
231 $mime_type = ! empty( $this->output_mime_type ) ? $this->output_mime_type : $this->mime_type; |
|
232 // Get the default quality setting for the mime type. |
|
233 $default_quality = $this->get_default_quality( $mime_type ); |
|
234 |
227 if ( null === $quality ) { |
235 if ( null === $quality ) { |
228 /** |
236 /** |
229 * Filters the default image compression quality setting. |
237 * Filters the default image compression quality setting. |
230 * |
238 * |
231 * Applies only during initial editor instantiation, or when set_quality() is run |
239 * Applies only during initial editor instantiation, or when set_quality() is run |
236 * @since 3.5.0 |
244 * @since 3.5.0 |
237 * |
245 * |
238 * @param int $quality Quality level between 1 (low) and 100 (high). |
246 * @param int $quality Quality level between 1 (low) and 100 (high). |
239 * @param string $mime_type Image mime type. |
247 * @param string $mime_type Image mime type. |
240 */ |
248 */ |
241 $quality = apply_filters( 'wp_editor_set_quality', $this->default_quality, $this->mime_type ); |
249 $quality = apply_filters( 'wp_editor_set_quality', $default_quality, $mime_type ); |
242 |
250 |
243 if ( 'image/jpeg' === $this->mime_type ) { |
251 if ( 'image/jpeg' === $mime_type ) { |
244 /** |
252 /** |
245 * Filters the JPEG compression quality for backward-compatibility. |
253 * Filters the JPEG compression quality for backward-compatibility. |
246 * |
254 * |
247 * Applies only during initial editor instantiation, or when set_quality() is run |
255 * Applies only during initial editor instantiation, or when set_quality() is run |
248 * manually without the `$quality` argument. |
256 * manually without the `$quality` argument. |
259 */ |
267 */ |
260 $quality = apply_filters( 'jpeg_quality', $quality, 'image_resize' ); |
268 $quality = apply_filters( 'jpeg_quality', $quality, 'image_resize' ); |
261 } |
269 } |
262 |
270 |
263 if ( $quality < 0 || $quality > 100 ) { |
271 if ( $quality < 0 || $quality > 100 ) { |
264 $quality = $this->default_quality; |
272 $quality = $default_quality; |
265 } |
273 } |
266 } |
274 } |
267 |
275 |
268 // Allow 0, but squash to 1 due to identical images in GD, and for backward compatibility. |
276 // Allow 0, but squash to 1 due to identical images in GD, and for backward compatibility. |
269 if ( 0 === $quality ) { |
277 if ( 0 === $quality ) { |
274 $this->quality = $quality; |
282 $this->quality = $quality; |
275 return true; |
283 return true; |
276 } else { |
284 } else { |
277 return new WP_Error( 'invalid_image_quality', __( 'Attempted to set image quality outside of the range [1,100].' ) ); |
285 return new WP_Error( 'invalid_image_quality', __( 'Attempted to set image quality outside of the range [1,100].' ) ); |
278 } |
286 } |
|
287 } |
|
288 |
|
289 /** |
|
290 * Returns the default compression quality setting for the mime type. |
|
291 * |
|
292 * @since 5.8.1 |
|
293 * |
|
294 * @param string $mime_type |
|
295 * @return int The default quality setting for the mime type. |
|
296 */ |
|
297 protected function get_default_quality( $mime_type ) { |
|
298 switch ( $mime_type ) { |
|
299 case 'image/webp': |
|
300 $quality = 86; |
|
301 break; |
|
302 case 'image/jpeg': |
|
303 default: |
|
304 $quality = $this->default_quality; |
|
305 } |
|
306 |
|
307 return $quality; |
279 } |
308 } |
280 |
309 |
281 /** |
310 /** |
282 * Returns preferred mime-type and extension based on provided |
311 * Returns preferred mime-type and extension based on provided |
283 * file's extension and mime, or current file's extension and mime. |
312 * file's extension and mime, or current file's extension and mime. |
312 // Check to see if specified mime-type is the same as type implied by |
341 // Check to see if specified mime-type is the same as type implied by |
313 // file extension. If so, prefer extension from file. |
342 // file extension. If so, prefer extension from file. |
314 if ( ! $mime_type || ( $file_mime == $mime_type ) ) { |
343 if ( ! $mime_type || ( $file_mime == $mime_type ) ) { |
315 $mime_type = $file_mime; |
344 $mime_type = $file_mime; |
316 $new_ext = $file_ext; |
345 $new_ext = $file_ext; |
|
346 } |
|
347 |
|
348 /** |
|
349 * Filters the image editor output format mapping. |
|
350 * |
|
351 * Enables filtering the mime type used to save images. By default, |
|
352 * the mapping array is empty, so the mime type matches the source image. |
|
353 * |
|
354 * @see WP_Image_Editor::get_output_format() |
|
355 * |
|
356 * @since 5.8.0 |
|
357 * |
|
358 * @param string[] $output_format { |
|
359 * An array of mime type mappings. Maps a source mime type to a new |
|
360 * destination mime type. Default empty array. |
|
361 * |
|
362 * @type string ...$0 The new mime type. |
|
363 * } |
|
364 * @param string $filename Path to the image. |
|
365 * @param string $mime_type The source image mime type. |
|
366 * } |
|
367 */ |
|
368 $output_format = apply_filters( 'image_editor_output_format', array(), $filename, $mime_type ); |
|
369 |
|
370 if ( isset( $output_format[ $mime_type ] ) |
|
371 && $this->supports_mime_type( $output_format[ $mime_type ] ) |
|
372 ) { |
|
373 $mime_type = $output_format[ $mime_type ]; |
|
374 $new_ext = $this->get_extension( $mime_type ); |
317 } |
375 } |
318 |
376 |
319 // Double-check that the mime-type selected is supported by the editor. |
377 // Double-check that the mime-type selected is supported by the editor. |
320 // If not, choose a default instead. |
378 // If not, choose a default instead. |
321 if ( ! $this->supports_mime_type( $mime_type ) ) { |
379 if ( ! $this->supports_mime_type( $mime_type ) ) { |
330 */ |
388 */ |
331 $mime_type = apply_filters( 'image_editor_default_mime_type', $this->default_mime_type ); |
389 $mime_type = apply_filters( 'image_editor_default_mime_type', $this->default_mime_type ); |
332 $new_ext = $this->get_extension( $mime_type ); |
390 $new_ext = $this->get_extension( $mime_type ); |
333 } |
391 } |
334 |
392 |
335 if ( $filename ) { |
393 // Ensure both $filename and $new_ext are not empty. |
|
394 // $this->get_extension() returns false on error which would effectively remove the extension |
|
395 // from $filename. That shouldn't happen, files without extensions are not supported. |
|
396 if ( $filename && $new_ext ) { |
336 $dir = pathinfo( $filename, PATHINFO_DIRNAME ); |
397 $dir = pathinfo( $filename, PATHINFO_DIRNAME ); |
337 $ext = pathinfo( $filename, PATHINFO_EXTENSION ); |
398 $ext = pathinfo( $filename, PATHINFO_EXTENSION ); |
338 |
399 |
339 $filename = trailingslashit( $dir ) . wp_basename( $filename, ".$ext" ) . ".{$new_ext}"; |
400 $filename = trailingslashit( $dir ) . wp_basename( $filename, ".$ext" ) . ".{$new_ext}"; |
|
401 } |
|
402 |
|
403 if ( $mime_type && ( $mime_type !== $this->mime_type ) ) { |
|
404 // The image will be converted when saving. Set the quality for the new mime-type if not already set. |
|
405 if ( $mime_type !== $this->output_mime_type ) { |
|
406 $this->output_mime_type = $mime_type; |
|
407 $this->set_quality(); |
|
408 } |
|
409 } elseif ( ! empty( $this->output_mime_type ) ) { |
|
410 // Reset output_mime_type and quality. |
|
411 $this->output_mime_type = null; |
|
412 $this->set_quality(); |
340 } |
413 } |
341 |
414 |
342 return array( $filename, $new_ext, $mime_type ); |
415 return array( $filename, $new_ext, $mime_type ); |
343 } |
416 } |
344 |
417 |
363 |
436 |
364 $name = wp_basename( $this->file, ".$ext" ); |
437 $name = wp_basename( $this->file, ".$ext" ); |
365 $new_ext = strtolower( $extension ? $extension : $ext ); |
438 $new_ext = strtolower( $extension ? $extension : $ext ); |
366 |
439 |
367 if ( ! is_null( $dest_path ) ) { |
440 if ( ! is_null( $dest_path ) ) { |
368 $_dest_path = realpath( $dest_path ); |
441 if ( ! wp_is_stream( $dest_path ) ) { |
369 if ( $_dest_path ) { |
442 $_dest_path = realpath( $dest_path ); |
370 $dir = $_dest_path; |
443 if ( $_dest_path ) { |
|
444 $dir = $_dest_path; |
|
445 } |
|
446 } else { |
|
447 $dir = $dest_path; |
371 } |
448 } |
372 } |
449 } |
373 |
450 |
374 return trailingslashit( $dir ) . "{$name}-{$suffix}.{$new_ext}"; |
451 return trailingslashit( $dir ) . "{$name}-{$suffix}.{$new_ext}"; |
375 } |
452 } |
543 * |
620 * |
544 * @param string $mime_type |
621 * @param string $mime_type |
545 * @return string|false |
622 * @return string|false |
546 */ |
623 */ |
547 protected static function get_extension( $mime_type = null ) { |
624 protected static function get_extension( $mime_type = null ) { |
548 $extensions = explode( '|', array_search( $mime_type, wp_get_mime_types(), true ) ); |
625 if ( empty( $mime_type ) ) { |
549 |
|
550 if ( empty( $extensions[0] ) ) { |
|
551 return false; |
626 return false; |
552 } |
627 } |
553 |
628 |
554 return $extensions[0]; |
629 return wp_get_default_extension_for_mime_type( $mime_type ); |
555 } |
630 } |
556 } |
631 } |
557 |
632 |