Introduce WP_Image_Editor, WP_Image_Editor_Imagick, and WP_Image_Editor_GD. Abstracts image editing API and adds support for ImageMagick.
Props DH-Shredder, kurtpayne, markoheijnen see #6821 git-svn-id: https://develop.svn.wordpress.org/trunk@22094 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
7a10f83cdd
commit
7790af3154
@ -197,39 +197,82 @@ function wp_image_editor($post_id, $msg = false) {
|
||||
<?php
|
||||
}
|
||||
|
||||
function wp_stream_image($image, $mime_type, $post_id) {
|
||||
$image = apply_filters('image_save_pre', $image, $post_id);
|
||||
/**
|
||||
* Streams image in WP_Image_Editor to browser.
|
||||
* Provided for backcompat reasons
|
||||
*
|
||||
* @param WP_Image_Editor $image
|
||||
* @param string $mime_type
|
||||
* @param int $post_id
|
||||
* @return boolean
|
||||
*/
|
||||
function wp_stream_image( $image, $mime_type, $post_id ) {
|
||||
if ( $image instanceof WP_Image_Editor ) {
|
||||
$image = apply_filters('image_editor_save_pre', $image, $post_id);
|
||||
|
||||
switch ( $mime_type ) {
|
||||
case 'image/jpeg':
|
||||
header('Content-Type: image/jpeg');
|
||||
return imagejpeg($image, null, 90);
|
||||
case 'image/png':
|
||||
header('Content-Type: image/png');
|
||||
return imagepng($image);
|
||||
case 'image/gif':
|
||||
header('Content-Type: image/gif');
|
||||
return imagegif($image);
|
||||
default:
|
||||
if ( is_wp_error( $image->stream( $mime_type ) ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
} else {
|
||||
_deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) );
|
||||
|
||||
$image = apply_filters('image_save_pre', $image, $post_id);
|
||||
|
||||
switch ( $mime_type ) {
|
||||
case 'image/jpeg':
|
||||
header( 'Content-Type: image/jpeg' );
|
||||
return imagejpeg( $image, null, 90 );
|
||||
case 'image/png':
|
||||
header( 'Content-Type: image/png' );
|
||||
return imagepng( $image );
|
||||
case 'image/gif':
|
||||
header( 'Content-Type: image/gif' );
|
||||
return imagegif( $image );
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function wp_save_image_file($filename, $image, $mime_type, $post_id) {
|
||||
$image = apply_filters('image_save_pre', $image, $post_id);
|
||||
$saved = apply_filters('wp_save_image_file', null, $filename, $image, $mime_type, $post_id);
|
||||
if ( null !== $saved )
|
||||
return $saved;
|
||||
/**
|
||||
* Saves Image to File
|
||||
* @TODO: Add mime_type support to WP_Image_Editor
|
||||
*
|
||||
* @param string $filename
|
||||
* @param WP_Image_Editor $image
|
||||
* @param string $mime_type
|
||||
* @param int $post_id
|
||||
* @return boolean
|
||||
*/
|
||||
function wp_save_image_file( $filename, $image, $mime_type, $post_id ) {
|
||||
if ( $image instanceof WP_Image_Editor ) {
|
||||
$image = apply_filters('image_editor_save_pre', $image, $post_id);
|
||||
$saved = apply_filters('wp_save_image_editor_file', null, $filename, $image, $mime_type, $post_id);
|
||||
|
||||
switch ( $mime_type ) {
|
||||
case 'image/jpeg':
|
||||
return imagejpeg( $image, $filename, apply_filters( 'jpeg_quality', 90, 'edit_image' ) );
|
||||
case 'image/png':
|
||||
return imagepng($image, $filename);
|
||||
case 'image/gif':
|
||||
return imagegif($image, $filename);
|
||||
default:
|
||||
return false;
|
||||
if ( null !== $saved )
|
||||
return $saved;
|
||||
|
||||
return $image->save( $filename, $mime_type );
|
||||
} else {
|
||||
_deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) );
|
||||
|
||||
$image = apply_filters('image_save_pre', $image, $post_id);
|
||||
$saved = apply_filters('wp_save_image_file', null, $filename, $image, $mime_type, $post_id);
|
||||
|
||||
if ( null !== $saved )
|
||||
return $saved;
|
||||
|
||||
switch ( $mime_type ) {
|
||||
case 'image/jpeg':
|
||||
return imagejpeg( $image, $filename, apply_filters( 'jpeg_quality', 90, 'edit_image' ) );
|
||||
case 'image/png':
|
||||
return imagepng( $image, $filename );
|
||||
case 'image/gif':
|
||||
return imagegif( $image, $filename );
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -238,7 +281,9 @@ function _image_get_preview_ratio($w, $h) {
|
||||
return $max > 400 ? (400 / $max) : 1;
|
||||
}
|
||||
|
||||
// @TODO: Returns GD resource, but is NOT public
|
||||
function _rotate_image_resource($img, $angle) {
|
||||
_deprecated_function( __FUNCTION__, '3.5', __( 'Use WP_Image_Editor::rotate' ) );
|
||||
if ( function_exists('imagerotate') ) {
|
||||
$rotated = imagerotate($img, $angle, 0);
|
||||
if ( is_resource($rotated) ) {
|
||||
@ -249,7 +294,18 @@ function _rotate_image_resource($img, $angle) {
|
||||
return $img;
|
||||
}
|
||||
|
||||
/**
|
||||
* @TODO: Only used within image_edit_apply_changes
|
||||
* and receives/returns GD Resource.
|
||||
* Consider removal.
|
||||
*
|
||||
* @param GD_Resource $img
|
||||
* @param boolean $horz
|
||||
* @param boolean $vert
|
||||
* @return GD_Resource
|
||||
*/
|
||||
function _flip_image_resource($img, $horz, $vert) {
|
||||
_deprecated_function( __FUNCTION__, '3.5', __( 'Use WP_Image_Editor::flip' ) );
|
||||
$w = imagesx($img);
|
||||
$h = imagesy($img);
|
||||
$dst = wp_imagecreatetruecolor($w, $h);
|
||||
@ -267,6 +323,18 @@ function _flip_image_resource($img, $horz, $vert) {
|
||||
return $img;
|
||||
}
|
||||
|
||||
/**
|
||||
* @TODO: Only used within image_edit_apply_changes
|
||||
* and receives/returns GD Resource.
|
||||
* Consider removal.
|
||||
*
|
||||
* @param GD_Resource $img
|
||||
* @param float $x
|
||||
* @param float $y
|
||||
* @param float $w
|
||||
* @param float $h
|
||||
* @return GD_Resource
|
||||
*/
|
||||
function _crop_image_resource($img, $x, $y, $w, $h) {
|
||||
$dst = wp_imagecreatetruecolor($w, $h);
|
||||
if ( is_resource($dst) ) {
|
||||
@ -278,10 +346,19 @@ function _crop_image_resource($img, $x, $y, $w, $h) {
|
||||
return $img;
|
||||
}
|
||||
|
||||
function image_edit_apply_changes($img, $changes) {
|
||||
/**
|
||||
* Performs group of changes on Editor specified.
|
||||
*
|
||||
* @param WP_Image_Editor $image
|
||||
* @param type $changes
|
||||
* @return WP_Image_Editor
|
||||
*/
|
||||
function image_edit_apply_changes( $image, $changes ) {
|
||||
if ( is_resource( $image ) )
|
||||
_deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) );
|
||||
|
||||
if ( !is_array($changes) )
|
||||
return $img;
|
||||
return $image;
|
||||
|
||||
// expand change operations
|
||||
foreach ( $changes as $key => $obj ) {
|
||||
@ -326,55 +403,83 @@ function image_edit_apply_changes($img, $changes) {
|
||||
}
|
||||
|
||||
// image resource before applying the changes
|
||||
$img = apply_filters('image_edit_before_change', $img, $changes);
|
||||
if ( $image instanceof WP_Image_Editor )
|
||||
$image = apply_filters('wp_image_editor_before_change', $image, $changes);
|
||||
elseif ( is_resource( $image ) )
|
||||
$image = apply_filters('image_edit_before_change', $image, $changes);
|
||||
|
||||
foreach ( $changes as $operation ) {
|
||||
switch ( $operation->type ) {
|
||||
case 'rotate':
|
||||
if ( $operation->angle != 0 )
|
||||
$img = _rotate_image_resource($img, $operation->angle);
|
||||
if ( $operation->angle != 0 ) {
|
||||
if ( $image instanceof WP_Image_Editor )
|
||||
$image->rotate( $operation->angle );
|
||||
else
|
||||
$image = _rotate_image_resource( $image, $operation->angle );
|
||||
}
|
||||
break;
|
||||
case 'flip':
|
||||
if ( $operation->axis != 0 )
|
||||
$img = _flip_image_resource($img, ($operation->axis & 1) != 0, ($operation->axis & 2) != 0);
|
||||
if ( $image instanceof WP_Image_Editor )
|
||||
$image->flip( ($operation->axis & 1) != 0, ($operation->axis & 2) != 0 );
|
||||
else
|
||||
$image = _flip_image_resource( $image, ( $operation->axis & 1 ) != 0, ( $operation->axis & 2 ) != 0 );
|
||||
break;
|
||||
case 'crop':
|
||||
$sel = $operation->sel;
|
||||
$scale = 1 / _image_get_preview_ratio( imagesx($img), imagesy($img) ); // discard preview scaling
|
||||
$img = _crop_image_resource($img, $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale);
|
||||
|
||||
if ( $image instanceof WP_Image_Editor ) {
|
||||
$size = $image->get_size();
|
||||
$w = $size['width'];
|
||||
$h = $size['height'];
|
||||
|
||||
$scale = 1 / _image_get_preview_ratio( $w, $h ); // discard preview scaling
|
||||
$image->crop( $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale );
|
||||
} else {
|
||||
$scale = 1 / _image_get_preview_ratio( imagesx( $image ), imagesy( $image ) ); // discard preview scaling
|
||||
$image = _crop_image_resource( $image, $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $img;
|
||||
return $image;
|
||||
}
|
||||
|
||||
function stream_preview_image($post_id) {
|
||||
$post = get_post($post_id);
|
||||
@ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) );
|
||||
$img = load_image_to_edit( $post_id, $post->post_mime_type, array(400, 400) );
|
||||
|
||||
if ( !is_resource($img) )
|
||||
return false;
|
||||
/**
|
||||
* Streams image in post to browser, along with enqueued changes
|
||||
* in $_REQUEST['history']
|
||||
*
|
||||
* @param int $post_id
|
||||
* @return boolean
|
||||
*/
|
||||
function stream_preview_image( $post_id ) {
|
||||
$post = get_post( $post_id );
|
||||
@ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) );
|
||||
|
||||
$img = WP_Image_Editor::get_instance( _load_image_to_edit_path( $post_id ) );
|
||||
|
||||
if ( is_wp_error( $img ) )
|
||||
return false;
|
||||
|
||||
$changes = !empty($_REQUEST['history']) ? json_decode( stripslashes($_REQUEST['history']) ) : null;
|
||||
if ( $changes )
|
||||
$img = image_edit_apply_changes($img, $changes);
|
||||
$img = image_edit_apply_changes( $img, $changes );
|
||||
|
||||
// scale the image
|
||||
$w = imagesx($img);
|
||||
$h = imagesy($img);
|
||||
$ratio = _image_get_preview_ratio($w, $h);
|
||||
$size = $img->get_size();
|
||||
$w = $size['width'];
|
||||
$h = $size['height'];
|
||||
|
||||
$ratio = _image_get_preview_ratio( $w, $h );
|
||||
$w2 = $w * $ratio;
|
||||
$h2 = $h * $ratio;
|
||||
|
||||
$preview = wp_imagecreatetruecolor($w2, $h2);
|
||||
imagecopyresampled( $preview, $img, 0, 0, 0, 0, $w2, $h2, $w, $h );
|
||||
wp_stream_image($preview, $post->post_mime_type, $post_id);
|
||||
if ( is_wp_error( $img->resize( $w2, $h2 ) ) )
|
||||
return false;
|
||||
|
||||
imagedestroy($preview);
|
||||
imagedestroy($img);
|
||||
return true;
|
||||
return wp_stream_image( $img, $post->post_mime_type, $post_id );
|
||||
}
|
||||
|
||||
function wp_restore_image($post_id) {
|
||||
@ -450,14 +555,20 @@ function wp_restore_image($post_id) {
|
||||
return $msg;
|
||||
}
|
||||
|
||||
function wp_save_image($post_id) {
|
||||
/**
|
||||
* Saves image to post along with enqueued changes
|
||||
* in $_REQUEST['history']
|
||||
*
|
||||
* @param int $post_id
|
||||
* @return \stdClass
|
||||
*/
|
||||
function wp_save_image( $post_id ) {
|
||||
$return = new stdClass;
|
||||
$success = $delete = $scaled = $nocrop = false;
|
||||
$post = get_post($post_id);
|
||||
@ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) );
|
||||
$img = load_image_to_edit($post_id, $post->post_mime_type);
|
||||
$post = get_post( $post_id );
|
||||
|
||||
if ( !is_resource($img) ) {
|
||||
$img = WP_Image_Editor::get_instance( _load_image_to_edit_path( $post_id, 'full' ) );
|
||||
if ( !$img ) {
|
||||
$return->error = esc_js( __('Unable to create new image.') );
|
||||
return $return;
|
||||
}
|
||||
@ -468,19 +579,16 @@ function wp_save_image($post_id) {
|
||||
$scale = !empty($_REQUEST['do']) && 'scale' == $_REQUEST['do'];
|
||||
|
||||
if ( $scale && $fwidth > 0 && $fheight > 0 ) {
|
||||
$sX = imagesx($img);
|
||||
$sY = imagesy($img);
|
||||
$size = $img->get_size();
|
||||
$sX = $size['width'];
|
||||
$sY = $size['height'];
|
||||
|
||||
// check if it has roughly the same w / h ratio
|
||||
$diff = round($sX / $sY, 2) - round($fwidth / $fheight, 2);
|
||||
if ( -0.1 < $diff && $diff < 0.1 ) {
|
||||
// scale the full size image
|
||||
$dst = wp_imagecreatetruecolor($fwidth, $fheight);
|
||||
if ( imagecopyresampled( $dst, $img, 0, 0, 0, 0, $fwidth, $fheight, $sX, $sY ) ) {
|
||||
imagedestroy($img);
|
||||
$img = $dst;
|
||||
if ( $img->resize( $fwidth, $fheight ) )
|
||||
$scaled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !$scaled ) {
|
||||
@ -551,11 +659,13 @@ function wp_save_image($post_id) {
|
||||
if ( $tag )
|
||||
$backup_sizes[$tag] = array('width' => $meta['width'], 'height' => $meta['height'], 'file' => $path_parts['basename']);
|
||||
|
||||
$success = update_attached_file($post_id, $new_path);
|
||||
$success = update_attached_file( $post_id, $new_path );
|
||||
|
||||
$meta['file'] = _wp_relative_upload_path($new_path);
|
||||
$meta['width'] = imagesx($img);
|
||||
$meta['height'] = imagesy($img);
|
||||
$meta['file'] = _wp_relative_upload_path( $new_path );
|
||||
|
||||
$size = $img->get_size();
|
||||
$meta['width'] = $size['width'];
|
||||
$meta['height'] = $size['height'];
|
||||
|
||||
if ( $success && ('nothumb' == $target || 'all' == $target) ) {
|
||||
$sizes = get_intermediate_image_sizes();
|
||||
@ -570,10 +680,12 @@ function wp_save_image($post_id) {
|
||||
$success = $delete = $nocrop = true;
|
||||
}
|
||||
|
||||
if ( isset($sizes) ) {
|
||||
if ( isset( $sizes ) ) {
|
||||
$_sizes = array();
|
||||
|
||||
foreach ( $sizes as $size ) {
|
||||
$tag = false;
|
||||
if ( isset($meta['sizes'][$size]) ) {
|
||||
if ( isset( $meta['sizes'][$size] ) ) {
|
||||
if ( isset($backup_sizes["$size-orig"]) ) {
|
||||
if ( ( !defined('IMAGE_EDIT_OVERWRITE') || !IMAGE_EDIT_OVERWRITE ) && $backup_sizes["$size-orig"]['file'] != $meta['sizes'][$size]['file'] )
|
||||
$tag = "$size-$suffix";
|
||||
@ -586,17 +698,16 @@ function wp_save_image($post_id) {
|
||||
}
|
||||
|
||||
$crop = $nocrop ? false : get_option("{$size}_crop");
|
||||
$resized = image_make_intermediate_size($new_path, get_option("{$size}_size_w"), get_option("{$size}_size_h"), $crop );
|
||||
|
||||
if ( $resized )
|
||||
$meta['sizes'][$size] = $resized;
|
||||
else
|
||||
unset($meta['sizes'][$size]);
|
||||
$_sizes[ $size ] = array( 'width' => get_option("{$size}_size_w"), 'height' => get_option("{$size}_size_h"), 'crop' => $crop );
|
||||
}
|
||||
|
||||
$meta['sizes'] = $img->multi_resize( $_sizes );
|
||||
}
|
||||
|
||||
unset( $img );
|
||||
|
||||
if ( $success ) {
|
||||
wp_update_attachment_metadata($post_id, $meta);
|
||||
wp_update_attachment_metadata( $post_id, $meta );
|
||||
update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes);
|
||||
|
||||
if ( $target == 'thumbnail' || $target == 'all' || $target == 'full' ) {
|
||||
@ -612,11 +723,9 @@ function wp_save_image($post_id) {
|
||||
|
||||
if ( $delete ) {
|
||||
$delpath = apply_filters('wp_delete_file', $new_path);
|
||||
@unlink($delpath);
|
||||
@unlink( $delpath );
|
||||
}
|
||||
|
||||
imagedestroy($img);
|
||||
|
||||
$return->msg = esc_js( __('Image saved') );
|
||||
return $return;
|
||||
}
|
||||
|
@ -22,61 +22,33 @@
|
||||
* @param string $dst_file Optional. The destination file to write to.
|
||||
* @return string|WP_Error|false New filepath on success, WP_Error or false on failure.
|
||||
*/
|
||||
function wp_crop_image( $src, $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $src_abs = false, $dst_file = false ) {
|
||||
if ( is_numeric( $src ) ) { // Handle int as attachment ID
|
||||
$src_file = get_attached_file( $src );
|
||||
function wp_crop_image( $src_file, $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $src_abs = false, $dst_file = false ) {
|
||||
if ( is_numeric( $src_file ) ) { // Handle int as attachment ID
|
||||
$src_file = get_attached_file( $src_file );
|
||||
if ( ! file_exists( $src_file ) ) {
|
||||
// If the file doesn't exist, attempt a url fopen on the src link.
|
||||
// This can occur with certain file replication plugins.
|
||||
$post = get_post( $src );
|
||||
$image_type = $post->post_mime_type;
|
||||
$src = load_image_to_edit( $src, $post->post_mime_type, 'full' );
|
||||
} else {
|
||||
$size = @getimagesize( $src_file );
|
||||
$image_type = ( $size ) ? $size['mime'] : '';
|
||||
$src = wp_load_image( $src_file );
|
||||
$src_file = _load_image_to_edit_path( $src_file, 'full' );
|
||||
}
|
||||
} else {
|
||||
$size = @getimagesize( $src );
|
||||
$image_type = ( $size ) ? $size['mime'] : '';
|
||||
$src = wp_load_image( $src );
|
||||
}
|
||||
|
||||
if ( ! is_resource( $src ) )
|
||||
return new WP_Error( 'error_loading_image', $src, $src_file );
|
||||
$editor = WP_Image_Editor::get_instance( $src_file );
|
||||
$src = $editor->crop( $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $src_abs );
|
||||
|
||||
$dst = wp_imagecreatetruecolor( $dst_w, $dst_h );
|
||||
|
||||
if ( $src_abs ) {
|
||||
$src_w -= $src_x;
|
||||
$src_h -= $src_y;
|
||||
}
|
||||
|
||||
if ( function_exists( 'imageantialias' ) )
|
||||
imageantialias( $dst, true );
|
||||
|
||||
imagecopyresampled( $dst, $src, 0, 0, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h );
|
||||
|
||||
imagedestroy( $src ); // Free up memory
|
||||
if ( is_wp_error( $src ) )
|
||||
return $src;
|
||||
|
||||
if ( ! $dst_file )
|
||||
$dst_file = str_replace( basename( $src_file ), 'cropped-' . basename( $src_file ), $src_file );
|
||||
|
||||
if ( 'image/png' != $image_type )
|
||||
$dst_file = preg_replace( '/\\.[^\\.]+$/', '.jpg', $dst_file );
|
||||
|
||||
// The directory containing the original file may no longer exist when
|
||||
// using a replication plugin.
|
||||
wp_mkdir_p( dirname( $dst_file ) );
|
||||
|
||||
$dst_file = dirname( $dst_file ) . '/' . wp_unique_filename( dirname( $dst_file ), basename( $dst_file ) );
|
||||
|
||||
if ( 'image/png' == $image_type && imagepng( $dst, $dst_file ) )
|
||||
return $dst_file;
|
||||
elseif ( imagejpeg( $dst, $dst_file, apply_filters( 'jpeg_quality', 90, 'wp_crop_image' ) ) )
|
||||
return $dst_file;
|
||||
else
|
||||
return false;
|
||||
$result = $editor->save( $dst_file );
|
||||
return $dst_file;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -121,11 +93,8 @@ function wp_generate_attachment_metadata( $attachment_id, $file ) {
|
||||
|
||||
$sizes = apply_filters( 'intermediate_image_sizes_advanced', $sizes );
|
||||
|
||||
foreach ($sizes as $size => $size_data ) {
|
||||
$resized = image_make_intermediate_size( $file, $size_data['width'], $size_data['height'], $size_data['crop'] );
|
||||
if ( $resized )
|
||||
$metadata['sizes'][$size] = $resized;
|
||||
}
|
||||
$editor = WP_Image_Editor::get_instance( $file );
|
||||
$metadata['sizes'] = $editor->multi_resize( $sizes );
|
||||
|
||||
// fetch additional metadata from exif/iptc
|
||||
$image_meta = wp_read_image_metadata( $file );
|
||||
|
357
wp-includes/class-wp-image-editor-gd.php
Normal file
357
wp-includes/class-wp-image-editor-gd.php
Normal file
@ -0,0 +1,357 @@
|
||||
<?php
|
||||
/**
|
||||
* WordPress GD Image Editor
|
||||
*
|
||||
* @package WordPress
|
||||
* @subpackage Image_Editor
|
||||
*/
|
||||
|
||||
/**
|
||||
* WordPress Image Editor Class for Image Manipulation through GD
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @package WordPress
|
||||
* @subpackage Image_Editor
|
||||
* @uses WP_Image_Editor Extends class
|
||||
*/
|
||||
class WP_Image_Editor_GD extends WP_Image_Editor {
|
||||
protected $image = false; // GD Resource
|
||||
|
||||
function __destruct() {
|
||||
if ( $this->image ) {
|
||||
// we don't need the original in memory anymore
|
||||
imagedestroy( $this->image );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if current environment supports GD
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @access protected
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public static function test() {
|
||||
if ( ! extension_loaded('gd') || ! function_exists('gd_info') )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads image from $this->file into new GD Resource
|
||||
*
|
||||
* @since 3.5
|
||||
* @access protected
|
||||
*
|
||||
* @return boolean|\WP_Error
|
||||
*/
|
||||
protected function load() {
|
||||
if ( $this->image )
|
||||
return true;
|
||||
|
||||
if ( ! file_exists( $this->file ) )
|
||||
return new WP_Error( 'error_loading_image', __('File doesn’t exist?'), $this->file );
|
||||
|
||||
// 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 new WP_Error( 'invalid_image', __('File 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->update_size( $size[0], $size[1] );
|
||||
$this->mime_type = $size['mime'];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets or updates current image size
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @access protected
|
||||
*
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
*/
|
||||
protected function update_size( $width = false, $height = false ) {
|
||||
if ( ! $width )
|
||||
$width = imagesx( $this->image );
|
||||
|
||||
if ( ! $height )
|
||||
$height = imagesy( $this->image );
|
||||
|
||||
return parent::update_size( $width, $height );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if editor supports mime-type specified
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @access public
|
||||
*
|
||||
* @param string $mime_type
|
||||
* @return boolean
|
||||
*/
|
||||
public static function supports_mime_type( $mime_type ) {
|
||||
$allowed_mime_types = array( 'image/gif', 'image/png', 'image/jpeg' );
|
||||
|
||||
return in_array( $mime_type, $allowed_mime_types );
|
||||
}
|
||||
|
||||
/**
|
||||
* Resizes current image.
|
||||
* Wrapper around _resize, since _resize returns a GD Resource
|
||||
*
|
||||
* @param int $max_w
|
||||
* @param int $max_h
|
||||
* @param boolean $crop
|
||||
* @return boolean|WP_Error
|
||||
*/
|
||||
public function resize( $max_w, $max_h, $crop = false ) {
|
||||
if ( ( $this->size['width'] == $max_w ) && ( $this->size['height'] == $max_h ) )
|
||||
return true;
|
||||
|
||||
$resized = $this->_resize( $max_w, $max_h, $crop );
|
||||
|
||||
if ( is_resource( $resized ) ) {
|
||||
imagedestroy( $this->image );
|
||||
$this->image = $resized;
|
||||
return true;
|
||||
|
||||
} elseif ( is_wp_error( $resized ) )
|
||||
return $resized;
|
||||
|
||||
return new WP_Error( 'image_resize_error', __('Image resize failed.'), $this->file );
|
||||
}
|
||||
|
||||
protected function _resize( $max_w, $max_h, $crop = false ) {
|
||||
$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'), $this->file );
|
||||
}
|
||||
list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dims;
|
||||
|
||||
$resized = wp_imagecreatetruecolor( $dst_w, $dst_h );
|
||||
imagecopyresampled( $resized, $this->image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h );
|
||||
|
||||
if ( is_resource( $resized ) ) {
|
||||
$this->update_size( $dst_w, $dst_h );
|
||||
return $resized;
|
||||
}
|
||||
|
||||
return WP_Error( 'image_resize_error', __('Image resize failed.'), $this->file );
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes current image and saves to disk
|
||||
* multiple sizes from single source.
|
||||
*
|
||||
* @param array $sizes { {width, height}, ... }
|
||||
* @return array
|
||||
*/
|
||||
public function multi_resize( $sizes ) {
|
||||
$metadata = array();
|
||||
$orig_size = $this->size;
|
||||
|
||||
foreach ( $sizes as $size => $size_data ) {
|
||||
$image = $this->_resize( $size_data['width'], $size_data['height'], $size_data['crop'] );
|
||||
|
||||
if( ! is_wp_error( $image ) ) {
|
||||
$resized = $this->_save( $image );
|
||||
|
||||
imagedestroy( $image );
|
||||
unset( $resized['path'] );
|
||||
|
||||
if ( ! is_wp_error( $resized ) && $resized )
|
||||
$metadata[$size] = $resized;
|
||||
}
|
||||
|
||||
$this->size = $orig_size;
|
||||
}
|
||||
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crops Image.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @access public
|
||||
*
|
||||
* @param string|int $src The source file or Attachment ID.
|
||||
* @param int $src_x The start x position to crop from.
|
||||
* @param int $src_y The start y position to crop from.
|
||||
* @param int $src_w The width to crop.
|
||||
* @param int $src_h The height to crop.
|
||||
* @param int $dst_w Optional. The destination width.
|
||||
* @param int $dst_h Optional. The destination height.
|
||||
* @param int $src_abs Optional. If the source crop points are absolute.
|
||||
* @return boolean|WP_Error
|
||||
*/
|
||||
public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ) {
|
||||
// If destination width/height isn't specified, use same as
|
||||
// width/height from source.
|
||||
if ( ! $dst_w )
|
||||
$dst_w = $src_w;
|
||||
if ( ! $dst_h )
|
||||
$dst_h = $src_h;
|
||||
|
||||
$dst = wp_imagecreatetruecolor( $dst_w, $dst_h );
|
||||
|
||||
if ( $src_abs ) {
|
||||
$src_w -= $src_x;
|
||||
$src_h -= $src_y;
|
||||
}
|
||||
|
||||
if ( function_exists( 'imageantialias' ) )
|
||||
imageantialias( $dst, true );
|
||||
|
||||
imagecopyresampled( $dst, $this->image, 0, 0, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h );
|
||||
|
||||
if ( is_resource( $dst ) ) {
|
||||
imagedestroy( $this->image );
|
||||
$this->image = $dst;
|
||||
$this->update_size( $dst_w, $dst_h );
|
||||
return true;
|
||||
}
|
||||
|
||||
return WP_Error( 'image_crop_error', __('Image crop failed.'), $this->file );
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates current image counter-clockwise by $angle.
|
||||
* Ported from image-edit.php
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @access public
|
||||
*
|
||||
* @param float $angle
|
||||
* @return boolean|WP_Error
|
||||
*/
|
||||
public function rotate( $angle ) {
|
||||
if ( function_exists('imagerotate') ) {
|
||||
$rotated = imagerotate( $this->image, $angle, 0 );
|
||||
|
||||
if ( is_resource( $rotated ) ) {
|
||||
imagedestroy( $this->image );
|
||||
$this->image = $rotated;
|
||||
$this->update_size();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return WP_Error( 'image_rotate_error', __('Image rotate failed.'), $this->file );
|
||||
}
|
||||
|
||||
/**
|
||||
* Flips current image
|
||||
*
|
||||
* @param boolean $horz Horizonal Flip
|
||||
* @param boolean $vert Vertical Flip
|
||||
* @returns boolean|WP_Error
|
||||
*/
|
||||
public function flip( $horz, $vert ) {
|
||||
$w = $this->size['width'];
|
||||
$h = $this->size['height'];
|
||||
$dst = wp_imagecreatetruecolor( $w, $h );
|
||||
|
||||
if ( is_resource( $dst ) ) {
|
||||
$sx = $vert ? ($w - 1) : 0;
|
||||
$sy = $horz ? ($h - 1) : 0;
|
||||
$sw = $vert ? -$w : $w;
|
||||
$sh = $horz ? -$h : $h;
|
||||
|
||||
if ( imagecopyresampled( $dst, $this->image, 0, 0, $sx, $sy, $w, $h, $sw, $sh ) ) {
|
||||
imagedestroy( $this->image );
|
||||
$this->image = $dst;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return WP_Error( 'image_flip_error', __('Image flip failed.'), $this->file );
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves current in-memory image to file
|
||||
*
|
||||
* @param string $destfilename
|
||||
* @param string $mime_type
|
||||
* @return array|WP_Error {'path'=>string, 'file'=>string, 'width'=>int, 'height'=>int, 'mime-type'=>string}
|
||||
*/
|
||||
public function save( $filename = null, $mime_type = null ) {
|
||||
$saved = $this->_save( $this->image, $filename, $mime_type );
|
||||
|
||||
if ( ! is_wp_error( $saved ) ) {
|
||||
$this->file = $saved['path'];
|
||||
$this->mime_type = $saved['mime-type'];
|
||||
}
|
||||
|
||||
return $saved;
|
||||
}
|
||||
|
||||
protected function _save( $image, $filename = null, $mime_type = null ) {
|
||||
list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
|
||||
|
||||
if ( ! $filename )
|
||||
$filename = $this->generate_filename( null, null, $extension );
|
||||
|
||||
if ( 'image/gif' == $mime_type ) {
|
||||
if ( ! $this->make_image( $filename, 'imagegif', array( $image, $filename ) ) )
|
||||
return new WP_Error( 'image_save_error', __('Image Editor Save Failed') );
|
||||
}
|
||||
elseif ( 'image/png' == $mime_type ) {
|
||||
// convert from full colors to index colors, like original PNG.
|
||||
if ( function_exists('imageistruecolor') && ! imageistruecolor( $image ) )
|
||||
imagetruecolortopalette( $image, false, imagecolorstotal( $image ) );
|
||||
|
||||
if ( ! $this->make_image( $filename, 'imagepng', array( $image, $filename ) ) )
|
||||
return new WP_Error( 'image_save_error', __('Image Editor Save Failed') );
|
||||
}
|
||||
elseif ( 'image/jpeg' == $mime_type ) {
|
||||
if ( ! $this->make_image( $filename, 'imagejpeg', array( $image, $filename, apply_filters( 'jpeg_quality', $this->quality, 'image_resize' ) ) ) )
|
||||
return new WP_Error( 'image_save_error', __('Image Editor Save Failed') );
|
||||
}
|
||||
else {
|
||||
return new WP_Error( 'image_save_error', __('Image Editor Save Failed') );
|
||||
}
|
||||
|
||||
// Set correct file permissions
|
||||
$stat = stat( dirname( $filename ) );
|
||||
$perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits
|
||||
@ chmod( $filename, $perms );
|
||||
|
||||
return array(
|
||||
'path' => $filename,
|
||||
'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
|
||||
'width' => $this->size['width'],
|
||||
'height' => $this->size['height'],
|
||||
'mime-type'=> $mime_type,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns stream of current image
|
||||
*
|
||||
* @param string $mime_type
|
||||
*/
|
||||
public function stream( $mime_type = null ) {
|
||||
list( $filename, $extension, $mime_type ) = $this->get_output_format( null, $mime_type );
|
||||
|
||||
switch ( $mime_type ) {
|
||||
case 'image/png':
|
||||
header( 'Content-Type: image/png' );
|
||||
return imagepng( $this->image );
|
||||
case 'image/gif':
|
||||
header( 'Content-Type: image/gif' );
|
||||
return imagegif( $this->image );
|
||||
default:
|
||||
header( 'Content-Type: image/jpeg' );
|
||||
return imagejpeg( $this->image, null, $this->quality );
|
||||
}
|
||||
}
|
||||
}
|
410
wp-includes/class-wp-image-editor-imagick.php
Normal file
410
wp-includes/class-wp-image-editor-imagick.php
Normal file
@ -0,0 +1,410 @@
|
||||
<?php
|
||||
/**
|
||||
* WordPress Imagick Image Editor
|
||||
*
|
||||
* @package WordPress
|
||||
* @subpackage Image_Editor
|
||||
*/
|
||||
|
||||
/**
|
||||
* WordPress Image Editor Class for Image Manipulation through Imagick PHP Module
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @package WordPress
|
||||
* @subpackage Image_Editor
|
||||
* @uses WP_Image_Editor Extends class
|
||||
*/
|
||||
class WP_Image_Editor_Imagick extends WP_Image_Editor {
|
||||
protected $image = null; // Imagick Object
|
||||
|
||||
function __destruct() {
|
||||
if ( $this->image ) {
|
||||
// we don't need the original in memory anymore
|
||||
$this->image->clear();
|
||||
$this->image->destroy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if current environment supports Imagick
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @access protected
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public static function test() {
|
||||
if ( ! extension_loaded( 'imagick' ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads image from $this->file into new Imagick Object
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @access protected
|
||||
*
|
||||
* @return boolean|WP_Error True if loaded; WP_Error on failure.
|
||||
*/
|
||||
protected function load() {
|
||||
if ( $this->image )
|
||||
return true;
|
||||
|
||||
if ( ! file_exists( $this->file ) )
|
||||
return new WP_Error( 'error_loading_image', __('File doesn’t exist?'), $this->file );
|
||||
|
||||
try {
|
||||
$this->image = new Imagick( $this->file );
|
||||
|
||||
if( ! $this->image->valid() )
|
||||
return new WP_Error( 'invalid_image', __('File is not an image.'), $this->file);
|
||||
|
||||
// Select the first frame to handle animated GIFs properly
|
||||
$this->image->setIteratorIndex(0);
|
||||
$this->mime_type = $this->get_mime_type( $this->image->getImageFormat() );
|
||||
}
|
||||
catch ( Exception $e ) {
|
||||
return new WP_Error( 'invalid_image', $e->getMessage(), $this->file );
|
||||
}
|
||||
|
||||
$updated_size = $this->update_size();
|
||||
if ( is_wp_error( $updated_size ) )
|
||||
return $updated_size;
|
||||
|
||||
return $this->set_quality();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets Image Compression quality on a 1-100% scale.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @access public
|
||||
*
|
||||
* @param int $quality Compression Quality. Range: [1,100]
|
||||
* @return boolean|WP_Error
|
||||
*/
|
||||
public function set_quality( $quality = null ) {
|
||||
if ( !$quality )
|
||||
$quality = $this->quality;
|
||||
|
||||
try {
|
||||
if( 'image/jpeg' == $this->mime_type ) {
|
||||
$this->image->setImageCompressionQuality( apply_filters( 'jpeg_quality', $quality, 'image_resize' ) );
|
||||
$this->image->setImageCompression( imagick::COMPRESSION_JPEG );
|
||||
}
|
||||
else {
|
||||
$this->image->setImageCompressionQuality( $quality );
|
||||
}
|
||||
}
|
||||
catch ( Exception $e ) {
|
||||
return new WP_Error( 'image_quality_error', $e->getMessage() );
|
||||
}
|
||||
|
||||
return parent::set_quality( $quality );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets or updates current image size
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @access protected
|
||||
*
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
*/
|
||||
protected function update_size( $width = null, $height = null ) {
|
||||
$size = null;
|
||||
if ( !$width || !$height ) {
|
||||
try {
|
||||
$size = $this->image->getImageGeometry();
|
||||
}
|
||||
catch ( Exception $e ) {
|
||||
return new WP_Error( 'invalid_image', __('Could not read image size'), $this->file );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $width )
|
||||
$width = $size['width'];
|
||||
|
||||
if ( ! $height )
|
||||
$height = $size['height'];
|
||||
|
||||
return parent::update_size( $width, $height );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if editor supports mime-type specified
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @access public
|
||||
*
|
||||
* @param string $mime_type
|
||||
* @return boolean
|
||||
*/
|
||||
public static function supports_mime_type( $mime_type = null ) {
|
||||
if ( ! $mime_type )
|
||||
return false;
|
||||
|
||||
$imagick_extension = strtoupper( self::get_extension( $mime_type ) );
|
||||
|
||||
try {
|
||||
return ( (bool) Imagick::queryFormats( $imagick_extension ) );
|
||||
}
|
||||
catch ( Exception $e ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resizes current image.
|
||||
*
|
||||
* @param int $max_w
|
||||
* @param int $max_h
|
||||
* @param boolean $crop
|
||||
* @return boolean|WP_Error
|
||||
*/
|
||||
public function resize( $max_w, $max_h, $crop = false ) {
|
||||
if ( ( $this->size['width'] == $max_w ) && ( $this->size['height'] == $max_h ) )
|
||||
return true;
|
||||
|
||||
$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 ( $crop ) {
|
||||
return $this->crop( $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h );
|
||||
}
|
||||
|
||||
try {
|
||||
/**
|
||||
* @TODO: Thumbnail is more efficient, given a newer version of Imagemagick.
|
||||
* $this->image->thumbnailImage( $dst_w, $dst_h );
|
||||
*/
|
||||
$this->image->scaleImage( $dst_w, $dst_h );
|
||||
}
|
||||
catch ( Exception $e ) {
|
||||
return new WP_Error( 'image_resize_error', $e->getMessage() );
|
||||
}
|
||||
|
||||
return $this->update_size( $dst_w, $dst_h );
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes current image and saves to disk
|
||||
* multiple sizes from single source.
|
||||
*
|
||||
* @param array $sizes
|
||||
* @return array
|
||||
*/
|
||||
public function multi_resize( $sizes ) {
|
||||
$metadata = array();
|
||||
$orig_size = $this->size;
|
||||
$orig_image = $this->image->getImage();
|
||||
|
||||
foreach ( $sizes as $size => $size_data ) {
|
||||
if ( ! $this->image )
|
||||
$this->image = $orig_image->getImage();
|
||||
|
||||
$resize_result = $this->resize( $size_data['width'], $size_data['height'], $size_data['crop'] );
|
||||
|
||||
if( ! is_wp_error( $resize_result ) ) {
|
||||
$resized = $this->_save( $this->image );
|
||||
|
||||
$this->image->clear();
|
||||
$this->image->destroy();
|
||||
$this->image = null;
|
||||
unset( $resized['path'] );
|
||||
|
||||
if ( ! is_wp_error( $resized ) && $resized )
|
||||
$metadata[$size] = $resized;
|
||||
}
|
||||
|
||||
$this->size = $orig_size;
|
||||
}
|
||||
|
||||
$this->image = $orig_image;
|
||||
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crops Image.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @access public
|
||||
*
|
||||
* @param string|int $src The source file or Attachment ID.
|
||||
* @param int $src_x The start x position to crop from.
|
||||
* @param int $src_y The start y position to crop from.
|
||||
* @param int $src_w The width to crop.
|
||||
* @param int $src_h The height to crop.
|
||||
* @param int $dst_w Optional. The destination width.
|
||||
* @param int $dst_h Optional. The destination height.
|
||||
* @param int $src_abs Optional. If the source crop points are absolute.
|
||||
* @return boolean|WP_Error
|
||||
*/
|
||||
public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ) {
|
||||
// Not sure this is compatible.
|
||||
if ( $src_abs ) {
|
||||
$src_w -= $src_x;
|
||||
$src_h -= $src_y;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->image->cropImage( $src_w, $src_h, $src_x, $src_y );
|
||||
$this->image->setImagePage( $src_w, $src_h, 0, 0);
|
||||
|
||||
if ( $dst_w || $dst_h ) {
|
||||
// If destination width/height isn't specified, use same as
|
||||
// width/height from source.
|
||||
if ( ! $dst_w )
|
||||
$dst_w = $src_w;
|
||||
if ( ! $dst_h )
|
||||
$dst_h = $src_h;
|
||||
|
||||
$this->image->scaleImage( $dst_w, $dst_h );
|
||||
return $this->update_size( $dst_w, $dst_h );
|
||||
}
|
||||
}
|
||||
catch ( Exception $e ) {
|
||||
return new WP_Error( 'image_crop_error', $e->getMessage() );
|
||||
}
|
||||
return $this->update_size( $src_w, $src_h );
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates current image counter-clockwise by $angle.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @access public
|
||||
*
|
||||
* @param float $angle
|
||||
* @return boolean|WP_Error
|
||||
*/
|
||||
public function rotate( $angle ) {
|
||||
/**
|
||||
* $angle is 360-$angle because Imagick rotates clockwise
|
||||
* (GD rotates counter-clockwise)
|
||||
*/
|
||||
try {
|
||||
$this->image->rotateImage( new ImagickPixel('none'), 360-$angle );
|
||||
}
|
||||
catch ( Exception $e ) {
|
||||
return new WP_Error( 'image_rotate_error', $e->getMessage() );
|
||||
}
|
||||
return $this->update_size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Flips current image
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @access public
|
||||
*
|
||||
* @param boolean $horz Horizontal Flip
|
||||
* @param boolean $vert Vertical Flip
|
||||
* @returns boolean
|
||||
*/
|
||||
public function flip( $horz, $vert ) {
|
||||
try {
|
||||
if ( $horz )
|
||||
$this->image->flipImage();
|
||||
|
||||
if ( $vert )
|
||||
$this->image->flopImage();
|
||||
}
|
||||
catch ( Exception $e ) {
|
||||
return new WP_Error( 'image_flip_error', $e->getMessage() );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves current image to file
|
||||
*
|
||||
* @param string $destfilename
|
||||
* @param string $mime_type
|
||||
* @return array|WP_Error {'path'=>string, 'file'=>string, 'width'=>int, 'height'=>int, 'mime-type'=>string}
|
||||
*/
|
||||
public function save( $destfilename = null, $mime_type = null ) {
|
||||
$saved = $this->_save( $this->image, $destfilename, $mime_type );
|
||||
|
||||
if ( ! is_wp_error( $saved ) ) {
|
||||
$this->file = $saved['path'];
|
||||
$this->mime_type = $saved['mime-type'];
|
||||
|
||||
try {
|
||||
$this->image->setImageFormat( strtoupper( $this->get_extension( $this->mime_type ) ) );
|
||||
}
|
||||
catch ( Exception $e ) {
|
||||
return new WP_Error( 'image_save_error', $e->getMessage(), $this->file );
|
||||
}
|
||||
}
|
||||
|
||||
return $saved;
|
||||
}
|
||||
|
||||
protected function _save( $image, $filename = null, $mime_type = null ) {
|
||||
list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
|
||||
|
||||
if ( ! $filename )
|
||||
$filename = $this->generate_filename( null, null, $extension );
|
||||
|
||||
try {
|
||||
// Store initial Format
|
||||
$orig_format = $this->image->getImageFormat();
|
||||
|
||||
$this->image->setImageFormat( strtoupper( $this->get_extension( $mime_type ) ) );
|
||||
$this->make_image( $filename, array( $image, 'writeImage' ), array( $filename ) );
|
||||
|
||||
// Reset original Format
|
||||
$this->image->setImageFormat( $orig_format );
|
||||
}
|
||||
catch ( Exception $e ) {
|
||||
return new WP_Error( 'image_save_error', $e->getMessage(), $filename );
|
||||
}
|
||||
|
||||
// Set correct file permissions
|
||||
$stat = stat( dirname( $filename ) );
|
||||
$perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits
|
||||
@ chmod( $filename, $perms );
|
||||
|
||||
return array(
|
||||
'path' => $filename,
|
||||
'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
|
||||
'width' => $this->size['width'],
|
||||
'height' => $this->size['height'],
|
||||
'mime-type' => $mime_type,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Streams current image to browser
|
||||
*
|
||||
* @param string $mime_type
|
||||
* @return boolean|WP_Error
|
||||
*/
|
||||
public function stream( $mime_type = null ) {
|
||||
list( $filename, $extension, $mime_type ) = $this->get_output_format( null, $mime_type );
|
||||
|
||||
try {
|
||||
// Temporarily change format for stream
|
||||
$this->image->setImageFormat( strtoupper( $extension ) );
|
||||
|
||||
// Output stream of image content
|
||||
header( "Content-Type: $mime_type" );
|
||||
print $this->image->getImageBlob();
|
||||
|
||||
// Reset Image to original Format
|
||||
$this->image->setImageFormat( $this->get_extension( $this->mime_type ) );
|
||||
}
|
||||
catch ( Exception $e ) {
|
||||
return new WP_Error( 'image_stream_error', $e->getMessage() );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
324
wp-includes/class-wp-image-editor.php
Normal file
324
wp-includes/class-wp-image-editor.php
Normal file
@ -0,0 +1,324 @@
|
||||
<?php
|
||||
/**
|
||||
* Base WordPress Image Editor
|
||||
*
|
||||
* @package WordPress
|
||||
* @subpackage Image_Editor
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base WordPress Image Editor class for which Editor implementations extend
|
||||
*
|
||||
* @since 3.5.0
|
||||
*/
|
||||
abstract class WP_Image_Editor {
|
||||
protected $file = null;
|
||||
protected $size = null;
|
||||
protected $mime_type = null;
|
||||
protected $default_mime_type = 'image/jpeg';
|
||||
protected $quality = 90;
|
||||
private static $implementation;
|
||||
|
||||
protected function __construct( $filename ) {
|
||||
$this->file = $filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a WP_Image_Editor instance and loads file into it.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @access public
|
||||
*
|
||||
* @param string $path Path to File to Load
|
||||
* @return WP_Image_Editor|WP_Error|boolean
|
||||
*/
|
||||
public final static function get_instance( $path = null ) {
|
||||
$implementation = apply_filters( 'image_editor_class', self::choose_implementation(), $path );
|
||||
|
||||
if ( $implementation ) {
|
||||
$editor = new $implementation( $path );
|
||||
$loaded = $editor->load();
|
||||
|
||||
if ( is_wp_error ( $loaded ) )
|
||||
return $loaded;
|
||||
|
||||
return $editor;
|
||||
}
|
||||
|
||||
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 final static function choose_implementation() {
|
||||
|
||||
if ( null === self::$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;
|
||||
|
||||
self::$implementation = $class;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return self::$implementation;
|
||||
}
|
||||
|
||||
abstract public static function test(); // returns bool
|
||||
abstract protected function load(); // returns bool|WP_Error
|
||||
abstract public static function supports_mime_type( $mime_type ); // returns bool
|
||||
abstract public function resize( $max_w, $max_h, $crop = false );
|
||||
abstract public function multi_resize( $sizes );
|
||||
abstract public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false );
|
||||
abstract public function rotate( $angle );
|
||||
abstract public function flip( $horz, $vert );
|
||||
abstract public function save( $destfilename = null, $mime_type = null );
|
||||
abstract public function stream( $mime_type = null );
|
||||
|
||||
/**
|
||||
* Gets dimensions of image
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {'width'=>int, 'height'=>int}
|
||||
*/
|
||||
public function get_size() {
|
||||
return $this->size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets current image size
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @access protected
|
||||
*
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
*/
|
||||
protected function update_size( $width = null, $height = null ) {
|
||||
$this->size = array(
|
||||
'width' => $width,
|
||||
'height' => $height
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets Image Compression quality on a 1-100% scale.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @access public
|
||||
*
|
||||
* @param int $quality Compression Quality. Range: [1,100]
|
||||
* @return boolean
|
||||
*/
|
||||
public function set_quality( $quality ) {
|
||||
$this->quality = apply_filters( 'wp_editor_set_quality', $quality );
|
||||
|
||||
return ( (bool) $this->quality );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns preferred mime-type and extension based on provided
|
||||
* file's extension and mime, or current file's extension and mime.
|
||||
*
|
||||
* Will default to $this->default_mime_type if requested is not supported.
|
||||
*
|
||||
* Provides corrected filename only if filename is provided.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @access protected
|
||||
*
|
||||
* @param string $filename
|
||||
* @param type $mime_type
|
||||
* @return array { filename|null, extension, mime-type }
|
||||
*/
|
||||
protected function get_output_format( $filename = null, $mime_type = null ) {
|
||||
$new_ext = $file_ext = null;
|
||||
$file_mime = null;
|
||||
|
||||
// By default, assume specified type takes priority
|
||||
if ( $mime_type ) {
|
||||
$new_ext = $this->get_extension( $mime_type );
|
||||
}
|
||||
|
||||
if ( $filename ) {
|
||||
$file_ext = strtolower( pathinfo( $filename, PATHINFO_EXTENSION ) );
|
||||
$file_mime = $this->get_mime_type( $file_ext );
|
||||
}
|
||||
else {
|
||||
// If no file specified, grab editor's current extension and mime-type.
|
||||
$file_ext = strtolower( pathinfo( $this->file, PATHINFO_EXTENSION ) );
|
||||
$file_mime = $this->mime_type;
|
||||
}
|
||||
|
||||
// Check to see if specified mime-type is the same as type implied by
|
||||
// file extension. If so, prefer extension from file.
|
||||
if ( ! $mime_type || ( $file_mime == $mime_type ) ) {
|
||||
$mime_type = $file_mime;
|
||||
$new_ext = $file_ext;
|
||||
}
|
||||
|
||||
// Double-check that the mime-type selected is supported by the editor.
|
||||
// If not, choose a default instead.
|
||||
if ( ! $this->supports_mime_type( $mime_type ) ) {
|
||||
$mime_type = apply_filters( 'image_editor_default_mime_type', $this->default_mime_type );
|
||||
$new_ext = $this->get_extension( $mime_type );
|
||||
}
|
||||
|
||||
if ( $filename ) {
|
||||
$ext = '';
|
||||
$info = pathinfo( $filename );
|
||||
$dir = $info['dirname'];
|
||||
|
||||
if( isset( $info['extension'] ) )
|
||||
$ext = $info['extension'];
|
||||
|
||||
$filename = trailingslashit( $dir ) . wp_basename( $filename, ".$ext" ) . ".{$new_ext}";
|
||||
}
|
||||
|
||||
return array( $filename, $new_ext, $mime_type );
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an output filename based on current file, and adding proper suffix
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @access public
|
||||
*
|
||||
* @param string $suffix
|
||||
* @param string $dest_path
|
||||
* @param string $extension
|
||||
* @return string filename
|
||||
*/
|
||||
public function generate_filename( $suffix = null, $dest_path = null, $extension = null ) {
|
||||
// $suffix will be appended to the destination filename, just before the extension
|
||||
if ( ! $suffix )
|
||||
$suffix = $this->get_suffix();
|
||||
|
||||
$info = pathinfo( $this->file );
|
||||
$dir = $info['dirname'];
|
||||
$ext = $info['extension'];
|
||||
|
||||
$name = wp_basename( $this->file, ".$ext" );
|
||||
$new_ext = strtolower( $extension ? $extension : $ext );
|
||||
|
||||
if ( ! is_null( $dest_path ) && $_dest_path = realpath( $dest_path ) )
|
||||
$dir = $_dest_path;
|
||||
|
||||
return trailingslashit( $dir ) . "{$name}-{$suffix}.{$new_ext}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and returns proper suffix for file based on height and width.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @access public
|
||||
*
|
||||
* @return string suffix
|
||||
*/
|
||||
public function get_suffix() {
|
||||
if ( ! $this->get_size() )
|
||||
return false;
|
||||
|
||||
return "{$this->size['width']}x{$this->size['height']}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Either calls editor's save function or handles file as a stream.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @access protected
|
||||
*
|
||||
* @param string|stream $filename
|
||||
* @param callable $function
|
||||
* @param array $arguments
|
||||
* @return boolean
|
||||
*/
|
||||
protected function make_image( $filename, $function, $arguments ) {
|
||||
$dst_file = $filename;
|
||||
|
||||
if ( $stream = wp_is_stream( $filename ) ) {
|
||||
$filename = null;
|
||||
ob_start();
|
||||
}
|
||||
|
||||
$result = call_user_func_array( $function, $arguments );
|
||||
|
||||
if( $result && $stream ) {
|
||||
$contents = ob_get_contents();
|
||||
|
||||
$fp = fopen( $dst_file, 'w' );
|
||||
|
||||
if( ! $fp )
|
||||
return false;
|
||||
|
||||
fwrite( $fp, $contents );
|
||||
fclose( $fp );
|
||||
}
|
||||
|
||||
if( $stream ) {
|
||||
ob_end_clean();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns first matched mime-type from extension,
|
||||
* as mapped from wp_get_mime_types()
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @access protected
|
||||
*
|
||||
* @param string $extension
|
||||
* @return string|boolean
|
||||
*/
|
||||
protected static function get_mime_type( $extension = null ) {
|
||||
if ( ! $extension )
|
||||
return false;
|
||||
|
||||
$mime_types = wp_get_mime_types();
|
||||
$extensions = array_keys( $mime_types );
|
||||
|
||||
foreach( $extensions as $_extension ) {
|
||||
if( preg_match("/{$extension}/i", $_extension ) ) {
|
||||
return $mime_types[ $_extension ];
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns first matched extension from Mime-type,
|
||||
* as mapped from wp_get_mime_types()
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @access protected
|
||||
*
|
||||
* @param string $mime_type
|
||||
* @return string|boolean
|
||||
*/
|
||||
protected static function get_extension( $mime_type = null ) {
|
||||
$extensions = explode( '|', array_search( $mime_type, wp_get_mime_types() ) );
|
||||
|
||||
if ( empty( $extensions[0] ) )
|
||||
return false;
|
||||
|
||||
return $extensions[0];
|
||||
}
|
||||
}
|
@ -3205,6 +3205,83 @@ function _get_post_ancestors( &$post ) {
|
||||
_deprecated_function( __FUNCTION__, '3.5' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Load an image from a string, if PHP supports it.
|
||||
*
|
||||
* @since 2.1.0
|
||||
* @deprecated 3.5.0
|
||||
* @see WP_Image_Editor
|
||||
*
|
||||
* @param string $file Filename of the image to load.
|
||||
* @return resource The resulting image resource on success, Error string on failure.
|
||||
*/
|
||||
function wp_load_image( $file ) {
|
||||
_deprecated_function( __FUNCTION__, '3.5', 'WP_Image_Editor' );
|
||||
|
||||
if ( is_numeric( $file ) )
|
||||
$file = get_attached_file( $file );
|
||||
|
||||
if ( ! file_exists( $file ) )
|
||||
return sprintf(__('File “%s” doesn’t exist?'), $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 ) );
|
||||
$image = imagecreatefromstring( file_get_contents( $file ) );
|
||||
|
||||
if ( !is_resource( $image ) )
|
||||
return sprintf(__('File “%s” is not an image.'), $file);
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale down an image to fit a particular size and save a new copy of the image.
|
||||
*
|
||||
* The PNG transparency will be preserved using the function, as well as the
|
||||
* image type. If the file going in is PNG, then the resized image is going to
|
||||
* be PNG. The only supported image types are PNG, GIF, and JPEG.
|
||||
*
|
||||
* Some functionality requires API to exist, so some PHP version may lose out
|
||||
* support. This is not the fault of WordPress (where functionality is
|
||||
* downgraded, not actual defects), but of your PHP version.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @deprecated 3.5.0
|
||||
* @see WP_Image_Editor
|
||||
*
|
||||
* @param string $file Image file path.
|
||||
* @param int $max_w Maximum width to resize to.
|
||||
* @param int $max_h Maximum height to resize to.
|
||||
* @param bool $crop Optional. Whether to crop image or resize.
|
||||
* @param string $suffix Optional. File suffix.
|
||||
* @param string $dest_path Optional. New image file path.
|
||||
* @param int $jpeg_quality Optional, default is 90. Image quality percentage.
|
||||
* @return mixed WP_Error on failure. String with new destination path.
|
||||
*/
|
||||
function image_resize( $file, $max_w, $max_h, $crop = false, $suffix = null, $dest_path = null, $jpeg_quality = 90 ) {
|
||||
_deprecated_function( __FUNCTION__, '3.5', 'WP_Image_Editor' );
|
||||
|
||||
$editor = WP_Image_Editor::get_instance( $file );
|
||||
if ( is_wp_error( $editor ) )
|
||||
return $editor;
|
||||
$editor->set_quality( $jpeg_quality );
|
||||
|
||||
$resized = $editor->resize( $max_w, $max_h, $crop );
|
||||
if ( is_wp_error( $resized ) )
|
||||
return $resized;
|
||||
|
||||
$dest_file = $editor->generate_filename( $suffix, $dest_path );
|
||||
$saved = $editor->save( $dest_file );
|
||||
|
||||
if ( is_wp_error( $saved ) )
|
||||
return $saved;
|
||||
|
||||
return $dest_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a single post, based on post ID.
|
||||
*
|
||||
|
@ -1295,9 +1295,21 @@ function wp_get_original_referer() {
|
||||
* @return bool Whether the path was created. True if path already exists.
|
||||
*/
|
||||
function wp_mkdir_p( $target ) {
|
||||
$wrapper = null;
|
||||
|
||||
// strip the protocol
|
||||
if( wp_is_stream( $target ) ) {
|
||||
list( $wrapper, $target ) = explode( '://', $target, 2 );
|
||||
}
|
||||
|
||||
// from php.net/mkdir user contributed notes
|
||||
$target = str_replace( '//', '/', $target );
|
||||
|
||||
// put the wrapper back on the target
|
||||
if( $wrapper !== null ) {
|
||||
$target = $wrapper . '://' . $target;
|
||||
}
|
||||
|
||||
// safe mode fails with a trailing slash under certain PHP versions.
|
||||
$target = rtrim($target, '/'); // Use rtrim() instead of untrailingslashit to avoid formatting.php dependency.
|
||||
if ( empty($target) )
|
||||
@ -3749,6 +3761,19 @@ function _device_can_upload() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a given path is a stream URL
|
||||
*
|
||||
* @param string $path The resource path or URL
|
||||
* @return bool True if the path is a stream URL
|
||||
*/
|
||||
function wp_is_stream( $path ) {
|
||||
$wrappers = stream_get_wrappers();
|
||||
$wrappers_re = '(' . join('|', $wrappers) . ')';
|
||||
|
||||
return preg_match( "!^$wrappers_re://!", $path ) === 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the supplied date is valid for the Gregorian calendar
|
||||
*
|
||||
|
@ -235,34 +235,6 @@ function get_image_tag($id, $alt, $title, $align, $size='medium') {
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load an image from a string, if PHP supports it.
|
||||
*
|
||||
* @since 2.1.0
|
||||
*
|
||||
* @param string $file Filename of the image to load.
|
||||
* @return resource The resulting image resource on success, Error string on failure.
|
||||
*/
|
||||
function wp_load_image( $file ) {
|
||||
if ( is_numeric( $file ) )
|
||||
$file = get_attached_file( $file );
|
||||
|
||||
if ( ! file_exists( $file ) )
|
||||
return sprintf(__('File “%s” doesn’t exist?'), $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 ) );
|
||||
$image = imagecreatefromstring( file_get_contents( $file ) );
|
||||
|
||||
if ( !is_resource( $image ) )
|
||||
return sprintf(__('File “%s” is not an image.'), $file);
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the new dimensions for a downsampled image.
|
||||
*
|
||||
@ -392,92 +364,6 @@ function image_resize_dimensions($orig_w, $orig_h, $dest_w, $dest_h, $crop = fal
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale down an image to fit a particular size and save a new copy of the image.
|
||||
*
|
||||
* The PNG transparency will be preserved using the function, as well as the
|
||||
* image type. If the file going in is PNG, then the resized image is going to
|
||||
* be PNG. The only supported image types are PNG, GIF, and JPEG.
|
||||
*
|
||||
* Some functionality requires API to exist, so some PHP version may lose out
|
||||
* support. This is not the fault of WordPress (where functionality is
|
||||
* downgraded, not actual defects), but of your PHP version.
|
||||
*
|
||||
* @since 2.5.0
|
||||
*
|
||||
* @param string $file Image file path.
|
||||
* @param int $max_w Maximum width to resize to.
|
||||
* @param int $max_h Maximum height to resize to.
|
||||
* @param bool $crop Optional. Whether to crop image or resize.
|
||||
* @param string $suffix Optional. File suffix.
|
||||
* @param string $dest_path Optional. New image file path.
|
||||
* @param int $jpeg_quality Optional, default is 90. Image quality percentage.
|
||||
* @return mixed WP_Error on failure. String with new destination path.
|
||||
*/
|
||||
function image_resize( $file, $max_w, $max_h, $crop = false, $suffix = null, $dest_path = null, $jpeg_quality = 90 ) {
|
||||
|
||||
$image = wp_load_image( $file );
|
||||
if ( !is_resource( $image ) )
|
||||
return new WP_Error( 'error_loading_image', $image, $file );
|
||||
|
||||
$size = @getimagesize( $file );
|
||||
if ( !$size )
|
||||
return new WP_Error('invalid_image', __('Could not read image size'), $file);
|
||||
list($orig_w, $orig_h, $orig_type) = $size;
|
||||
|
||||
$dims = image_resize_dimensions($orig_w, $orig_h, $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, $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 == $orig_type && function_exists('imageistruecolor') && !imageistruecolor( $image ) )
|
||||
imagetruecolortopalette( $newimage, false, imagecolorstotal( $image ) );
|
||||
|
||||
// we don't need the original in memory anymore
|
||||
imagedestroy( $image );
|
||||
|
||||
// $suffix will be appended to the destination filename, just before the extension
|
||||
if ( !$suffix )
|
||||
$suffix = "{$dst_w}x{$dst_h}";
|
||||
|
||||
$info = pathinfo($file);
|
||||
$dir = $info['dirname'];
|
||||
$ext = $info['extension'];
|
||||
$name = wp_basename($file, ".$ext");
|
||||
|
||||
if ( !is_null($dest_path) and $_dest_path = realpath($dest_path) )
|
||||
$dir = $_dest_path;
|
||||
$destfilename = "{$dir}/{$name}-{$suffix}.{$ext}";
|
||||
|
||||
if ( IMAGETYPE_GIF == $orig_type ) {
|
||||
if ( !imagegif( $newimage, $destfilename ) )
|
||||
return new WP_Error('resize_path_invalid', __( 'Resize path invalid' ));
|
||||
} elseif ( IMAGETYPE_PNG == $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 $destfilename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize an image to make a thumbnail or intermediate size.
|
||||
*
|
||||
@ -493,16 +379,18 @@ function image_resize( $file, $max_w, $max_h, $crop = false, $suffix = null, $de
|
||||
* @param bool $crop Optional, default is false. Whether to crop image to specified height and width or resize.
|
||||
* @return bool|array False, if no image was created. Metadata array on success.
|
||||
*/
|
||||
function image_make_intermediate_size($file, $width, $height, $crop=false) {
|
||||
function image_make_intermediate_size( $file, $width, $height, $crop = false ) {
|
||||
if ( $width || $height ) {
|
||||
$resized_file = image_resize($file, $width, $height, $crop);
|
||||
if ( !is_wp_error($resized_file) && $resized_file && $info = getimagesize($resized_file) ) {
|
||||
$resized_file = apply_filters('image_make_intermediate_size', $resized_file);
|
||||
return array(
|
||||
'file' => wp_basename( $resized_file ),
|
||||
'width' => $info[0],
|
||||
'height' => $info[1],
|
||||
);
|
||||
$editor = WP_Image_Editor::get_instance( $file );
|
||||
|
||||
if ( is_wp_error( $editor->resize( $width, $height, $crop ) ) );
|
||||
return false;
|
||||
|
||||
$resized_file = $editor->save();
|
||||
|
||||
if ( ! is_wp_error( $resized_file ) && $resized_file ) {
|
||||
unset( $resized_file['path'] );
|
||||
return $resized_file;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -1047,6 +935,7 @@ function gd_edit_image_support($mime_type) {
|
||||
|
||||
/**
|
||||
* Create new GD image resource with transparency support
|
||||
* @TODO: Deprecate if possible.
|
||||
*
|
||||
* @since 2.9.0
|
||||
*
|
||||
|
@ -143,6 +143,10 @@ require( ABSPATH . WPINC . '/nav-menu.php' );
|
||||
require( ABSPATH . WPINC . '/nav-menu-template.php' );
|
||||
require( ABSPATH . WPINC . '/admin-bar.php' );
|
||||
|
||||
require( ABSPATH . WPINC . '/class-wp-image-editor.php' );
|
||||
require( ABSPATH . WPINC . '/class-wp-image-editor-gd.php' );
|
||||
require( ABSPATH . WPINC . '/class-wp-image-editor-imagick.php' );
|
||||
|
||||
// Load multisite-specific files.
|
||||
if ( is_multisite() ) {
|
||||
require( ABSPATH . WPINC . '/ms-functions.php' );
|
||||
|
Loading…
Reference in New Issue
Block a user