wp/wp-includes/class-wp-image-editor.php
changeset 18 be944660c56a
parent 16 a86126ab1dd4
child 19 3d72ae0968f4
equal deleted inserted replaced
17:34716fd837a4 18:be944660c56a
    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.
    62 	 * Loads image from $this->file into editor.
    65 	 * Loads image from $this->file into editor.
    63 	 *
    66 	 *
    64 	 * @since 3.5.0
    67 	 * @since 3.5.0
    65 	 * @abstract
    68 	 * @abstract
    66 	 *
    69 	 *
    67 	 * @return bool|WP_Error True if loaded; WP_Error on failure.
    70 	 * @return true|WP_Error True if loaded; WP_Error on failure.
    68 	 */
    71 	 */
    69 	abstract public function load();
    72 	abstract public function load();
    70 
    73 
    71 	/**
    74 	/**
    72 	 * Saves current image to file.
    75 	 * Saves current image to file.
    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