wp/wp-includes/class-wp-image-editor-gd.php
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
     8 
     8 
     9 /**
     9 /**
    10  * WordPress Image Editor Class for Image Manipulation through GD
    10  * WordPress Image Editor Class for Image Manipulation through GD
    11  *
    11  *
    12  * @since 3.5.0
    12  * @since 3.5.0
    13  * @package WordPress
    13  *
    14  * @subpackage Image_Editor
    14  * @see WP_Image_Editor
    15  * @uses WP_Image_Editor Extends class
       
    16  */
    15  */
    17 class WP_Image_Editor_GD extends WP_Image_Editor {
    16 class WP_Image_Editor_GD extends WP_Image_Editor {
    18 	/**
    17 	/**
       
    18 	 * GD Resource.
       
    19 	 *
    19 	 * @var resource
    20 	 * @var resource
    20 	 */
    21 	 */
    21 	protected $image; // GD Resource
    22 	protected $image;
    22 
    23 
    23 	public function __destruct() {
    24 	public function __destruct() {
    24 		if ( $this->image ) {
    25 		if ( $this->image ) {
    25 			// we don't need the original in memory anymore
    26 			// we don't need the original in memory anymore
    26 			imagedestroy( $this->image );
    27 			imagedestroy( $this->image );
    29 
    30 
    30 	/**
    31 	/**
    31 	 * Checks to see if current environment supports GD.
    32 	 * Checks to see if current environment supports GD.
    32 	 *
    33 	 *
    33 	 * @since 3.5.0
    34 	 * @since 3.5.0
    34 	 * @access public
    35 	 *
    35 	 *
    36 	 * @static
    36 	 * @return boolean
    37 	 *
       
    38 	 * @param array $args
       
    39 	 * @return bool
    37 	 */
    40 	 */
    38 	public static function test( $args = array() ) {
    41 	public static function test( $args = array() ) {
    39 		if ( ! extension_loaded('gd') || ! function_exists('gd_info') )
    42 		if ( ! extension_loaded('gd') || ! function_exists('gd_info') )
    40 			return false;
    43 			return false;
    41 
    44 
    52 
    55 
    53 	/**
    56 	/**
    54 	 * Checks to see if editor supports the mime-type specified.
    57 	 * Checks to see if editor supports the mime-type specified.
    55 	 *
    58 	 *
    56 	 * @since 3.5.0
    59 	 * @since 3.5.0
    57 	 * @access public
    60 	 *
       
    61 	 * @static
    58 	 *
    62 	 *
    59 	 * @param string $mime_type
    63 	 * @param string $mime_type
    60 	 * @return boolean
    64 	 * @return bool
    61 	 */
    65 	 */
    62 	public static function supports_mime_type( $mime_type ) {
    66 	public static function supports_mime_type( $mime_type ) {
    63 		$image_types = imagetypes();
    67 		$image_types = imagetypes();
    64 		switch( $mime_type ) {
    68 		switch( $mime_type ) {
    65 			case 'image/jpeg':
    69 			case 'image/jpeg':
    75 
    79 
    76 	/**
    80 	/**
    77 	 * Loads image from $this->file into new GD Resource.
    81 	 * Loads image from $this->file into new GD Resource.
    78 	 *
    82 	 *
    79 	 * @since 3.5.0
    83 	 * @since 3.5.0
    80 	 * @access protected
    84 	 *
    81 	 *
    85 	 * @return bool|WP_Error True if loaded successfully; WP_Error on failure.
    82 	 * @return boolean|WP_Error True if loaded successfully; WP_Error on failure.
       
    83 	 */
    86 	 */
    84 	public function load() {
    87 	public function load() {
    85 		if ( $this->image )
    88 		if ( $this->image )
    86 			return true;
    89 			return true;
    87 
    90 
    88 		if ( ! is_file( $this->file ) && ! preg_match( '|^https?://|', $this->file ) )
    91 		if ( ! is_file( $this->file ) && ! preg_match( '|^https?://|', $this->file ) )
    89 			return new WP_Error( 'error_loading_image', __('File doesn’t exist?'), $this->file );
    92 			return new WP_Error( 'error_loading_image', __('File doesn’t exist?'), $this->file );
    90 
    93 
    91 		/**
    94 		// Set artificially high because GD uses uncompressed images in memory.
    92 		 * Filter the memory limit allocated for image manipulation.
    95 		wp_raise_memory_limit( 'image' );
    93 		 *
       
    94 		 * @since 3.5.0
       
    95 		 *
       
    96 		 * @param int|string $limit Maximum memory limit to allocate for images. Default WP_MAX_MEMORY_LIMIT.
       
    97 		 *                          Accepts an integer (bytes), or a shorthand string notation, such as '256M'.
       
    98 		 */
       
    99 		// Set artificially high because GD uses uncompressed images in memory
       
   100 		@ini_set( 'memory_limit', apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT ) );
       
   101 
    96 
   102 		$this->image = @imagecreatefromstring( file_get_contents( $this->file ) );
    97 		$this->image = @imagecreatefromstring( file_get_contents( $this->file ) );
   103 
    98 
   104 		if ( ! is_resource( $this->image ) )
    99 		if ( ! is_resource( $this->image ) )
   105 			return new WP_Error( 'invalid_image', __('File is not an image.'), $this->file );
   100 			return new WP_Error( 'invalid_image', __('File is not an image.'), $this->file );
   121 
   116 
   122 	/**
   117 	/**
   123 	 * Sets or updates current image size.
   118 	 * Sets or updates current image size.
   124 	 *
   119 	 *
   125 	 * @since 3.5.0
   120 	 * @since 3.5.0
   126 	 * @access protected
       
   127 	 *
   121 	 *
   128 	 * @param int $width
   122 	 * @param int $width
   129 	 * @param int $height
   123 	 * @param int $height
       
   124 	 * @return true
   130 	 */
   125 	 */
   131 	protected function update_size( $width = false, $height = false ) {
   126 	protected function update_size( $width = false, $height = false ) {
   132 		if ( ! $width )
   127 		if ( ! $width )
   133 			$width = imagesx( $this->image );
   128 			$width = imagesx( $this->image );
   134 
   129 
   145 	 * At minimum, either a height or width must be provided.
   140 	 * At minimum, either a height or width must be provided.
   146 	 * If one of the two is set to null, the resize will
   141 	 * If one of the two is set to null, the resize will
   147 	 * maintain aspect ratio according to the provided dimension.
   142 	 * maintain aspect ratio according to the provided dimension.
   148 	 *
   143 	 *
   149 	 * @since 3.5.0
   144 	 * @since 3.5.0
   150 	 * @access public
       
   151 	 *
   145 	 *
   152 	 * @param  int|null $max_w Image width.
   146 	 * @param  int|null $max_w Image width.
   153 	 * @param  int|null $max_h Image height.
   147 	 * @param  int|null $max_h Image height.
   154 	 * @param  boolean  $crop
   148 	 * @param  bool     $crop
   155 	 * @return boolean|WP_Error
   149 	 * @return true|WP_Error
   156 	 */
   150 	 */
   157 	public function resize( $max_w, $max_h, $crop = false ) {
   151 	public function resize( $max_w, $max_h, $crop = false ) {
   158 		if ( ( $this->size['width'] == $max_w ) && ( $this->size['height'] == $max_h ) )
   152 		if ( ( $this->size['width'] == $max_w ) && ( $this->size['height'] == $max_h ) )
   159 			return true;
   153 			return true;
   160 
   154 
   169 			return $resized;
   163 			return $resized;
   170 
   164 
   171 		return new WP_Error( 'image_resize_error', __('Image resize failed.'), $this->file );
   165 		return new WP_Error( 'image_resize_error', __('Image resize failed.'), $this->file );
   172 	}
   166 	}
   173 
   167 
       
   168 	/**
       
   169 	 *
       
   170 	 * @param int $max_w
       
   171 	 * @param int $max_h
       
   172 	 * @param bool|array $crop
       
   173 	 * @return resource|WP_Error
       
   174 	 */
   174 	protected function _resize( $max_w, $max_h, $crop = false ) {
   175 	protected function _resize( $max_w, $max_h, $crop = false ) {
   175 		$dims = image_resize_dimensions( $this->size['width'], $this->size['height'], $max_w, $max_h, $crop );
   176 		$dims = image_resize_dimensions( $this->size['width'], $this->size['height'], $max_w, $max_h, $crop );
   176 		if ( ! $dims ) {
   177 		if ( ! $dims ) {
   177 			return new WP_Error( 'error_getting_dimensions', __('Could not calculate resized image dimensions'), $this->file );
   178 			return new WP_Error( 'error_getting_dimensions', __('Could not calculate resized image dimensions'), $this->file );
   178 		}
   179 		}
   191 
   192 
   192 	/**
   193 	/**
   193 	 * Resize multiple images from a single source.
   194 	 * Resize multiple images from a single source.
   194 	 *
   195 	 *
   195 	 * @since 3.5.0
   196 	 * @since 3.5.0
   196 	 * @access public
       
   197 	 *
   197 	 *
   198 	 * @param array $sizes {
   198 	 * @param array $sizes {
   199 	 *     An array of image size arrays. Default sizes are 'small', 'medium', 'large'.
   199 	 *     An array of image size arrays. Default sizes are 'small', 'medium', 'medium_large', 'large'.
   200 	 *
   200 	 *
   201 	 *     Either a height or width must be provided.
   201 	 *     Either a height or width must be provided.
   202 	 *     If one of the two is set to null, the resize will
   202 	 *     If one of the two is set to null, the resize will
   203 	 *     maintain aspect ratio according to the provided dimension.
   203 	 *     maintain aspect ratio according to the provided dimension.
   204 	 *
   204 	 *
   205 	 *     @type array $size {
   205 	 *     @type array $size {
   206 	 *         @type int  ['width']  Optional. Image width.
   206 	 *         Array of height, width values, and whether to crop.
   207 	 *         @type int  ['height'] Optional. Image height.
   207 	 *
   208 	 *         @type bool ['crop']   Optional. Whether to crop the image. Default false.
   208 	 *         @type int  $width  Image width. Optional if `$height` is specified.
       
   209 	 *         @type int  $height Image height. Optional if `$width` is specified.
       
   210 	 *         @type bool $crop   Optional. Whether to crop the image. Default false.
   209 	 *     }
   211 	 *     }
   210 	 * }
   212 	 * }
   211 	 * @return array An array of resized images' metadata by size.
   213 	 * @return array An array of resized images' metadata by size.
   212 	 */
   214 	 */
   213 	public function multi_resize( $sizes ) {
   215 	public function multi_resize( $sizes ) {
   252 
   254 
   253 	/**
   255 	/**
   254 	 * Crops Image.
   256 	 * Crops Image.
   255 	 *
   257 	 *
   256 	 * @since 3.5.0
   258 	 * @since 3.5.0
   257 	 * @access public
   259 	 *
   258 	 *
   260 	 * @param int  $src_x   The start x position to crop from.
   259 	 * @param int $src_x The start x position to crop from.
   261 	 * @param int  $src_y   The start y position to crop from.
   260 	 * @param int $src_y The start y position to crop from.
   262 	 * @param int  $src_w   The width to crop.
   261 	 * @param int $src_w The width to crop.
   263 	 * @param int  $src_h   The height to crop.
   262 	 * @param int $src_h The height to crop.
   264 	 * @param int  $dst_w   Optional. The destination width.
   263 	 * @param int $dst_w Optional. The destination width.
   265 	 * @param int  $dst_h   Optional. The destination height.
   264 	 * @param int $dst_h Optional. The destination height.
   266 	 * @param bool $src_abs Optional. If the source crop points are absolute.
   265 	 * @param boolean $src_abs Optional. If the source crop points are absolute.
   267 	 * @return bool|WP_Error
   266 	 * @return boolean|WP_Error
       
   267 	 */
   268 	 */
   268 	public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ) {
   269 	public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ) {
   269 		// If destination width/height isn't specified, use same as
   270 		// If destination width/height isn't specified, use same as
   270 		// width/height from source.
   271 		// width/height from source.
   271 		if ( ! $dst_w )
   272 		if ( ! $dst_w )
   298 	/**
   299 	/**
   299 	 * Rotates current image counter-clockwise by $angle.
   300 	 * Rotates current image counter-clockwise by $angle.
   300 	 * Ported from image-edit.php
   301 	 * Ported from image-edit.php
   301 	 *
   302 	 *
   302 	 * @since 3.5.0
   303 	 * @since 3.5.0
   303 	 * @access public
       
   304 	 *
   304 	 *
   305 	 * @param float $angle
   305 	 * @param float $angle
   306 	 * @return boolean|WP_Error
   306 	 * @return true|WP_Error
   307 	 */
   307 	 */
   308 	public function rotate( $angle ) {
   308 	public function rotate( $angle ) {
   309 		if ( function_exists('imagerotate') ) {
   309 		if ( function_exists('imagerotate') ) {
   310 			$transparency = imagecolorallocatealpha( $this->image, 255, 255, 255, 127 );
   310 			$transparency = imagecolorallocatealpha( $this->image, 255, 255, 255, 127 );
   311 			$rotated = imagerotate( $this->image, $angle, $transparency );
   311 			$rotated = imagerotate( $this->image, $angle, $transparency );
   324 
   324 
   325 	/**
   325 	/**
   326 	 * Flips current image.
   326 	 * Flips current image.
   327 	 *
   327 	 *
   328 	 * @since 3.5.0
   328 	 * @since 3.5.0
   329 	 * @access public
   329 	 *
   330 	 *
   330 	 * @param bool $horz Flip along Horizontal Axis
   331 	 * @param boolean $horz Flip along Horizontal Axis
   331 	 * @param bool $vert Flip along Vertical Axis
   332 	 * @param boolean $vert Flip along Vertical Axis
   332 	 * @return true|WP_Error
   333 	 * @returns boolean|WP_Error
       
   334 	 */
   333 	 */
   335 	public function flip( $horz, $vert ) {
   334 	public function flip( $horz, $vert ) {
   336 		$w = $this->size['width'];
   335 		$w = $this->size['width'];
   337 		$h = $this->size['height'];
   336 		$h = $this->size['height'];
   338 		$dst = wp_imagecreatetruecolor( $w, $h );
   337 		$dst = wp_imagecreatetruecolor( $w, $h );
   354 
   353 
   355 	/**
   354 	/**
   356 	 * Saves current in-memory image to file.
   355 	 * Saves current in-memory image to file.
   357 	 *
   356 	 *
   358 	 * @since 3.5.0
   357 	 * @since 3.5.0
   359 	 * @access public
       
   360 	 *
   358 	 *
   361 	 * @param string|null $filename
   359 	 * @param string|null $filename
   362 	 * @param string|null $mime_type
   360 	 * @param string|null $mime_type
   363 	 * @return array|WP_Error {'path'=>string, 'file'=>string, 'width'=>int, 'height'=>int, 'mime-type'=>string}
   361 	 * @return array|WP_Error {'path'=>string, 'file'=>string, 'width'=>int, 'height'=>int, 'mime-type'=>string}
   364 	 */
   362 	 */
   409 		$stat = stat( dirname( $filename ) );
   407 		$stat = stat( dirname( $filename ) );
   410 		$perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits
   408 		$perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits
   411 		@ chmod( $filename, $perms );
   409 		@ chmod( $filename, $perms );
   412 
   410 
   413 		/**
   411 		/**
   414 		 * Filter the name of the saved image file.
   412 		 * Filters the name of the saved image file.
   415 		 *
   413 		 *
   416 		 * @since 2.6.0
   414 		 * @since 2.6.0
   417 		 *
   415 		 *
   418 		 * @param string $filename Name of the file.
   416 		 * @param string $filename Name of the file.
   419 		 */
   417 		 */
   428 
   426 
   429 	/**
   427 	/**
   430 	 * Returns stream of current image.
   428 	 * Returns stream of current image.
   431 	 *
   429 	 *
   432 	 * @since 3.5.0
   430 	 * @since 3.5.0
   433 	 * @access public
   431 	 *
   434 	 *
   432 	 * @param string $mime_type The mime type of the image.
   435 	 * @param string $mime_type
   433 	 * @return bool True on success, false on failure.
   436 	 */
   434 	 */
   437 	public function stream( $mime_type = null ) {
   435 	public function stream( $mime_type = null ) {
   438 		list( $filename, $extension, $mime_type ) = $this->get_output_format( null, $mime_type );
   436 		list( $filename, $extension, $mime_type ) = $this->get_output_format( null, $mime_type );
   439 
   437 
   440 		switch ( $mime_type ) {
   438 		switch ( $mime_type ) {
   452 
   450 
   453 	/**
   451 	/**
   454 	 * Either calls editor's save function or handles file as a stream.
   452 	 * Either calls editor's save function or handles file as a stream.
   455 	 *
   453 	 *
   456 	 * @since 3.5.0
   454 	 * @since 3.5.0
   457 	 * @access protected
       
   458 	 *
   455 	 *
   459 	 * @param string|stream $filename
   456 	 * @param string|stream $filename
   460 	 * @param callable $function
   457 	 * @param callable $function
   461 	 * @param array $arguments
   458 	 * @param array $arguments
   462 	 * @return boolean
   459 	 * @return bool
   463 	 */
   460 	 */
   464 	protected function make_image( $filename, $function, $arguments ) {
   461 	protected function make_image( $filename, $function, $arguments ) {
   465 		if ( wp_is_stream( $filename ) )
   462 		if ( wp_is_stream( $filename ) )
   466 			$arguments[1] = null;
   463 			$arguments[1] = null;
   467 
   464