wp/wp-includes/class-wp-image-editor-imagick.php
changeset 9 177826044cd9
parent 7 cf61fcea0001
child 16 a86126ab1dd4
equal deleted inserted replaced
8:c7c34916027a 9:177826044cd9
    35 	 * We require Imagick 2.2.0 or greater, based on whether the queryFormats()
    35 	 * We require Imagick 2.2.0 or greater, based on whether the queryFormats()
    36 	 * method can be called statically.
    36 	 * method can be called statically.
    37 	 *
    37 	 *
    38 	 * @since 3.5.0
    38 	 * @since 3.5.0
    39 	 *
    39 	 *
    40 	 * @static
       
    41 	 *
       
    42 	 * @param array $args
    40 	 * @param array $args
    43 	 * @return bool
    41 	 * @return bool
    44 	 */
    42 	 */
    45 	public static function test( $args = array() ) {
    43 	public static function test( $args = array() ) {
    46 
    44 
    47 		// First, test Imagick's extension and classes.
    45 		// First, test Imagick's extension and classes.
    48 		if ( ! extension_loaded( 'imagick' ) || ! class_exists( 'Imagick', false ) || ! class_exists( 'ImagickPixel', false ) )
    46 		if ( ! extension_loaded( 'imagick' ) || ! class_exists( 'Imagick', false ) || ! class_exists( 'ImagickPixel', false ) ) {
    49 			return false;
    47 			return false;
    50 
    48 		}
    51 		if ( version_compare( phpversion( 'imagick' ), '2.2.0', '<' ) )
    49 
       
    50 		if ( version_compare( phpversion( 'imagick' ), '2.2.0', '<' ) ) {
    52 			return false;
    51 			return false;
       
    52 		}
    53 
    53 
    54 		$required_methods = array(
    54 		$required_methods = array(
    55 			'clear',
    55 			'clear',
    56 			'destroy',
    56 			'destroy',
    57 			'valid',
    57 			'valid',
    72 			'flopimage',
    72 			'flopimage',
    73 			'readimage',
    73 			'readimage',
    74 		);
    74 		);
    75 
    75 
    76 		// Now, test for deep requirements within Imagick.
    76 		// Now, test for deep requirements within Imagick.
    77 		if ( ! defined( 'imagick::COMPRESSION_JPEG' ) )
    77 		if ( ! defined( 'imagick::COMPRESSION_JPEG' ) ) {
    78 			return false;
    78 			return false;
       
    79 		}
    79 
    80 
    80 		$class_methods = array_map( 'strtolower', get_class_methods( 'Imagick' ) );
    81 		$class_methods = array_map( 'strtolower', get_class_methods( 'Imagick' ) );
    81 		if ( array_diff( $required_methods, $class_methods ) ) {
    82 		if ( array_diff( $required_methods, $class_methods ) ) {
    82 			return false;
    83 			return false;
    83 		}
    84 		}
    93 	/**
    94 	/**
    94 	 * Checks to see if editor supports the mime-type specified.
    95 	 * Checks to see if editor supports the mime-type specified.
    95 	 *
    96 	 *
    96 	 * @since 3.5.0
    97 	 * @since 3.5.0
    97 	 *
    98 	 *
    98 	 * @static
       
    99 	 *
       
   100 	 * @param string $mime_type
    99 	 * @param string $mime_type
   101 	 * @return bool
   100 	 * @return bool
   102 	 */
   101 	 */
   103 	public static function supports_mime_type( $mime_type ) {
   102 	public static function supports_mime_type( $mime_type ) {
   104 		$imagick_extension = strtoupper( self::get_extension( $mime_type ) );
   103 		$imagick_extension = strtoupper( self::get_extension( $mime_type ) );
   105 
   104 
   106 		if ( ! $imagick_extension )
   105 		if ( ! $imagick_extension ) {
   107 			return false;
   106 			return false;
       
   107 		}
   108 
   108 
   109 		// setIteratorIndex is optional unless mime is an animated format.
   109 		// setIteratorIndex is optional unless mime is an animated format.
   110 		// Here, we just say no if you are missing it and aren't loading a jpeg.
   110 		// Here, we just say no if you are missing it and aren't loading a jpeg.
   111 		if ( ! method_exists( 'Imagick', 'setIteratorIndex' ) && $mime_type != 'image/jpeg' )
   111 		if ( ! method_exists( 'Imagick', 'setIteratorIndex' ) && $mime_type != 'image/jpeg' ) {
   112 				return false;
   112 				return false;
       
   113 		}
   113 
   114 
   114 		try {
   115 		try {
   115 			return ( (bool) @Imagick::queryFormats( $imagick_extension ) );
   116 			return ( (bool) @Imagick::queryFormats( $imagick_extension ) );
   116 		}
   117 		} catch ( Exception $e ) {
   117 		catch ( Exception $e ) {
       
   118 			return false;
   118 			return false;
   119 		}
   119 		}
   120 	}
   120 	}
   121 
   121 
   122 	/**
   122 	/**
   125 	 * @since 3.5.0
   125 	 * @since 3.5.0
   126 	 *
   126 	 *
   127 	 * @return true|WP_Error True if loaded; WP_Error on failure.
   127 	 * @return true|WP_Error True if loaded; WP_Error on failure.
   128 	 */
   128 	 */
   129 	public function load() {
   129 	public function load() {
   130 		if ( $this->image instanceof Imagick )
   130 		if ( $this->image instanceof Imagick ) {
   131 			return true;
   131 			return true;
   132 
   132 		}
   133 		if ( ! is_file( $this->file ) && ! preg_match( '|^https?://|', $this->file ) )
   133 
   134 			return new WP_Error( 'error_loading_image', __('File doesn&#8217;t exist?'), $this->file );
   134 		if ( ! is_file( $this->file ) && ! preg_match( '|^https?://|', $this->file ) ) {
       
   135 			return new WP_Error( 'error_loading_image', __( 'File doesn&#8217;t exist?' ), $this->file );
       
   136 		}
   135 
   137 
   136 		/*
   138 		/*
   137 		 * Even though Imagick uses less PHP memory than GD, set higher limit
   139 		 * Even though Imagick uses less PHP memory than GD, set higher limit
   138 		 * for users that have low PHP.ini limits.
   140 		 * for users that have low PHP.ini limits.
   139 		 */
   141 		 */
   140 		wp_raise_memory_limit( 'image' );
   142 		wp_raise_memory_limit( 'image' );
   141 
   143 
   142 		try {
   144 		try {
   143 			$this->image = new Imagick();
   145 			$this->image    = new Imagick();
   144 			$file_extension = strtolower( pathinfo( $this->file, PATHINFO_EXTENSION ) );
   146 			$file_extension = strtolower( pathinfo( $this->file, PATHINFO_EXTENSION ) );
   145 			$filename = $this->file;
   147 			$filename       = $this->file;
   146 
   148 
   147 			if ( 'pdf' == $file_extension ) {
   149 			if ( 'pdf' == $file_extension ) {
   148 				$filename = $this->pdf_setup();
   150 				$filename = $this->pdf_setup();
   149 			}
   151 			}
   150 
   152 
   151 			// Reading image after Imagick instantiation because `setResolution`
   153 			// Reading image after Imagick instantiation because `setResolution`
   152 			// only applies correctly before the image is read.
   154 			// only applies correctly before the image is read.
   153 			$this->image->readImage( $filename );
   155 			$this->image->readImage( $filename );
   154 
   156 
   155 			if ( ! $this->image->valid() )
   157 			if ( ! $this->image->valid() ) {
   156 				return new WP_Error( 'invalid_image', __('File is not an image.'), $this->file);
   158 				return new WP_Error( 'invalid_image', __( 'File is not an image.' ), $this->file );
       
   159 			}
   157 
   160 
   158 			// Select the first frame to handle animated images properly
   161 			// Select the first frame to handle animated images properly
   159 			if ( is_callable( array( $this->image, 'setIteratorIndex' ) ) )
   162 			if ( is_callable( array( $this->image, 'setIteratorIndex' ) ) ) {
   160 				$this->image->setIteratorIndex(0);
   163 				$this->image->setIteratorIndex( 0 );
       
   164 			}
   161 
   165 
   162 			$this->mime_type = $this->get_mime_type( $this->image->getImageFormat() );
   166 			$this->mime_type = $this->get_mime_type( $this->image->getImageFormat() );
   163 		}
   167 		} catch ( Exception $e ) {
   164 		catch ( Exception $e ) {
       
   165 			return new WP_Error( 'invalid_image', $e->getMessage(), $this->file );
   168 			return new WP_Error( 'invalid_image', $e->getMessage(), $this->file );
   166 		}
   169 		}
   167 
   170 
   168 		$updated_size = $this->update_size();
   171 		$updated_size = $this->update_size();
   169 		if ( is_wp_error( $updated_size ) ) {
   172 		if ( is_wp_error( $updated_size ) ) {
   191 
   194 
   192 		try {
   195 		try {
   193 			if ( 'image/jpeg' == $this->mime_type ) {
   196 			if ( 'image/jpeg' == $this->mime_type ) {
   194 				$this->image->setImageCompressionQuality( $quality );
   197 				$this->image->setImageCompressionQuality( $quality );
   195 				$this->image->setImageCompression( imagick::COMPRESSION_JPEG );
   198 				$this->image->setImageCompression( imagick::COMPRESSION_JPEG );
   196 			}
   199 			} else {
   197 			else {
       
   198 				$this->image->setImageCompressionQuality( $quality );
   200 				$this->image->setImageCompressionQuality( $quality );
   199 			}
   201 			}
   200 		}
   202 		} catch ( Exception $e ) {
   201 		catch ( Exception $e ) {
       
   202 			return new WP_Error( 'image_quality_error', $e->getMessage() );
   203 			return new WP_Error( 'image_quality_error', $e->getMessage() );
   203 		}
   204 		}
   204 
   205 
   205 		return true;
   206 		return true;
   206 	}
   207 	}
   215 	 *
   216 	 *
   216 	 * @return true|WP_Error
   217 	 * @return true|WP_Error
   217 	 */
   218 	 */
   218 	protected function update_size( $width = null, $height = null ) {
   219 	protected function update_size( $width = null, $height = null ) {
   219 		$size = null;
   220 		$size = null;
   220 		if ( !$width || !$height ) {
   221 		if ( ! $width || ! $height ) {
   221 			try {
   222 			try {
   222 				$size = $this->image->getImageGeometry();
   223 				$size = $this->image->getImageGeometry();
   223 			}
   224 			} catch ( Exception $e ) {
   224 			catch ( Exception $e ) {
       
   225 				return new WP_Error( 'invalid_image', __( 'Could not read image size.' ), $this->file );
   225 				return new WP_Error( 'invalid_image', __( 'Could not read image size.' ), $this->file );
   226 			}
   226 			}
   227 		}
   227 		}
   228 
   228 
   229 		if ( ! $width )
   229 		if ( ! $width ) {
   230 			$width = $size['width'];
   230 			$width = $size['width'];
   231 
   231 		}
   232 		if ( ! $height )
   232 
       
   233 		if ( ! $height ) {
   233 			$height = $size['height'];
   234 			$height = $size['height'];
       
   235 		}
   234 
   236 
   235 		return parent::update_size( $width, $height );
   237 		return parent::update_size( $width, $height );
   236 	}
   238 	}
   237 
   239 
   238 	/**
   240 	/**
   248 	 * @param  int|null $max_h Image height.
   250 	 * @param  int|null $max_h Image height.
   249 	 * @param  bool     $crop
   251 	 * @param  bool     $crop
   250 	 * @return bool|WP_Error
   252 	 * @return bool|WP_Error
   251 	 */
   253 	 */
   252 	public function resize( $max_w, $max_h, $crop = false ) {
   254 	public function resize( $max_w, $max_h, $crop = false ) {
   253 		if ( ( $this->size['width'] == $max_w ) && ( $this->size['height'] == $max_h ) )
   255 		if ( ( $this->size['width'] == $max_w ) && ( $this->size['height'] == $max_h ) ) {
   254 			return true;
   256 			return true;
       
   257 		}
   255 
   258 
   256 		$dims = image_resize_dimensions( $this->size['width'], $this->size['height'], $max_w, $max_h, $crop );
   259 		$dims = image_resize_dimensions( $this->size['width'], $this->size['height'], $max_w, $max_h, $crop );
   257 		if ( ! $dims )
   260 		if ( ! $dims ) {
   258 			return new WP_Error( 'error_getting_dimensions', __('Could not calculate resized image dimensions') );
   261 			return new WP_Error( 'error_getting_dimensions', __( 'Could not calculate resized image dimensions' ) );
       
   262 		}
   259 		list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dims;
   263 		list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dims;
   260 
   264 
   261 		if ( $crop ) {
   265 		if ( $crop ) {
   262 			return $this->crop( $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h );
   266 			return $this->crop( $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h );
   263 		}
   267 		}
   333 			 * To be more efficient, resample large images to 5x the destination size before resizing
   337 			 * To be more efficient, resample large images to 5x the destination size before resizing
   334 			 * whenever the output size is less that 1/3 of the original image size (1/3^2 ~= .111),
   338 			 * whenever the output size is less that 1/3 of the original image size (1/3^2 ~= .111),
   335 			 * unless we would be resampling to a scale smaller than 128x128.
   339 			 * unless we would be resampling to a scale smaller than 128x128.
   336 			 */
   340 			 */
   337 			if ( is_callable( array( $this->image, 'sampleImage' ) ) ) {
   341 			if ( is_callable( array( $this->image, 'sampleImage' ) ) ) {
   338 				$resize_ratio = ( $dst_w / $this->size['width'] ) * ( $dst_h / $this->size['height'] );
   342 				$resize_ratio  = ( $dst_w / $this->size['width'] ) * ( $dst_h / $this->size['height'] );
   339 				$sample_factor = 5;
   343 				$sample_factor = 5;
   340 
   344 
   341 				if ( $resize_ratio < .111 && ( $dst_w * $sample_factor > 128 && $dst_h * $sample_factor > 128 ) ) {
   345 				if ( $resize_ratio < .111 && ( $dst_w * $sample_factor > 128 && $dst_h * $sample_factor > 128 ) ) {
   342 					$this->image->sampleImage( $dst_w * $sample_factor, $dst_h * $sample_factor );
   346 					$this->image->sampleImage( $dst_w * $sample_factor, $dst_h * $sample_factor );
   343 				}
   347 				}
   396 			}
   400 			}
   397 
   401 
   398 			if ( is_callable( array( $this->image, 'setInterlaceScheme' ) ) && defined( 'Imagick::INTERLACE_NO' ) ) {
   402 			if ( is_callable( array( $this->image, 'setInterlaceScheme' ) ) && defined( 'Imagick::INTERLACE_NO' ) ) {
   399 				$this->image->setInterlaceScheme( Imagick::INTERLACE_NO );
   403 				$this->image->setInterlaceScheme( Imagick::INTERLACE_NO );
   400 			}
   404 			}
   401 
   405 		} catch ( Exception $e ) {
   402 		}
       
   403 		catch ( Exception $e ) {
       
   404 			return new WP_Error( 'image_resize_error', $e->getMessage() );
   406 			return new WP_Error( 'image_resize_error', $e->getMessage() );
   405 		}
   407 		}
   406 	}
   408 	}
   407 
   409 
   408 	/**
   410 	/**
   426 	 *     }
   428 	 *     }
   427 	 * }
   429 	 * }
   428 	 * @return array An array of resized images' metadata by size.
   430 	 * @return array An array of resized images' metadata by size.
   429 	 */
   431 	 */
   430 	public function multi_resize( $sizes ) {
   432 	public function multi_resize( $sizes ) {
   431 		$metadata = array();
   433 		$metadata   = array();
   432 		$orig_size = $this->size;
   434 		$orig_size  = $this->size;
   433 		$orig_image = $this->image->getImage();
   435 		$orig_image = $this->image->getImage();
   434 
   436 
   435 		foreach ( $sizes as $size => $size_data ) {
   437 		foreach ( $sizes as $size => $size_data ) {
   436 			if ( ! $this->image )
   438 			if ( ! $this->image ) {
   437 				$this->image = $orig_image->getImage();
   439 				$this->image = $orig_image->getImage();
       
   440 			}
   438 
   441 
   439 			if ( ! isset( $size_data['width'] ) && ! isset( $size_data['height'] ) ) {
   442 			if ( ! isset( $size_data['width'] ) && ! isset( $size_data['height'] ) ) {
   440 				continue;
   443 				continue;
   441 			}
   444 			}
   442 
   445 
   450 			if ( ! isset( $size_data['crop'] ) ) {
   453 			if ( ! isset( $size_data['crop'] ) ) {
   451 				$size_data['crop'] = false;
   454 				$size_data['crop'] = false;
   452 			}
   455 			}
   453 
   456 
   454 			$resize_result = $this->resize( $size_data['width'], $size_data['height'], $size_data['crop'] );
   457 			$resize_result = $this->resize( $size_data['width'], $size_data['height'], $size_data['crop'] );
   455 			$duplicate = ( ( $orig_size['width'] == $size_data['width'] ) && ( $orig_size['height'] == $size_data['height'] ) );
   458 			$duplicate     = ( ( $orig_size['width'] == $size_data['width'] ) && ( $orig_size['height'] == $size_data['height'] ) );
   456 
   459 
   457 			if ( ! is_wp_error( $resize_result ) && ! $duplicate ) {
   460 			if ( ! is_wp_error( $resize_result ) && ! $duplicate ) {
   458 				$resized = $this->_save( $this->image );
   461 				$resized = $this->_save( $this->image );
   459 
   462 
   460 				$this->image->clear();
   463 				$this->image->clear();
   461 				$this->image->destroy();
   464 				$this->image->destroy();
   462 				$this->image = null;
   465 				$this->image = null;
   463 
   466 
   464 				if ( ! is_wp_error( $resized ) && $resized ) {
   467 				if ( ! is_wp_error( $resized ) && $resized ) {
   465 					unset( $resized['path'] );
   468 					unset( $resized['path'] );
   466 					$metadata[$size] = $resized;
   469 					$metadata[ $size ] = $resized;
   467 				}
   470 				}
   468 			}
   471 			}
   469 
   472 
   470 			$this->size = $orig_size;
   473 			$this->size = $orig_size;
   471 		}
   474 		}
   495 			$src_h -= $src_y;
   498 			$src_h -= $src_y;
   496 		}
   499 		}
   497 
   500 
   498 		try {
   501 		try {
   499 			$this->image->cropImage( $src_w, $src_h, $src_x, $src_y );
   502 			$this->image->cropImage( $src_w, $src_h, $src_x, $src_y );
   500 			$this->image->setImagePage( $src_w, $src_h, 0, 0);
   503 			$this->image->setImagePage( $src_w, $src_h, 0, 0 );
   501 
   504 
   502 			if ( $dst_w || $dst_h ) {
   505 			if ( $dst_w || $dst_h ) {
   503 				// If destination width/height isn't specified, use same as
   506 				// If destination width/height isn't specified, use same as
   504 				// width/height from source.
   507 				// width/height from source.
   505 				if ( ! $dst_w )
   508 				if ( ! $dst_w ) {
   506 					$dst_w = $src_w;
   509 					$dst_w = $src_w;
   507 				if ( ! $dst_h )
   510 				}
       
   511 				if ( ! $dst_h ) {
   508 					$dst_h = $src_h;
   512 					$dst_h = $src_h;
       
   513 				}
   509 
   514 
   510 				$thumb_result = $this->thumbnail_image( $dst_w, $dst_h );
   515 				$thumb_result = $this->thumbnail_image( $dst_w, $dst_h );
   511 				if ( is_wp_error( $thumb_result ) ) {
   516 				if ( is_wp_error( $thumb_result ) ) {
   512 					return $thumb_result;
   517 					return $thumb_result;
   513 				}
   518 				}
   514 
   519 
   515 				return $this->update_size();
   520 				return $this->update_size();
   516 			}
   521 			}
   517 		}
   522 		} catch ( Exception $e ) {
   518 		catch ( Exception $e ) {
       
   519 			return new WP_Error( 'image_crop_error', $e->getMessage() );
   523 			return new WP_Error( 'image_crop_error', $e->getMessage() );
   520 		}
   524 		}
   521 		return $this->update_size();
   525 		return $this->update_size();
   522 	}
   526 	}
   523 
   527 
   533 		/**
   537 		/**
   534 		 * $angle is 360-$angle because Imagick rotates clockwise
   538 		 * $angle is 360-$angle because Imagick rotates clockwise
   535 		 * (GD rotates counter-clockwise)
   539 		 * (GD rotates counter-clockwise)
   536 		 */
   540 		 */
   537 		try {
   541 		try {
   538 			$this->image->rotateImage( new ImagickPixel('none'), 360-$angle );
   542 			$this->image->rotateImage( new ImagickPixel( 'none' ), 360 - $angle );
   539 
   543 
   540 			// Normalise Exif orientation data so that display is consistent across devices.
   544 			// Normalise Exif orientation data so that display is consistent across devices.
   541 			if ( is_callable( array( $this->image, 'setImageOrientation' ) ) && defined( 'Imagick::ORIENTATION_TOPLEFT' ) ) {
   545 			if ( is_callable( array( $this->image, 'setImageOrientation' ) ) && defined( 'Imagick::ORIENTATION_TOPLEFT' ) ) {
   542 				$this->image->setImageOrientation( Imagick::ORIENTATION_TOPLEFT );
   546 				$this->image->setImageOrientation( Imagick::ORIENTATION_TOPLEFT );
   543 			}
   547 			}
   544 
   548 
   545 			// Since this changes the dimensions of the image, update the size.
   549 			// Since this changes the dimensions of the image, update the size.
   546 			$result = $this->update_size();
   550 			$result = $this->update_size();
   547 			if ( is_wp_error( $result ) )
   551 			if ( is_wp_error( $result ) ) {
   548 				return $result;
   552 				return $result;
       
   553 			}
   549 
   554 
   550 			$this->image->setImagePage( $this->size['width'], $this->size['height'], 0, 0 );
   555 			$this->image->setImagePage( $this->size['width'], $this->size['height'], 0, 0 );
   551 		}
   556 		} catch ( Exception $e ) {
   552 		catch ( Exception $e ) {
       
   553 			return new WP_Error( 'image_rotate_error', $e->getMessage() );
   557 			return new WP_Error( 'image_rotate_error', $e->getMessage() );
   554 		}
   558 		}
   555 		return true;
   559 		return true;
   556 	}
   560 	}
   557 
   561 
   564 	 * @param bool $vert Flip along Vertical Axis
   568 	 * @param bool $vert Flip along Vertical Axis
   565 	 * @return true|WP_Error
   569 	 * @return true|WP_Error
   566 	 */
   570 	 */
   567 	public function flip( $horz, $vert ) {
   571 	public function flip( $horz, $vert ) {
   568 		try {
   572 		try {
   569 			if ( $horz )
   573 			if ( $horz ) {
   570 				$this->image->flipImage();
   574 				$this->image->flipImage();
   571 
   575 			}
   572 			if ( $vert )
   576 
       
   577 			if ( $vert ) {
   573 				$this->image->flopImage();
   578 				$this->image->flopImage();
   574 		}
   579 			}
   575 		catch ( Exception $e ) {
   580 		} catch ( Exception $e ) {
   576 			return new WP_Error( 'image_flip_error', $e->getMessage() );
   581 			return new WP_Error( 'image_flip_error', $e->getMessage() );
   577 		}
   582 		}
   578 		return true;
   583 		return true;
   579 	}
   584 	}
   580 
   585 
   589 	 */
   594 	 */
   590 	public function save( $destfilename = null, $mime_type = null ) {
   595 	public function save( $destfilename = null, $mime_type = null ) {
   591 		$saved = $this->_save( $this->image, $destfilename, $mime_type );
   596 		$saved = $this->_save( $this->image, $destfilename, $mime_type );
   592 
   597 
   593 		if ( ! is_wp_error( $saved ) ) {
   598 		if ( ! is_wp_error( $saved ) ) {
   594 			$this->file = $saved['path'];
   599 			$this->file      = $saved['path'];
   595 			$this->mime_type = $saved['mime-type'];
   600 			$this->mime_type = $saved['mime-type'];
   596 
   601 
   597 			try {
   602 			try {
   598 				$this->image->setImageFormat( strtoupper( $this->get_extension( $this->mime_type ) ) );
   603 				$this->image->setImageFormat( strtoupper( $this->get_extension( $this->mime_type ) ) );
   599 			}
   604 			} catch ( Exception $e ) {
   600 			catch ( Exception $e ) {
       
   601 				return new WP_Error( 'image_save_error', $e->getMessage(), $this->file );
   605 				return new WP_Error( 'image_save_error', $e->getMessage(), $this->file );
   602 			}
   606 			}
   603 		}
   607 		}
   604 
   608 
   605 		return $saved;
   609 		return $saved;
   606 	}
   610 	}
   607 
   611 
   608 	/**
   612 	/**
   609 	 *
       
   610 	 * @param Imagick $image
   613 	 * @param Imagick $image
   611 	 * @param string $filename
   614 	 * @param string $filename
   612 	 * @param string $mime_type
   615 	 * @param string $mime_type
   613 	 * @return array|WP_Error
   616 	 * @return array|WP_Error
   614 	 */
   617 	 */
   615 	protected function _save( $image, $filename = null, $mime_type = null ) {
   618 	protected function _save( $image, $filename = null, $mime_type = null ) {
   616 		list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
   619 		list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
   617 
   620 
   618 		if ( ! $filename )
   621 		if ( ! $filename ) {
   619 			$filename = $this->generate_filename( null, null, $extension );
   622 			$filename = $this->generate_filename( null, null, $extension );
       
   623 		}
   620 
   624 
   621 		try {
   625 		try {
   622 			// Store initial Format
   626 			// Store initial Format
   623 			$orig_format = $this->image->getImageFormat();
   627 			$orig_format = $this->image->getImageFormat();
   624 
   628 
   625 			$this->image->setImageFormat( strtoupper( $this->get_extension( $mime_type ) ) );
   629 			$this->image->setImageFormat( strtoupper( $this->get_extension( $mime_type ) ) );
   626 			$this->make_image( $filename, array( $image, 'writeImage' ), array( $filename ) );
   630 			$this->make_image( $filename, array( $image, 'writeImage' ), array( $filename ) );
   627 
   631 
   628 			// Reset original Format
   632 			// Reset original Format
   629 			$this->image->setImageFormat( $orig_format );
   633 			$this->image->setImageFormat( $orig_format );
   630 		}
   634 		} catch ( Exception $e ) {
   631 		catch ( Exception $e ) {
       
   632 			return new WP_Error( 'image_save_error', $e->getMessage(), $filename );
   635 			return new WP_Error( 'image_save_error', $e->getMessage(), $filename );
   633 		}
   636 		}
   634 
   637 
   635 		// Set correct file permissions
   638 		// Set correct file permissions
   636 		$stat = stat( dirname( $filename ) );
   639 		$stat  = stat( dirname( $filename ) );
   637 		$perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits
   640 		$perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits
   638 		@ chmod( $filename, $perms );
   641 		@ chmod( $filename, $perms );
   639 
   642 
   640 		/** This filter is documented in wp-includes/class-wp-image-editor-gd.php */
   643 		/** This filter is documented in wp-includes/class-wp-image-editor-gd.php */
   641 		return array(
   644 		return array(
   666 			header( "Content-Type: $mime_type" );
   669 			header( "Content-Type: $mime_type" );
   667 			print $this->image->getImageBlob();
   670 			print $this->image->getImageBlob();
   668 
   671 
   669 			// Reset Image to original Format
   672 			// Reset Image to original Format
   670 			$this->image->setImageFormat( $this->get_extension( $this->mime_type ) );
   673 			$this->image->setImageFormat( $this->get_extension( $this->mime_type ) );
   671 		}
   674 		} catch ( Exception $e ) {
   672 		catch ( Exception $e ) {
       
   673 			return new WP_Error( 'image_stream_error', $e->getMessage() );
   675 			return new WP_Error( 'image_stream_error', $e->getMessage() );
   674 		}
   676 		}
   675 
   677 
   676 		return true;
   678 		return true;
   677 	}
   679 	}
   717 			foreach ( $this->image->getImageProfiles( '*', true ) as $key => $value ) {
   719 			foreach ( $this->image->getImageProfiles( '*', true ) as $key => $value ) {
   718 				if ( ! in_array( $key, $protected_profiles ) ) {
   720 				if ( ! in_array( $key, $protected_profiles ) ) {
   719 					$this->image->removeImageProfile( $key );
   721 					$this->image->removeImageProfile( $key );
   720 				}
   722 				}
   721 			}
   723 			}
   722 
       
   723 		} catch ( Exception $e ) {
   724 		} catch ( Exception $e ) {
   724 			return new WP_Error( 'image_strip_meta_error', $e->getMessage() );
   725 			return new WP_Error( 'image_strip_meta_error', $e->getMessage() );
   725 		}
   726 		}
   726 
   727 
   727 		return true;
   728 		return true;
   741 			// We want the thumbnail to be readable, so increase the rendering DPI.
   742 			// We want the thumbnail to be readable, so increase the rendering DPI.
   742 			$this->image->setResolution( 128, 128 );
   743 			$this->image->setResolution( 128, 128 );
   743 
   744 
   744 			// Only load the first page.
   745 			// Only load the first page.
   745 			return $this->file . '[0]';
   746 			return $this->file . '[0]';
   746 		}
   747 		} catch ( Exception $e ) {
   747 		catch ( Exception $e ) {
       
   748 			return new WP_Error( 'pdf_setup_failed', $e->getMessage(), $this->file );
   748 			return new WP_Error( 'pdf_setup_failed', $e->getMessage(), $this->file );
   749 		}
   749 		}
   750 	}
   750 	}
   751 
   751 
   752 }
   752 }