wp/wp-includes/class-wp-image-editor-gd.php
changeset 5 5e2f62d02dcd
parent 0 d970ebf37754
child 7 cf61fcea0001
equal deleted inserted replaced
4:346c88efed21 5:5e2f62d02dcd
    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_GD extends WP_Image_Editor {
    17 class WP_Image_Editor_GD extends WP_Image_Editor {
    18 
    18 	/**
    19 	protected $image = false; // GD Resource
    19 	 * @var resource
    20 
    20 	 */
    21 	function __destruct() {
    21 	protected $image; // GD Resource
       
    22 
       
    23 	public function __destruct() {
    22 		if ( $this->image ) {
    24 		if ( $this->image ) {
    23 			// we don't need the original in memory anymore
    25 			// we don't need the original in memory anymore
    24 			imagedestroy( $this->image );
    26 			imagedestroy( $this->image );
    25 		}
    27 		}
    26 	}
    28 	}
    75 	 * Loads image from $this->file into new GD Resource.
    77 	 * Loads image from $this->file into new GD Resource.
    76 	 *
    78 	 *
    77 	 * @since 3.5.0
    79 	 * @since 3.5.0
    78 	 * @access protected
    80 	 * @access protected
    79 	 *
    81 	 *
    80 	 * @return boolean|\WP_Error
    82 	 * @return boolean|WP_Error True if loaded successfully; WP_Error on failure.
    81 	 */
    83 	 */
    82 	public function load() {
    84 	public function load() {
    83 		if ( $this->image )
    85 		if ( $this->image )
    84 			return true;
    86 			return true;
    85 
    87 
    86 		if ( ! is_file( $this->file ) && ! preg_match( '|^https?://|', $this->file ) )
    88 		if ( ! is_file( $this->file ) && ! preg_match( '|^https?://|', $this->file ) )
    87 			return new WP_Error( 'error_loading_image', __('File doesn’t exist?'), $this->file );
    89 			return new WP_Error( 'error_loading_image', __('File doesn’t exist?'), $this->file );
    88 
    90 
       
    91 		/**
       
    92 		 * Filter the memory limit allocated for image manipulation.
       
    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 		 */
    89 		// Set artificially high because GD uses uncompressed images in memory
    99 		// Set artificially high because GD uses uncompressed images in memory
    90 		@ini_set( 'memory_limit', apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT ) );
   100 		@ini_set( 'memory_limit', apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT ) );
       
   101 
    91 		$this->image = @imagecreatefromstring( file_get_contents( $this->file ) );
   102 		$this->image = @imagecreatefromstring( file_get_contents( $this->file ) );
    92 
   103 
    93 		if ( ! is_resource( $this->image ) )
   104 		if ( ! is_resource( $this->image ) )
    94 			return new WP_Error( 'invalid_image', __('File is not an image.'), $this->file );
   105 			return new WP_Error( 'invalid_image', __('File is not an image.'), $this->file );
    95 
   106 
   103 		}
   114 		}
   104 
   115 
   105 		$this->update_size( $size[0], $size[1] );
   116 		$this->update_size( $size[0], $size[1] );
   106 		$this->mime_type = $size['mime'];
   117 		$this->mime_type = $size['mime'];
   107 
   118 
   108 		return true;
   119 		return $this->set_quality();
   109 	}
   120 	}
   110 
   121 
   111 	/**
   122 	/**
   112 	 * Sets or updates current image size.
   123 	 * Sets or updates current image size.
   113 	 *
   124 	 *
   129 
   140 
   130 	/**
   141 	/**
   131 	 * Resizes current image.
   142 	 * Resizes current image.
   132 	 * Wraps _resize, since _resize returns a GD Resource.
   143 	 * Wraps _resize, since _resize returns a GD Resource.
   133 	 *
   144 	 *
   134 	 * @since 3.5.0
   145 	 * At minimum, either a height or width must be provided.
   135 	 * @access public
   146 	 * If one of the two is set to null, the resize will
   136 	 *
   147 	 * maintain aspect ratio according to the provided dimension.
   137 	 * @param int $max_w
   148 	 *
   138 	 * @param int $max_h
   149 	 * @since 3.5.0
   139 	 * @param boolean $crop
   150 	 * @access public
       
   151 	 *
       
   152 	 * @param  int|null $max_w Image width.
       
   153 	 * @param  int|null $max_h Image height.
       
   154 	 * @param  boolean  $crop
   140 	 * @return boolean|WP_Error
   155 	 * @return boolean|WP_Error
   141 	 */
   156 	 */
   142 	public function resize( $max_w, $max_h, $crop = false ) {
   157 	public function resize( $max_w, $max_h, $crop = false ) {
   143 		if ( ( $this->size['width'] == $max_w ) && ( $this->size['height'] == $max_h ) )
   158 		if ( ( $this->size['width'] == $max_w ) && ( $this->size['height'] == $max_h ) )
   144 			return true;
   159 			return true;
   181 	 * @access public
   196 	 * @access public
   182 	 *
   197 	 *
   183 	 * @param array $sizes {
   198 	 * @param array $sizes {
   184 	 *     An array of image size arrays. Default sizes are 'small', 'medium', 'large'.
   199 	 *     An array of image size arrays. Default sizes are 'small', 'medium', 'large'.
   185 	 *
   200 	 *
       
   201 	 *     Either a height or width must be provided.
       
   202 	 *     If one of the two is set to null, the resize will
       
   203 	 *     maintain aspect ratio according to the provided dimension.
       
   204 	 *
   186 	 *     @type array $size {
   205 	 *     @type array $size {
   187 	 *         @type int  $width  Image width.
   206 	 *         @type int  ['width']  Optional. Image width.
   188 	 *         @type int  $height Image height.
   207 	 *         @type int  ['height'] Optional. Image height.
   189 	 *         @type bool $crop   Optional. Whether to crop the image. Default false.
   208 	 *         @type bool ['crop']   Optional. Whether to crop the image. Default false.
   190 	 *     }
   209 	 *     }
   191 	 * }
   210 	 * }
   192 	 * @return array An array of resized images metadata by size.
   211 	 * @return array An array of resized images' metadata by size.
   193 	 */
   212 	 */
   194 	public function multi_resize( $sizes ) {
   213 	public function multi_resize( $sizes ) {
   195 		$metadata = array();
   214 		$metadata = array();
   196 		$orig_size = $this->size;
   215 		$orig_size = $this->size;
   197 
   216 
   198 		foreach ( $sizes as $size => $size_data ) {
   217 		foreach ( $sizes as $size => $size_data ) {
   199 			if ( ! ( isset( $size_data['width'] ) && isset( $size_data['height'] ) ) )
   218 			if ( ! isset( $size_data['width'] ) && ! isset( $size_data['height'] ) ) {
   200 				continue;
   219 				continue;
   201 
   220 			}
   202 			if ( ! isset( $size_data['crop'] ) )
   221 
       
   222 			if ( ! isset( $size_data['width'] ) ) {
       
   223 				$size_data['width'] = null;
       
   224 			}
       
   225 			if ( ! isset( $size_data['height'] ) ) {
       
   226 				$size_data['height'] = null;
       
   227 			}
       
   228 
       
   229 			if ( ! isset( $size_data['crop'] ) ) {
   203 				$size_data['crop'] = false;
   230 				$size_data['crop'] = false;
       
   231 			}
   204 
   232 
   205 			$image = $this->_resize( $size_data['width'], $size_data['height'], $size_data['crop'] );
   233 			$image = $this->_resize( $size_data['width'], $size_data['height'], $size_data['crop'] );
   206 
   234 			$duplicate = ( ( $orig_size['width'] == $size_data['width'] ) && ( $orig_size['height'] == $size_data['height'] ) );
   207 			if( ! is_wp_error( $image ) ) {
   235 
       
   236 			if ( ! is_wp_error( $image ) && ! $duplicate ) {
   208 				$resized = $this->_save( $image );
   237 				$resized = $this->_save( $image );
   209 
   238 
   210 				imagedestroy( $image );
   239 				imagedestroy( $image );
   211 
   240 
   212 				if ( ! is_wp_error( $resized ) && $resized ) {
   241 				if ( ! is_wp_error( $resized ) && $resized ) {
   225 	 * Crops Image.
   254 	 * Crops Image.
   226 	 *
   255 	 *
   227 	 * @since 3.5.0
   256 	 * @since 3.5.0
   228 	 * @access public
   257 	 * @access public
   229 	 *
   258 	 *
   230 	 * @param string|int $src The source file or Attachment ID.
       
   231 	 * @param int $src_x The start x position to crop from.
   259 	 * @param int $src_x The start x position to crop from.
   232 	 * @param int $src_y The start y position to crop from.
   260 	 * @param int $src_y The start y position to crop from.
   233 	 * @param int $src_w The width to crop.
   261 	 * @param int $src_w The width to crop.
   234 	 * @param int $src_h The height to crop.
   262 	 * @param int $src_h The height to crop.
   235 	 * @param int $dst_w Optional. The destination width.
   263 	 * @param int $dst_w Optional. The destination width.
   277 	 * @param float $angle
   305 	 * @param float $angle
   278 	 * @return boolean|WP_Error
   306 	 * @return boolean|WP_Error
   279 	 */
   307 	 */
   280 	public function rotate( $angle ) {
   308 	public function rotate( $angle ) {
   281 		if ( function_exists('imagerotate') ) {
   309 		if ( function_exists('imagerotate') ) {
   282 			$rotated = imagerotate( $this->image, $angle, 0 );
   310 			$transparency = imagecolorallocatealpha( $this->image, 255, 255, 255, 127 );
       
   311 			$rotated = imagerotate( $this->image, $angle, $transparency );
   283 
   312 
   284 			if ( is_resource( $rotated ) ) {
   313 			if ( is_resource( $rotated ) ) {
       
   314 				imagealphablending( $rotated, true );
       
   315 				imagesavealpha( $rotated, true );
   285 				imagedestroy( $this->image );
   316 				imagedestroy( $this->image );
   286 				$this->image = $rotated;
   317 				$this->image = $rotated;
   287 				$this->update_size();
   318 				$this->update_size();
   288 				return true;
   319 				return true;
   289 			}
   320 			}
   325 	 * Saves current in-memory image to file.
   356 	 * Saves current in-memory image to file.
   326 	 *
   357 	 *
   327 	 * @since 3.5.0
   358 	 * @since 3.5.0
   328 	 * @access public
   359 	 * @access public
   329 	 *
   360 	 *
   330 	 * @param string $destfilename
   361 	 * @param string|null $filename
   331 	 * @param string $mime_type
   362 	 * @param string|null $mime_type
   332 	 * @return array|WP_Error {'path'=>string, 'file'=>string, 'width'=>int, 'height'=>int, 'mime-type'=>string}
   363 	 * @return array|WP_Error {'path'=>string, 'file'=>string, 'width'=>int, 'height'=>int, 'mime-type'=>string}
   333 	 */
   364 	 */
   334 	public function save( $filename = null, $mime_type = null ) {
   365 	public function save( $filename = null, $mime_type = null ) {
   335 		$saved = $this->_save( $this->image, $filename, $mime_type );
   366 		$saved = $this->_save( $this->image, $filename, $mime_type );
   336 
   367 
   340 		}
   371 		}
   341 
   372 
   342 		return $saved;
   373 		return $saved;
   343 	}
   374 	}
   344 
   375 
       
   376 	/**
       
   377 	 * @param resource $image
       
   378 	 * @param string|null $filename
       
   379 	 * @param string|null $mime_type
       
   380 	 * @return WP_Error|array
       
   381 	 */
   345 	protected function _save( $image, $filename = null, $mime_type = null ) {
   382 	protected function _save( $image, $filename = null, $mime_type = null ) {
   346 		list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
   383 		list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
   347 
   384 
   348 		if ( ! $filename )
   385 		if ( ! $filename )
   349 			$filename = $this->generate_filename( null, null, $extension );
   386 			$filename = $this->generate_filename( null, null, $extension );
   359 
   396 
   360 			if ( ! $this->make_image( $filename, 'imagepng', array( $image, $filename ) ) )
   397 			if ( ! $this->make_image( $filename, 'imagepng', array( $image, $filename ) ) )
   361 				return new WP_Error( 'image_save_error', __('Image Editor Save Failed') );
   398 				return new WP_Error( 'image_save_error', __('Image Editor Save Failed') );
   362 		}
   399 		}
   363 		elseif ( 'image/jpeg' == $mime_type ) {
   400 		elseif ( 'image/jpeg' == $mime_type ) {
   364 			if ( ! $this->make_image( $filename, 'imagejpeg', array( $image, $filename, apply_filters( 'jpeg_quality', $this->quality, 'image_resize' ) ) ) )
   401 			if ( ! $this->make_image( $filename, 'imagejpeg', array( $image, $filename, $this->get_quality() ) ) )
   365 				return new WP_Error( 'image_save_error', __('Image Editor Save Failed') );
   402 				return new WP_Error( 'image_save_error', __('Image Editor Save Failed') );
   366 		}
   403 		}
   367 		else {
   404 		else {
   368 			return new WP_Error( 'image_save_error', __('Image Editor Save Failed') );
   405 			return new WP_Error( 'image_save_error', __('Image Editor Save Failed') );
   369 		}
   406 		}
   371 		// Set correct file permissions
   408 		// Set correct file permissions
   372 		$stat = stat( dirname( $filename ) );
   409 		$stat = stat( dirname( $filename ) );
   373 		$perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits
   410 		$perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits
   374 		@ chmod( $filename, $perms );
   411 		@ chmod( $filename, $perms );
   375 
   412 
       
   413 		/**
       
   414 		 * Filter the name of the saved image file.
       
   415 		 *
       
   416 		 * @since 2.6.0
       
   417 		 *
       
   418 		 * @param string $filename Name of the file.
       
   419 		 */
   376 		return array(
   420 		return array(
   377 			'path' => $filename,
   421 			'path'      => $filename,
   378 			'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
   422 			'file'      => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
   379 			'width' => $this->size['width'],
   423 			'width'     => $this->size['width'],
   380 			'height' => $this->size['height'],
   424 			'height'    => $this->size['height'],
   381 			'mime-type'=> $mime_type,
   425 			'mime-type' => $mime_type,
   382 		);
   426 		);
   383 	}
   427 	}
   384 
   428 
   385 	/**
   429 	/**
   386 	 * Returns stream of current image.
   430 	 * Returns stream of current image.
   400 			case 'image/gif':
   444 			case 'image/gif':
   401 				header( 'Content-Type: image/gif' );
   445 				header( 'Content-Type: image/gif' );
   402 				return imagegif( $this->image );
   446 				return imagegif( $this->image );
   403 			default:
   447 			default:
   404 				header( 'Content-Type: image/jpeg' );
   448 				header( 'Content-Type: image/jpeg' );
   405 				return imagejpeg( $this->image, null, $this->quality );
   449 				return imagejpeg( $this->image, null, $this->get_quality() );
   406 		}
   450 		}
   407 	}
   451 	}
   408 
   452 
   409 	/**
   453 	/**
   410 	 * Either calls editor's save function or handles file as a stream.
   454 	 * Either calls editor's save function or handles file as a stream.