diff -r 000000000000 -r d970ebf37754 wp/wp-admin/includes/image-edit.php
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/wp/wp-admin/includes/image-edit.php Wed Nov 06 03:21:17 2013 +0000
@@ -0,0 +1,734 @@
+ 400 ? 400 / $big : 1;
+
+ $backup_sizes = get_post_meta( $post_id, '_wp_attachment_backup_sizes', true );
+ $can_restore = false;
+ if ( ! empty( $backup_sizes ) && isset( $backup_sizes['full-orig'], $meta['file'] ) )
+ $can_restore = $backup_sizes['full-orig']['file'] != basename( $meta['file'] );
+
+ if ( $msg ) {
+ if ( isset($msg->error) )
+ $note = "
";
+ elseif ( isset($msg->msg) )
+ $note = "";
+ }
+
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ; ?>?action=imgedit-preview&_ajax_nonce=<?php echo $nonce; ?>&postid=<?php echo $post_id; ?>&rand=<?php echo rand(1, 99999); ?>)
+
+
+
+
+ )" disabled="disabled" class="button-primary imgedit-submit-btn" value="" />
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+ , 'restore')" class="button-primary" value="" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+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;
+ }
+ }
+}
+
+/**
+ * Saves Image to File
+ *
+ * @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);
+
+ 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;
+ }
+ }
+}
+
+function _image_get_preview_ratio($w, $h) {
+ $max = max($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) ) {
+ imagedestroy($img);
+ $img = $rotated;
+ }
+ }
+ 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);
+ 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, $img, 0, 0, $sx, $sy, $w, $h, $sw, $sh) ) {
+ imagedestroy($img);
+ $img = $dst;
+ }
+ }
+ 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) ) {
+ if ( imagecopy($dst, $img, 0, 0, $x, $y, $w, $h) ) {
+ imagedestroy($img);
+ $img = $dst;
+ }
+ }
+ return $img;
+}
+
+/**
+ * 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 $image;
+
+ // expand change operations
+ foreach ( $changes as $key => $obj ) {
+ if ( isset($obj->r) ) {
+ $obj->type = 'rotate';
+ $obj->angle = $obj->r;
+ unset($obj->r);
+ } elseif ( isset($obj->f) ) {
+ $obj->type = 'flip';
+ $obj->axis = $obj->f;
+ unset($obj->f);
+ } elseif ( isset($obj->c) ) {
+ $obj->type = 'crop';
+ $obj->sel = $obj->c;
+ unset($obj->c);
+ }
+ $changes[$key] = $obj;
+ }
+
+ // combine operations
+ if ( count($changes) > 1 ) {
+ $filtered = array($changes[0]);
+ for ( $i = 0, $j = 1; $j < count($changes); $j++ ) {
+ $combined = false;
+ if ( $filtered[$i]->type == $changes[$j]->type ) {
+ switch ( $filtered[$i]->type ) {
+ case 'rotate':
+ $filtered[$i]->angle += $changes[$j]->angle;
+ $combined = true;
+ break;
+ case 'flip':
+ $filtered[$i]->axis ^= $changes[$j]->axis;
+ $combined = true;
+ break;
+ }
+ }
+ if ( !$combined )
+ $filtered[++$i] = $changes[$j];
+ }
+ $changes = $filtered;
+ unset($filtered);
+ }
+
+ // image resource before applying the 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 ) {
+ 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 )
+ 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;
+
+ 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 $image;
+}
+
+
+/**
+ * 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_get_image_editor( _load_image_to_edit_path( $post_id ) );
+
+ if ( is_wp_error( $img ) )
+ return false;
+
+ $changes = !empty($_REQUEST['history']) ? json_decode( wp_unslash($_REQUEST['history']) ) : null;
+ if ( $changes )
+ $img = image_edit_apply_changes( $img, $changes );
+
+ // scale the image
+ $size = $img->get_size();
+ $w = $size['width'];
+ $h = $size['height'];
+
+ $ratio = _image_get_preview_ratio( $w, $h );
+ $w2 = max ( 1, $w * $ratio );
+ $h2 = max ( 1, $h * $ratio );
+
+ if ( is_wp_error( $img->resize( $w2, $h2 ) ) )
+ return false;
+
+ return wp_stream_image( $img, $post->post_mime_type, $post_id );
+}
+
+function wp_restore_image($post_id) {
+ $meta = wp_get_attachment_metadata($post_id);
+ $file = get_attached_file($post_id);
+ $backup_sizes = get_post_meta( $post_id, '_wp_attachment_backup_sizes', true );
+ $restored = false;
+ $msg = new stdClass;
+
+ if ( !is_array($backup_sizes) ) {
+ $msg->error = __('Cannot load image metadata.');
+ return $msg;
+ }
+
+ $parts = pathinfo($file);
+ $suffix = time() . rand(100, 999);
+ $default_sizes = get_intermediate_image_sizes();
+
+ if ( isset($backup_sizes['full-orig']) && is_array($backup_sizes['full-orig']) ) {
+ $data = $backup_sizes['full-orig'];
+
+ if ( $parts['basename'] != $data['file'] ) {
+ if ( defined('IMAGE_EDIT_OVERWRITE') && IMAGE_EDIT_OVERWRITE ) {
+ // delete only if it's edited image
+ if ( preg_match('/-e[0-9]{13}\./', $parts['basename']) ) {
+ /** This filter is documented in wp-admin/custom-header.php */
+ $delpath = apply_filters('wp_delete_file', $file);
+ @unlink($delpath);
+ }
+ } elseif ( isset( $meta['width'], $meta['height'] ) ) {
+ $backup_sizes["full-$suffix"] = array('width' => $meta['width'], 'height' => $meta['height'], 'file' => $parts['basename']);
+ }
+ }
+
+ $restored_file = path_join($parts['dirname'], $data['file']);
+ $restored = update_attached_file($post_id, $restored_file);
+
+ $meta['file'] = _wp_relative_upload_path( $restored_file );
+ $meta['width'] = $data['width'];
+ $meta['height'] = $data['height'];
+ }
+
+ foreach ( $default_sizes as $default_size ) {
+ if ( isset($backup_sizes["$default_size-orig"]) ) {
+ $data = $backup_sizes["$default_size-orig"];
+ if ( isset($meta['sizes'][$default_size]) && $meta['sizes'][$default_size]['file'] != $data['file'] ) {
+ if ( defined('IMAGE_EDIT_OVERWRITE') && IMAGE_EDIT_OVERWRITE ) {
+ // delete only if it's edited image
+ if ( preg_match('/-e[0-9]{13}-/', $meta['sizes'][$default_size]['file']) ) {
+ /** This filter is documented in wp-admin/custom-header.php */
+ $delpath = apply_filters( 'wp_delete_file', path_join($parts['dirname'], $meta['sizes'][$default_size]['file']) );
+ @unlink($delpath);
+ }
+ } else {
+ $backup_sizes["$default_size-{$suffix}"] = $meta['sizes'][$default_size];
+ }
+ }
+
+ $meta['sizes'][$default_size] = $data;
+ } else {
+ unset($meta['sizes'][$default_size]);
+ }
+ }
+
+ if ( !wp_update_attachment_metadata($post_id, $meta) || !update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes) ) {
+ $msg->error = __('Cannot save image metadata.');
+ return $msg;
+ }
+
+ if ( !$restored )
+ $msg->error = __('Image metadata is inconsistent.');
+ else
+ $msg->msg = __('Image restored successfully.');
+
+ return $msg;
+}
+
+/**
+ * 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 );
+
+ $img = wp_get_image_editor( _load_image_to_edit_path( $post_id, 'full' ) );
+ if ( is_wp_error( $img ) ) {
+ $return->error = esc_js( __('Unable to create new image.') );
+ return $return;
+ }
+
+ $fwidth = !empty($_REQUEST['fwidth']) ? intval($_REQUEST['fwidth']) : 0;
+ $fheight = !empty($_REQUEST['fheight']) ? intval($_REQUEST['fheight']) : 0;
+ $target = !empty($_REQUEST['target']) ? preg_replace('/[^a-z0-9_-]+/i', '', $_REQUEST['target']) : '';
+ $scale = !empty($_REQUEST['do']) && 'scale' == $_REQUEST['do'];
+
+ if ( $scale && $fwidth > 0 && $fheight > 0 ) {
+ $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
+ if ( $img->resize( $fwidth, $fheight ) )
+ $scaled = true;
+ }
+
+ if ( !$scaled ) {
+ $return->error = esc_js( __('Error while saving the scaled image. Please reload the page and try again.') );
+ return $return;
+ }
+ } elseif ( !empty($_REQUEST['history']) ) {
+ $changes = json_decode( wp_unslash($_REQUEST['history']) );
+ if ( $changes )
+ $img = image_edit_apply_changes($img, $changes);
+ } else {
+ $return->error = esc_js( __('Nothing to save, the image has not changed.') );
+ return $return;
+ }
+
+ $meta = wp_get_attachment_metadata($post_id);
+ $backup_sizes = get_post_meta( $post->ID, '_wp_attachment_backup_sizes', true );
+
+ if ( !is_array($meta) ) {
+ $return->error = esc_js( __('Image data does not exist. Please re-upload the image.') );
+ return $return;
+ }
+
+ if ( !is_array($backup_sizes) )
+ $backup_sizes = array();
+
+ // generate new filename
+ $path = get_attached_file($post_id);
+ $path_parts = pathinfo( $path );
+ $filename = $path_parts['filename'];
+ $suffix = time() . rand(100, 999);
+
+ if ( defined('IMAGE_EDIT_OVERWRITE') && IMAGE_EDIT_OVERWRITE &&
+ isset($backup_sizes['full-orig']) && $backup_sizes['full-orig']['file'] != $path_parts['basename'] ) {
+
+ if ( 'thumbnail' == $target )
+ $new_path = "{$path_parts['dirname']}/{$filename}-temp.{$path_parts['extension']}";
+ else
+ $new_path = $path;
+ } else {
+ while( true ) {
+ $filename = preg_replace( '/-e([0-9]+)$/', '', $filename );
+ $filename .= "-e{$suffix}";
+ $new_filename = "{$filename}.{$path_parts['extension']}";
+ $new_path = "{$path_parts['dirname']}/$new_filename";
+ if ( file_exists($new_path) )
+ $suffix++;
+ else
+ break;
+ }
+ }
+
+ // save the full-size file, also needed to create sub-sizes
+ if ( !wp_save_image_file($new_path, $img, $post->post_mime_type, $post_id) ) {
+ $return->error = esc_js( __('Unable to save the image.') );
+ return $return;
+ }
+
+ if ( 'nothumb' == $target || 'all' == $target || 'full' == $target || $scaled ) {
+ $tag = false;
+ if ( isset($backup_sizes['full-orig']) ) {
+ if ( ( !defined('IMAGE_EDIT_OVERWRITE') || !IMAGE_EDIT_OVERWRITE ) && $backup_sizes['full-orig']['file'] != $path_parts['basename'] )
+ $tag = "full-$suffix";
+ } else {
+ $tag = 'full-orig';
+ }
+
+ if ( $tag )
+ $backup_sizes[$tag] = array('width' => $meta['width'], 'height' => $meta['height'], 'file' => $path_parts['basename']);
+
+ $success = update_attached_file( $post_id, $new_path );
+
+ $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();
+ if ( 'nothumb' == $target )
+ $sizes = array_diff( $sizes, array('thumbnail') );
+ }
+
+ $return->fw = $meta['width'];
+ $return->fh = $meta['height'];
+ } elseif ( 'thumbnail' == $target ) {
+ $sizes = array( 'thumbnail' );
+ $success = $delete = $nocrop = true;
+ }
+
+ if ( isset( $sizes ) ) {
+ $_sizes = array();
+
+ foreach ( $sizes as $size ) {
+ $tag = false;
+ 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";
+ } else {
+ $tag = "$size-orig";
+ }
+
+ if ( $tag )
+ $backup_sizes[$tag] = $meta['sizes'][$size];
+ }
+
+ $crop = $nocrop ? false : get_option("{$size}_crop");
+ $_sizes[ $size ] = array( 'width' => get_option("{$size}_size_w"), 'height' => get_option("{$size}_size_h"), 'crop' => $crop );
+ }
+
+ $meta['sizes'] = array_merge( $meta['sizes'], $img->multi_resize( $_sizes ) );
+ }
+
+ unset( $img );
+
+ if ( $success ) {
+ 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' ) {
+ // Check if it's an image edit from attachment edit screen
+ if ( ! empty( $_REQUEST['context'] ) && 'edit-attachment' == $_REQUEST['context'] ) {
+ $thumb_url = wp_get_attachment_image_src( $post_id, array( 900, 600 ), true );
+ $return->thumbnail = $thumb_url[0];
+ } else {
+ $file_url = wp_get_attachment_url($post_id);
+ if ( $thumb = $meta['sizes']['thumbnail'] )
+ $return->thumbnail = path_join( dirname($file_url), $thumb['file'] );
+ else
+ $return->thumbnail = "$file_url?w=128&h=128";
+ }
+ }
+ } else {
+ $delete = true;
+ }
+
+ if ( $delete ) {
+ /** This filter is documented in wp-admin/custom-header.php */
+ $delpath = apply_filters('wp_delete_file', $new_path);
+ @unlink( $delpath );
+ }
+
+ $return->msg = esc_js( __('Image saved') );
+ return $return;
+}