wp/wp-includes/class-wp-image-editor.php
changeset 16 a86126ab1dd4
parent 9 177826044cd9
child 18 be944660c56a
equal deleted inserted replaced
15:3d4e9c994f10 16:a86126ab1dd4
    28 		$this->file = $file;
    28 		$this->file = $file;
    29 	}
    29 	}
    30 
    30 
    31 	/**
    31 	/**
    32 	 * Checks to see if current environment supports the editor chosen.
    32 	 * Checks to see if current environment supports the editor chosen.
    33 	 * Must be overridden in a sub-class.
    33 	 * Must be overridden in a subclass.
    34 	 *
    34 	 *
    35 	 * @since 3.5.0
    35 	 * @since 3.5.0
    36 	 *
    36 	 *
    37 	 * @abstract
    37 	 * @abstract
    38 	 *
    38 	 *
    43 		return false;
    43 		return false;
    44 	}
    44 	}
    45 
    45 
    46 	/**
    46 	/**
    47 	 * Checks to see if editor supports the mime-type specified.
    47 	 * Checks to see if editor supports the mime-type specified.
    48 	 * Must be overridden in a sub-class.
    48 	 * Must be overridden in a subclass.
    49 	 *
    49 	 *
    50 	 * @since 3.5.0
    50 	 * @since 3.5.0
    51 	 *
    51 	 *
    52 	 * @abstract
    52 	 * @abstract
    53 	 *
    53 	 *
    88 	 * maintain aspect ratio according to the provided dimension.
    88 	 * maintain aspect ratio according to the provided dimension.
    89 	 *
    89 	 *
    90 	 * @since 3.5.0
    90 	 * @since 3.5.0
    91 	 * @abstract
    91 	 * @abstract
    92 	 *
    92 	 *
    93 	 * @param  int|null $max_w Image width.
    93 	 * @param int|null $max_w Image width.
    94 	 * @param  int|null $max_h Image height.
    94 	 * @param int|null $max_h Image height.
    95 	 * @param  bool     $crop
    95 	 * @param bool     $crop
    96 	 * @return bool|WP_Error
    96 	 * @return bool|WP_Error
    97 	 */
    97 	 */
    98 	abstract public function resize( $max_w, $max_h, $crop = false );
    98 	abstract public function resize( $max_w, $max_h, $crop = false );
    99 
    99 
   100 	/**
   100 	/**
   120 	 * Crops Image.
   120 	 * Crops Image.
   121 	 *
   121 	 *
   122 	 * @since 3.5.0
   122 	 * @since 3.5.0
   123 	 * @abstract
   123 	 * @abstract
   124 	 *
   124 	 *
   125 	 * @param int $src_x The start x position to crop from.
   125 	 * @param int  $src_x   The start x position to crop from.
   126 	 * @param int $src_y The start y position to crop from.
   126 	 * @param int  $src_y   The start y position to crop from.
   127 	 * @param int $src_w The width to crop.
   127 	 * @param int  $src_w   The width to crop.
   128 	 * @param int $src_h The height to crop.
   128 	 * @param int  $src_h   The height to crop.
   129 	 * @param int $dst_w Optional. The destination width.
   129 	 * @param int  $dst_w   Optional. The destination width.
   130 	 * @param int $dst_h Optional. The destination height.
   130 	 * @param int  $dst_h   Optional. The destination height.
   131 	 * @param bool $src_abs Optional. If the source crop points are absolute.
   131 	 * @param bool $src_abs Optional. If the source crop points are absolute.
   132 	 * @return bool|WP_Error
   132 	 * @return bool|WP_Error
   133 	 */
   133 	 */
   134 	abstract public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false );
   134 	abstract public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false );
   135 
   135 
   170 	/**
   170 	/**
   171 	 * Gets dimensions of image.
   171 	 * Gets dimensions of image.
   172 	 *
   172 	 *
   173 	 * @since 3.5.0
   173 	 * @since 3.5.0
   174 	 *
   174 	 *
   175 	 * @return array {'width'=>int, 'height'=>int}
   175 	 * @return array {
       
   176 	 *     Dimensions of the image.
       
   177 	 *
       
   178 	 *     @type int $width  The image width.
       
   179 	 *     @type int $height The image height.
       
   180 	 * }
   176 	 */
   181 	 */
   177 	public function get_size() {
   182 	public function get_size() {
   178 		return $this->size;
   183 		return $this->size;
   179 	}
   184 	}
   180 
   185 
   198 	/**
   203 	/**
   199 	 * Gets the Image Compression quality on a 1-100% scale.
   204 	 * Gets the Image Compression quality on a 1-100% scale.
   200 	 *
   205 	 *
   201 	 * @since 4.0.0
   206 	 * @since 4.0.0
   202 	 *
   207 	 *
   203 	 * @return int $quality Compression Quality. Range: [1,100]
   208 	 * @return int Compression Quality. Range: [1,100]
   204 	 */
   209 	 */
   205 	public function get_quality() {
   210 	public function get_quality() {
   206 		if ( ! $this->quality ) {
   211 		if ( ! $this->quality ) {
   207 			$this->set_quality();
   212 			$this->set_quality();
   208 		}
   213 		}
   224 			 * Filters the default image compression quality setting.
   229 			 * Filters the default image compression quality setting.
   225 			 *
   230 			 *
   226 			 * Applies only during initial editor instantiation, or when set_quality() is run
   231 			 * Applies only during initial editor instantiation, or when set_quality() is run
   227 			 * manually without the `$quality` argument.
   232 			 * manually without the `$quality` argument.
   228 			 *
   233 			 *
   229 			 * set_quality() has priority over the filter.
   234 			 * The WP_Image_Editor::set_quality() method has priority over the filter.
   230 			 *
   235 			 *
   231 			 * @since 3.5.0
   236 			 * @since 3.5.0
   232 			 *
   237 			 *
   233 			 * @param int    $quality   Quality level between 1 (low) and 100 (high).
   238 			 * @param int    $quality   Quality level between 1 (low) and 100 (high).
   234 			 * @param string $mime_type Image mime type.
   239 			 * @param string $mime_type Image mime type.
   235 			 */
   240 			 */
   236 			$quality = apply_filters( 'wp_editor_set_quality', $this->default_quality, $this->mime_type );
   241 			$quality = apply_filters( 'wp_editor_set_quality', $this->default_quality, $this->mime_type );
   237 
   242 
   238 			if ( 'image/jpeg' == $this->mime_type ) {
   243 			if ( 'image/jpeg' === $this->mime_type ) {
   239 				/**
   244 				/**
   240 				 * Filters the JPEG compression quality for backward-compatibility.
   245 				 * Filters the JPEG compression quality for backward-compatibility.
   241 				 *
   246 				 *
   242 				 * Applies only during initial editor instantiation, or when set_quality() is run
   247 				 * Applies only during initial editor instantiation, or when set_quality() is run
   243 				 * manually without the `$quality` argument.
   248 				 * manually without the `$quality` argument.
   244 				 *
   249 				 *
   245 				 * set_quality() has priority over the filter.
   250 				 * The WP_Image_Editor::set_quality() method has priority over the filter.
   246 				 *
   251 				 *
   247 				 * The filter is evaluated under two contexts: 'image_resize', and 'edit_image',
   252 				 * The filter is evaluated under two contexts: 'image_resize', and 'edit_image',
   248 				 * (when a JPEG image is saved to file).
   253 				 * (when a JPEG image is saved to file).
   249 				 *
   254 				 *
   250 				 * @since 2.5.0
   255 				 * @since 2.5.0
   288 	 * @return array { filename|null, extension, mime-type }
   293 	 * @return array { filename|null, extension, mime-type }
   289 	 */
   294 	 */
   290 	protected function get_output_format( $filename = null, $mime_type = null ) {
   295 	protected function get_output_format( $filename = null, $mime_type = null ) {
   291 		$new_ext = null;
   296 		$new_ext = null;
   292 
   297 
   293 		// By default, assume specified type takes priority
   298 		// By default, assume specified type takes priority.
   294 		if ( $mime_type ) {
   299 		if ( $mime_type ) {
   295 			$new_ext = $this->get_extension( $mime_type );
   300 			$new_ext = $this->get_extension( $mime_type );
   296 		}
   301 		}
   297 
   302 
   298 		if ( $filename ) {
   303 		if ( $filename ) {
   303 			$file_ext  = strtolower( pathinfo( $this->file, PATHINFO_EXTENSION ) );
   308 			$file_ext  = strtolower( pathinfo( $this->file, PATHINFO_EXTENSION ) );
   304 			$file_mime = $this->mime_type;
   309 			$file_mime = $this->mime_type;
   305 		}
   310 		}
   306 
   311 
   307 		// Check to see if specified mime-type is the same as type implied by
   312 		// Check to see if specified mime-type is the same as type implied by
   308 		// file extension.  If so, prefer extension from file.
   313 		// file extension. If so, prefer extension from file.
   309 		if ( ! $mime_type || ( $file_mime == $mime_type ) ) {
   314 		if ( ! $mime_type || ( $file_mime == $mime_type ) ) {
   310 			$mime_type = $file_mime;
   315 			$mime_type = $file_mime;
   311 			$new_ext   = $file_ext;
   316 			$new_ext   = $file_ext;
   312 		}
   317 		}
   313 
   318 
   346 	 * @param string $dest_path
   351 	 * @param string $dest_path
   347 	 * @param string $extension
   352 	 * @param string $extension
   348 	 * @return string filename
   353 	 * @return string filename
   349 	 */
   354 	 */
   350 	public function generate_filename( $suffix = null, $dest_path = null, $extension = null ) {
   355 	public function generate_filename( $suffix = null, $dest_path = null, $extension = null ) {
   351 		// $suffix will be appended to the destination filename, just before the extension
   356 		// $suffix will be appended to the destination filename, just before the extension.
   352 		if ( ! $suffix ) {
   357 		if ( ! $suffix ) {
   353 			$suffix = $this->get_suffix();
   358 			$suffix = $this->get_suffix();
   354 		}
   359 		}
   355 
   360 
   356 		$dir = pathinfo( $this->file, PATHINFO_DIRNAME );
   361 		$dir = pathinfo( $this->file, PATHINFO_DIRNAME );
   357 		$ext = pathinfo( $this->file, PATHINFO_EXTENSION );
   362 		$ext = pathinfo( $this->file, PATHINFO_EXTENSION );
   358 
   363 
   359 		$name    = wp_basename( $this->file, ".$ext" );
   364 		$name    = wp_basename( $this->file, ".$ext" );
   360 		$new_ext = strtolower( $extension ? $extension : $ext );
   365 		$new_ext = strtolower( $extension ? $extension : $ext );
   361 
   366 
   362 		if ( ! is_null( $dest_path ) && $_dest_path = realpath( $dest_path ) ) {
   367 		if ( ! is_null( $dest_path ) ) {
   363 			$dir = $_dest_path;
   368 			$_dest_path = realpath( $dest_path );
       
   369 			if ( $_dest_path ) {
       
   370 				$dir = $_dest_path;
       
   371 			}
   364 		}
   372 		}
   365 
   373 
   366 		return trailingslashit( $dir ) . "{$name}-{$suffix}.{$new_ext}";
   374 		return trailingslashit( $dir ) . "{$name}-{$suffix}.{$new_ext}";
   367 	}
   375 	}
   368 
   376 
   369 	/**
   377 	/**
   370 	 * Builds and returns proper suffix for file based on height and width.
   378 	 * Builds and returns proper suffix for file based on height and width.
   371 	 *
   379 	 *
   372 	 * @since 3.5.0
   380 	 * @since 3.5.0
   373 	 *
   381 	 *
   374 	 * @return false|string suffix
   382 	 * @return string|false suffix
   375 	 */
   383 	 */
   376 	public function get_suffix() {
   384 	public function get_suffix() {
   377 		if ( ! $this->get_size() ) {
   385 		if ( ! $this->get_size() ) {
   378 			return false;
   386 			return false;
   379 		}
   387 		}
   380 
   388 
   381 		return "{$this->size['width']}x{$this->size['height']}";
   389 		return "{$this->size['width']}x{$this->size['height']}";
   382 	}
   390 	}
   383 
   391 
   384 	/**
   392 	/**
       
   393 	 * Check if a JPEG image has EXIF Orientation tag and rotate it if needed.
       
   394 	 *
       
   395 	 * @since 5.3.0
       
   396 	 *
       
   397 	 * @return bool|WP_Error True if the image was rotated. False if not rotated (no EXIF data or the image doesn't need to be rotated).
       
   398 	 *                       WP_Error if error while rotating.
       
   399 	 */
       
   400 	public function maybe_exif_rotate() {
       
   401 		$orientation = null;
       
   402 
       
   403 		if ( is_callable( 'exif_read_data' ) && 'image/jpeg' === $this->mime_type ) {
       
   404 			$exif_data = @exif_read_data( $this->file );
       
   405 
       
   406 			if ( ! empty( $exif_data['Orientation'] ) ) {
       
   407 				$orientation = (int) $exif_data['Orientation'];
       
   408 			}
       
   409 		}
       
   410 
       
   411 		/**
       
   412 		 * Filters the `$orientation` value to correct it before rotating or to prevemnt rotating the image.
       
   413 		 *
       
   414 		 * @since 5.3.0
       
   415 		 *
       
   416 		 * @param int    $orientation EXIF Orientation value as retrieved from the image file.
       
   417 		 * @param string $file        Path to the image file.
       
   418 		 */
       
   419 		$orientation = apply_filters( 'wp_image_maybe_exif_rotate', $orientation, $this->file );
       
   420 
       
   421 		if ( ! $orientation || 1 === $orientation ) {
       
   422 			return false;
       
   423 		}
       
   424 
       
   425 		switch ( $orientation ) {
       
   426 			case 2:
       
   427 				// Flip horizontally.
       
   428 				$result = $this->flip( true, false );
       
   429 				break;
       
   430 			case 3:
       
   431 				// Rotate 180 degrees or flip horizontally and vertically.
       
   432 				// Flipping seems faster and uses less resources.
       
   433 				$result = $this->flip( true, true );
       
   434 				break;
       
   435 			case 4:
       
   436 				// Flip vertically.
       
   437 				$result = $this->flip( false, true );
       
   438 				break;
       
   439 			case 5:
       
   440 				// Rotate 90 degrees counter-clockwise and flip vertically.
       
   441 				$result = $this->rotate( 90 );
       
   442 
       
   443 				if ( ! is_wp_error( $result ) ) {
       
   444 					$result = $this->flip( false, true );
       
   445 				}
       
   446 
       
   447 				break;
       
   448 			case 6:
       
   449 				// Rotate 90 degrees clockwise (270 counter-clockwise).
       
   450 				$result = $this->rotate( 270 );
       
   451 				break;
       
   452 			case 7:
       
   453 				// Rotate 90 degrees counter-clockwise and flip horizontally.
       
   454 				$result = $this->rotate( 90 );
       
   455 
       
   456 				if ( ! is_wp_error( $result ) ) {
       
   457 					$result = $this->flip( true, false );
       
   458 				}
       
   459 
       
   460 				break;
       
   461 			case 8:
       
   462 				// Rotate 90 degrees counter-clockwise.
       
   463 				$result = $this->rotate( 90 );
       
   464 				break;
       
   465 		}
       
   466 
       
   467 		return $result;
       
   468 	}
       
   469 
       
   470 	/**
   385 	 * Either calls editor's save function or handles file as a stream.
   471 	 * Either calls editor's save function or handles file as a stream.
   386 	 *
   472 	 *
   387 	 * @since 3.5.0
   473 	 * @since 3.5.0
   388 	 *
   474 	 *
   389 	 * @param string|stream $filename
   475 	 * @param string|stream $filename
   390 	 * @param callable $function
   476 	 * @param callable      $function
   391 	 * @param array $arguments
   477 	 * @param array         $arguments
   392 	 * @return bool
   478 	 * @return bool
   393 	 */
   479 	 */
   394 	protected function make_image( $filename, $function, $arguments ) {
   480 	protected function make_image( $filename, $function, $arguments ) {
   395 		if ( $stream = wp_is_stream( $filename ) ) {
   481 		$stream = wp_is_stream( $filename );
       
   482 		if ( $stream ) {
   396 			ob_start();
   483 			ob_start();
   397 		} else {
   484 		} else {
   398 			// The directory containing the original file may no longer exist when using a replication plugin.
   485 			// The directory containing the original file may no longer exist when using a replication plugin.
   399 			wp_mkdir_p( dirname( $filename ) );
   486 			wp_mkdir_p( dirname( $filename ) );
   400 		}
   487 		}
   456 	 *
   543 	 *
   457 	 * @param string $mime_type
   544 	 * @param string $mime_type
   458 	 * @return string|false
   545 	 * @return string|false
   459 	 */
   546 	 */
   460 	protected static function get_extension( $mime_type = null ) {
   547 	protected static function get_extension( $mime_type = null ) {
   461 		$extensions = explode( '|', array_search( $mime_type, wp_get_mime_types() ) );
   548 		$extensions = explode( '|', array_search( $mime_type, wp_get_mime_types(), true ) );
   462 
   549 
   463 		if ( empty( $extensions[0] ) ) {
   550 		if ( empty( $extensions[0] ) ) {
   464 			return false;
   551 			return false;
   465 		}
   552 		}
   466 
   553