forked from WordPress/WordPress
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
First version of the WP_Image_Editor
- Loading branch information
1 parent
d7f7240
commit f96f9db
Showing
8 changed files
with
330 additions
and
125 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
<?php | ||
|
||
class WP_Image_Editor { | ||
|
||
final public static function get_instance( $path ) { | ||
$implementation = apply_filters( 'image_editor_class', self::choose_implementation(), $path ); | ||
|
||
if ( $implementation ) | ||
return new $implementation( $path ); | ||
|
||
return false; | ||
} | ||
|
||
/** | ||
* Tests which editors are capable of supporting the request. | ||
* | ||
* @since 3.5.0 | ||
* @access private | ||
* | ||
* @return string|bool Class name for the first editor that claims to support the request. False if no editor claims to support the request. | ||
*/ | ||
private static function choose_implementation() { | ||
static $implementation; | ||
|
||
if ( null === $implementation ) { | ||
$request_order = apply_filters( 'wp_editors', array( 'imagick', 'gd' ) ); | ||
|
||
// Loop over each editor on each request looking for one which will serve this request's needs | ||
foreach ( $request_order as $editor ) { | ||
$class = 'WP_Image_Editor_' . $editor; | ||
|
||
// Check to see if this editor is a possibility, calls the editor statically | ||
if ( ! call_user_func( array( $class, 'test' ) ) ) | ||
continue; | ||
|
||
if( ! apply_filters( 'wp_editor_use_' . $editor, true ) ) | ||
continue; | ||
|
||
$implementation = $class; | ||
} | ||
} | ||
|
||
return $implementation; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?php | ||
|
||
class WP_Image_Editor_Base { | ||
protected $file = false; | ||
protected $size = false; | ||
protected $orig_type = false; | ||
|
||
function __construct( $filename ) { | ||
$this->file = $filename; | ||
} | ||
|
||
public static function test() { | ||
return false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
<?php | ||
|
||
class WP_Image_Editor_GD extends WP_Image_Editor_Base { | ||
private $image = false; | ||
|
||
function __destruct() { | ||
if ( $this->image ) { | ||
// we don't need the original in memory anymore | ||
imagedestroy( $this->image ); | ||
} | ||
} | ||
|
||
public static function test() { | ||
if ( ! extension_loaded('gd') || ! function_exists('gd_info') ) | ||
return false; | ||
|
||
return true; | ||
} | ||
|
||
private function load() { | ||
if( $this->image ) | ||
return true; | ||
|
||
if ( ! file_exists( $this->file ) ) | ||
return sprintf( __('File “%s” doesn’t exist?'), $this->file ); | ||
|
||
if ( ! function_exists('imagecreatefromstring') ) | ||
return __('The GD image library is not installed.'); | ||
|
||
// Set artificially high because GD uses uncompressed images in memory | ||
@ini_set( 'memory_limit', apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT ) ); | ||
$this->image = imagecreatefromstring( file_get_contents( $this->file ) ); | ||
|
||
if ( ! is_resource( $this->image ) ) | ||
return sprintf( __('File “%s” is not an image.'), $this->file ); | ||
|
||
$size = @getimagesize( $this->file ); | ||
if ( ! $size ) | ||
return new WP_Error( 'invalid_image', __('Could not read image size'), $this->file ); | ||
|
||
$this->size = array( 'width' => $size[0], 'height' => $size[1] ); | ||
$this->orig_type = $size[1]; | ||
|
||
return true; | ||
} | ||
|
||
public function resize( $max_w, $max_h, $crop = false, $suffix = null, $dest_path = null, $jpeg_quality = 90 ) { | ||
if ( ! $this->load() ) | ||
return; | ||
|
||
$dims = image_resize_dimensions( $this->size['width'], $this->size['height'], $max_w, $max_h, $crop ); | ||
if ( ! $dims ) | ||
return new WP_Error( 'error_getting_dimensions', __('Could not calculate resized image dimensions') ); | ||
list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dims; | ||
|
||
$newimage = wp_imagecreatetruecolor( $dst_w, $dst_h ); | ||
|
||
imagecopyresampled( $newimage, $this->image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ); | ||
|
||
// convert from full colors to index colors, like original PNG. | ||
if ( IMAGETYPE_PNG == $this->orig_type && function_exists('imageistruecolor') && !imageistruecolor( $this->image ) ) | ||
imagetruecolortopalette( $newimage, false, imagecolorstotal( $this->image ) ); | ||
|
||
// $suffix will be appended to the destination filename, just before the extension | ||
if ( ! $suffix ) | ||
$suffix = "{$dst_w}x{$dst_h}"; | ||
|
||
$info = pathinfo( $this->file ); | ||
$dir = $info['dirname']; | ||
$ext = $info['extension']; | ||
$name = wp_basename( $this->file, ".$ext" ); | ||
|
||
if ( ! is_null( $dest_path ) && $_dest_path = realpath( $dest_path ) ) | ||
$dir = $_dest_path; | ||
$destfilename = "{$dir}/{$name}-{$suffix}.{$ext}"; | ||
|
||
if ( IMAGETYPE_GIF == $this->orig_type ) { | ||
if ( ! imagegif( $newimage, $destfilename ) ) | ||
return new WP_Error( 'resize_path_invalid', __( 'Resize path invalid' ) ); | ||
} | ||
elseif ( IMAGETYPE_PNG == $this->orig_type ) { | ||
if ( !imagepng( $newimage, $destfilename ) ) | ||
return new WP_Error( 'resize_path_invalid', __( 'Resize path invalid' ) ); | ||
} | ||
else { | ||
// all other formats are converted to jpg | ||
if ( 'jpg' != $ext && 'jpeg' != $ext ) | ||
$destfilename = "{$dir}/{$name}-{$suffix}.jpg"; | ||
|
||
if ( ! imagejpeg( $newimage, $destfilename, apply_filters( 'jpeg_quality', $jpeg_quality, 'image_resize' ) ) ) | ||
return new WP_Error( 'resize_path_invalid', __( 'Resize path invalid' ) ); | ||
} | ||
|
||
imagedestroy( $newimage ); | ||
|
||
// Set correct file permissions | ||
$stat = stat( dirname( $destfilename ) ); | ||
$perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits | ||
@ chmod( $destfilename, $perms ); | ||
|
||
return array( | ||
'path' => $destfilename, | ||
'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $destfilename ) ), | ||
'width' => $dst_w, | ||
'height' => $dst_h | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
<?php | ||
|
||
class WP_Image_Editor_Imagick extends WP_Image_Editor_Base { | ||
private $image = false; | ||
|
||
public static function test() { | ||
if ( ! extension_loaded('imagick') ) | ||
return false; | ||
|
||
return true; | ||
} | ||
|
||
private function load() { | ||
if ( ! file_exists( $this->file ) ) | ||
return sprintf( __('File “%s” doesn’t exist?'), $this->file ); | ||
|
||
try { | ||
$this->image = new Imagick( $this->file ); | ||
} | ||
catch ( Exception $e ) { | ||
return sprintf(__('File “%s” is not an image.'), $this->file); | ||
} | ||
|
||
if( ! $this->image->valid() ) { | ||
return sprintf(__('File “%s” is not an image.'), $this->file); | ||
} | ||
|
||
$this->size = $this->image->getImageGeometry(); | ||
$this->orig_type = $this->image->getImageFormat(); | ||
if ( ! $this->size ) | ||
return new WP_Error( 'invalid_image', __('Could not read image size'), $this->file ); | ||
|
||
return true; | ||
} | ||
|
||
public function resize( $max_w, $max_h, $crop = false, $suffix = null, $dest_path = null, $jpeg_quality = 90 ) { | ||
// Yes, this is forcing a load every time at the moment. | ||
// However, for multi-resize to work, it needs to do so, unless it's going to resize based on a modified image. | ||
if ( ! $this->load() ) | ||
return false; | ||
|
||
if ( ! is_object( $this->image ) ) | ||
return new WP_Error( 'error_loading_image', $this->image, $this->file ); | ||
|
||
$dims = image_resize_dimensions( $this->size['width'], $this->size['height'], $max_w, $max_h, $crop ); | ||
if ( ! $dims ) | ||
return new WP_Error( 'error_getting_dimensions', __('Could not calculate resized image dimensions') ); | ||
list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dims; | ||
|
||
if( 'JPEG' == $this->orig_type ) { | ||
$this->image->setImageCompression( imagick::COMPRESSION_JPEG ); | ||
$this->image->setImageCompressionQuality( $jpeg_quality ); | ||
} | ||
|
||
if ( $crop ) { | ||
$this->image->cropImage( $src_w, $src_h, $src_x, $src_y ); | ||
} | ||
|
||
//$this->image->thumbnailImage( $dst_w, $dst_h ); | ||
$this->image->scaleImage( $dst_w, $dst_h, true ); | ||
|
||
// $suffix will be appended to the destination filename, just before the extension | ||
if ( ! $suffix ) | ||
$suffix = "{$dst_w}x{$dst_h}"; | ||
|
||
$info = pathinfo( $this->file ); | ||
$dir = $info['dirname']; | ||
$ext = $info['extension']; | ||
$name = wp_basename( $this->file, ".$ext" ); | ||
|
||
if ( ! is_null( $dest_path ) && $_dest_path = realpath( $dest_path ) ) | ||
$dir = $_dest_path; | ||
$destfilename = "{$dir}/{$name}-{$suffix}.{$ext}"; | ||
|
||
if( apply_filters( 'wp_editors_stripimage', true ) ) { | ||
$this->image->stripImage(); | ||
} | ||
|
||
$this->image->writeImage( $destfilename ); | ||
|
||
// Set correct file permissions | ||
$stat = stat( dirname( $destfilename ) ); | ||
$perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits | ||
@ chmod( $destfilename, $perms ); | ||
|
||
return array( | ||
'path' => $destfilename, | ||
'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $destfilename ) ), | ||
'width' => $dst_w, | ||
'height' => $dst_h | ||
); | ||
} | ||
} |
Oops, something went wrong.
Copy/pasta?