wp/wp-admin/includes/image-edit.php
changeset 5 5e2f62d02dcd
parent 0 d970ebf37754
child 7 cf61fcea0001
equal deleted inserted replaced
4:346c88efed21 5:5e2f62d02dcd
     4  *
     4  *
     5  * @package WordPress
     5  * @package WordPress
     6  * @subpackage Administration
     6  * @subpackage Administration
     7  */
     7  */
     8 
     8 
       
     9 /**
       
    10  * Loads the WP image-editing interface.
       
    11  *
       
    12  * @param int         $post_id Post ID.
       
    13  * @param bool|object $msg     Optional. Message to display for image editor updates or errors.
       
    14  *                             Default false.
       
    15  */
     9 function wp_image_editor($post_id, $msg = false) {
    16 function wp_image_editor($post_id, $msg = false) {
    10 	$nonce = wp_create_nonce("image_editor-$post_id");
    17 	$nonce = wp_create_nonce("image_editor-$post_id");
    11 	$meta = wp_get_attachment_metadata($post_id);
    18 	$meta = wp_get_attachment_metadata($post_id);
    12 	$thumb = image_get_intermediate_size($post_id, 'thumbnail');
    19 	$thumb = image_get_intermediate_size($post_id, 'thumbnail');
    13 	$sub_sizes = isset($meta['sizes']) && is_array($meta['sizes']);
    20 	$sub_sizes = isset($meta['sizes']) && is_array($meta['sizes']);
    32 			$note = "<div class='updated'><p>$msg->msg</p></div>";
    39 			$note = "<div class='updated'><p>$msg->msg</p></div>";
    33 	}
    40 	}
    34 
    41 
    35 	?>
    42 	?>
    36 	<div class="imgedit-wrap">
    43 	<div class="imgedit-wrap">
    37 	<?php echo $note; ?>
    44 	<div id="imgedit-panel-<?php echo $post_id; ?>">
    38 	<table id="imgedit-panel-<?php echo $post_id; ?>"><tbody>
    45 
    39 	<tr><td>
    46 	<div class="imgedit-settings">
    40 	<div class="imgedit-menu">
       
    41 		<div onclick="imageEdit.crop(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-crop disabled" title="<?php esc_attr_e( 'Crop' ); ?>"></div><?php
       
    42 
       
    43 	// On some setups GD library does not provide imagerotate() - Ticket #11536
       
    44 	if ( wp_image_editor_supports( array( 'mime_type' => get_post_mime_type( $post_id ), 'methods' => array( 'rotate' ) ) ) ) { ?>
       
    45 		<div class="imgedit-rleft"  onclick="imageEdit.rotate( 90, <?php echo "$post_id, '$nonce'"; ?>, this)" title="<?php esc_attr_e( 'Rotate counter-clockwise' ); ?>"></div>
       
    46 		<div class="imgedit-rright" onclick="imageEdit.rotate(-90, <?php echo "$post_id, '$nonce'"; ?>, this)" title="<?php esc_attr_e( 'Rotate clockwise' ); ?>"></div>
       
    47 <?php } else {
       
    48 		$note_no_rotate = esc_attr__('Image rotation is not supported by your web host.');
       
    49 ?>
       
    50 	    <div class="imgedit-rleft disabled"  title="<?php echo $note_no_rotate; ?>"></div>
       
    51 	    <div class="imgedit-rright disabled" title="<?php echo $note_no_rotate; ?>"></div>
       
    52 <?php } ?>
       
    53 
       
    54 		<div onclick="imageEdit.flip(1, <?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-flipv" title="<?php esc_attr_e( 'Flip vertically' ); ?>"></div>
       
    55 		<div onclick="imageEdit.flip(2, <?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-fliph" title="<?php esc_attr_e( 'Flip horizontally' ); ?>"></div>
       
    56 
       
    57 		<div id="image-undo-<?php echo $post_id; ?>" onclick="imageEdit.undo(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-undo disabled" title="<?php esc_attr_e( 'Undo' ); ?>"></div>
       
    58 		<div id="image-redo-<?php echo $post_id; ?>" onclick="imageEdit.redo(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-redo disabled" title="<?php esc_attr_e( 'Redo' ); ?>"></div>
       
    59 		<br class="clear" />
       
    60 	</div>
       
    61 
       
    62 	<input type="hidden" id="imgedit-sizer-<?php echo $post_id; ?>" value="<?php echo $sizer; ?>" />
       
    63 	<input type="hidden" id="imgedit-minthumb-<?php echo $post_id; ?>" value="<?php echo ( get_option('thumbnail_size_w') . ':' . get_option('thumbnail_size_h') ); ?>" />
       
    64 	<input type="hidden" id="imgedit-history-<?php echo $post_id; ?>" value="" />
       
    65 	<input type="hidden" id="imgedit-undone-<?php echo $post_id; ?>" value="0" />
       
    66 	<input type="hidden" id="imgedit-selection-<?php echo $post_id; ?>" value="" />
       
    67 	<input type="hidden" id="imgedit-x-<?php echo $post_id; ?>" value="<?php echo isset( $meta['width'] ) ? $meta['width'] : 0; ?>" />
       
    68 	<input type="hidden" id="imgedit-y-<?php echo $post_id; ?>" value="<?php echo isset( $meta['height'] ) ? $meta['height'] : 0; ?>" />
       
    69 
       
    70 	<div id="imgedit-crop-<?php echo $post_id; ?>" class="imgedit-crop-wrap">
       
    71 	<img id="image-preview-<?php echo $post_id; ?>" onload="imageEdit.imgLoaded('<?php echo $post_id; ?>')" src="<?php echo admin_url( 'admin-ajax.php', 'relative' ); ?>?action=imgedit-preview&amp;_ajax_nonce=<?php echo $nonce; ?>&amp;postid=<?php echo $post_id; ?>&amp;rand=<?php echo rand(1, 99999); ?>" />
       
    72 	</div>
       
    73 
       
    74 	<div class="imgedit-submit">
       
    75 		<input type="button" onclick="imageEdit.close(<?php echo $post_id; ?>, 1)" class="button" value="<?php esc_attr_e( 'Cancel' ); ?>" />
       
    76 		<input type="button" onclick="imageEdit.save(<?php echo "$post_id, '$nonce'"; ?>)" disabled="disabled" class="button-primary imgedit-submit-btn" value="<?php esc_attr_e( 'Save' ); ?>" />
       
    77 	</div>
       
    78 	</td>
       
    79 
       
    80 	<td class="imgedit-settings">
       
    81 	<div class="imgedit-group">
    47 	<div class="imgedit-group">
    82 	<div class="imgedit-group-top">
    48 	<div class="imgedit-group-top">
    83 		<a class="imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);return false;" href="#"><strong><?php _e('Scale Image'); ?></strong></a>
    49 		<h3><?php _e( 'Scale Image' ); ?> <a href="#" class="dashicons dashicons-editor-help imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);return false;"></a></h3>
    84 		<div class="imgedit-help">
    50 		<div class="imgedit-help">
    85 		<p><?php _e('You can proportionally scale the original image. For best results the scaling should be done before performing any other operations on it like crop, rotate, etc. Note that images can only be scaled down, not up.'); ?></p>
    51 		<p><?php _e('You can proportionally scale the original image. For best results, scaling should be done before you crop, flip, or rotate. Images can only be scaled down, not up.'); ?></p>
       
    52 		</div>
    86 		<?php if ( isset( $meta['width'], $meta['height'] ) ): ?>
    53 		<?php if ( isset( $meta['width'], $meta['height'] ) ): ?>
    87 		<p><?php printf( __('Original dimensions %s'), $meta['width'] . '&times;' . $meta['height'] ); ?></p>
    54 		<p><?php printf( __('Original dimensions %s'), $meta['width'] . ' &times; ' . $meta['height'] ); ?></p>
    88 		<?php endif ?>
    55 		<?php endif ?>
    89 		<div class="imgedit-submit">
    56 		<div class="imgedit-submit">
    90 		<span class="nowrap"><input type="text" id="imgedit-scale-width-<?php echo $post_id; ?>" onkeyup="imageEdit.scaleChanged(<?php echo $post_id; ?>, 1)" onblur="imageEdit.scaleChanged(<?php echo $post_id; ?>, 1)" style="width:4em;" value="<?php echo isset( $meta['width'] ) ? $meta['width'] : 0; ?>" />&times;<input type="text" id="imgedit-scale-height-<?php echo $post_id; ?>" onkeyup="imageEdit.scaleChanged(<?php echo $post_id; ?>, 0)" onblur="imageEdit.scaleChanged(<?php echo $post_id; ?>, 0)" style="width:4em;" value="<?php echo isset( $meta['height'] ) ? $meta['height'] : 0; ?>" />
    57 		<span class="nowrap"><input type="text" id="imgedit-scale-width-<?php echo $post_id; ?>" onkeyup="imageEdit.scaleChanged(<?php echo $post_id; ?>, 1)" onblur="imageEdit.scaleChanged(<?php echo $post_id; ?>, 1)" style="width:4em;" value="<?php echo isset( $meta['width'] ) ? $meta['width'] : 0; ?>" /> &times; <input type="text" id="imgedit-scale-height-<?php echo $post_id; ?>" onkeyup="imageEdit.scaleChanged(<?php echo $post_id; ?>, 0)" onblur="imageEdit.scaleChanged(<?php echo $post_id; ?>, 0)" style="width:4em;" value="<?php echo isset( $meta['height'] ) ? $meta['height'] : 0; ?>" />
    91 		<span class="imgedit-scale-warn" id="imgedit-scale-warn-<?php echo $post_id; ?>">!</span></span>
    58 		<span class="imgedit-scale-warn" id="imgedit-scale-warn-<?php echo $post_id; ?>">!</span></span>
    92 		<input type="button" onclick="imageEdit.action(<?php echo "$post_id, '$nonce'"; ?>, 'scale')" class="button-primary" value="<?php esc_attr_e( 'Scale' ); ?>" />
    59 		<input type="button" onclick="imageEdit.action(<?php echo "$post_id, '$nonce'"; ?>, 'scale')" class="button button-primary" value="<?php esc_attr_e( 'Scale' ); ?>" />
       
    60 		</div>
       
    61 	</div>
       
    62 	</div>
       
    63 
       
    64 <?php if ( $can_restore ) { ?>
       
    65 
       
    66 	<div class="imgedit-group">
       
    67 	<div class="imgedit-group-top">
       
    68 		<h3><a onclick="imageEdit.toggleHelp(this);return false;" href="#"><?php _e('Restore Original Image'); ?> <span class="dashicons dashicons-arrow-down imgedit-help-toggle"></span></a></h3>
       
    69 		<div class="imgedit-help">
       
    70 		<p><?php _e('Discard any changes and restore the original image.');
       
    71 
       
    72 		if ( !defined('IMAGE_EDIT_OVERWRITE') || !IMAGE_EDIT_OVERWRITE )
       
    73 			echo ' '.__('Previously edited copies of the image will not be deleted.');
       
    74 
       
    75 		?></p>
       
    76 		<div class="imgedit-submit">
       
    77 		<input type="button" onclick="imageEdit.action(<?php echo "$post_id, '$nonce'"; ?>, 'restore')" class="button button-primary" value="<?php esc_attr_e( 'Restore image' ); ?>" <?php echo $can_restore; ?> />
    93 		</div>
    78 		</div>
    94 		</div>
    79 		</div>
    95 	</div>
    80 	</div>
    96 
       
    97 <?php if ( $can_restore ) { ?>
       
    98 
       
    99 	<div class="imgedit-group-top">
       
   100 		<a class="imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);return false;" href="#"><strong><?php _e('Restore Original Image'); ?></strong></a>
       
   101 		<div class="imgedit-help">
       
   102 		<p><?php _e('Discard any changes and restore the original image.');
       
   103 
       
   104 		if ( !defined('IMAGE_EDIT_OVERWRITE') || !IMAGE_EDIT_OVERWRITE )
       
   105 			echo ' '.__('Previously edited copies of the image will not be deleted.');
       
   106 
       
   107 		?></p>
       
   108 		<div class="imgedit-submit">
       
   109 		<input type="button" onclick="imageEdit.action(<?php echo "$post_id, '$nonce'"; ?>, 'restore')" class="button-primary" value="<?php esc_attr_e( 'Restore image' ); ?>" <?php echo $can_restore; ?> />
       
   110 		</div>
       
   111 		</div>
       
   112 	</div>
    81 	</div>
   113 
    82 
   114 <?php } ?>
    83 <?php } ?>
   115 
       
   116 	</div>
       
   117 
    84 
   118 	<div class="imgedit-group">
    85 	<div class="imgedit-group">
   119 	<div class="imgedit-group-top">
    86 	<div class="imgedit-group-top">
   120 		<strong><?php _e('Image Crop'); ?></strong>
    87 		<h3><?php _e('Image Crop'); ?> <a href="#" class="dashicons dashicons-editor-help imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);return false;"></a></h3>
   121 		<a class="imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);return false;" href="#"><?php _e('(help)'); ?></a>
    88 
   122 		<div class="imgedit-help">
    89 		<div class="imgedit-help">
   123 		<p><?php _e('The image can be cropped by clicking on it and dragging to select the desired part. While dragging the dimensions of the selection are displayed below.'); ?></p>
    90 		<p><?php _e('To crop the image, click on it and drag to make your selection.'); ?></p>
   124 
    91 
   125 		<p><strong><?php _e('Crop Aspect Ratio'); ?></strong><br />
    92 		<p><strong><?php _e('Crop Aspect Ratio'); ?></strong><br />
   126 		<?php _e('You can specify the crop selection aspect ratio then hold down the Shift key while dragging to lock it. The values can be 1:1 (square), 4:3, 16:9, etc. If there is a selection, specifying aspect ratio will set it immediately.'); ?></p>
    93 		<?php _e('The aspect ratio is the relationship between the width and height. You can preserve the aspect ratio by holding down the shift key while resizing your selection. Use the input box to specify the aspect ratio, e.g. 1:1 (square), 4:3, 16:9, etc.'); ?></p>
   127 
    94 
   128 		<p><strong><?php _e('Crop Selection'); ?></strong><br />
    95 		<p><strong><?php _e('Crop Selection'); ?></strong><br />
   129 		<?php _e('Once started, the selection can be adjusted by entering new values (in pixels). Note that these values are scaled to approximately match the original image dimensions. The minimum selection size equals the thumbnail size as set in the Media settings.'); ?></p>
    96 		<?php _e('Once you have made your selection, you can adjust it by entering the size in pixels. The minimum selection size is the thumbnail size as set in the Media settings.'); ?></p>
   130 		</div>
    97 		</div>
   131 	</div>
    98 	</div>
   132 
    99 
   133 	<p>
   100 	<p>
   134 		<?php _e('Aspect ratio:'); ?>
   101 		<?php _e('Aspect ratio:'); ?>
   141 
   108 
   142 	<p id="imgedit-crop-sel-<?php echo $post_id; ?>">
   109 	<p id="imgedit-crop-sel-<?php echo $post_id; ?>">
   143 		<?php _e('Selection:'); ?>
   110 		<?php _e('Selection:'); ?>
   144 		<span  class="nowrap">
   111 		<span  class="nowrap">
   145 		<input type="text" id="imgedit-sel-width-<?php echo $post_id; ?>" onkeyup="imageEdit.setNumSelection(<?php echo $post_id; ?>)" style="width:4em;" />
   112 		<input type="text" id="imgedit-sel-width-<?php echo $post_id; ?>" onkeyup="imageEdit.setNumSelection(<?php echo $post_id; ?>)" style="width:4em;" />
   146 		:
   113 		&times;
   147 		<input type="text" id="imgedit-sel-height-<?php echo $post_id; ?>" onkeyup="imageEdit.setNumSelection(<?php echo $post_id; ?>)" style="width:4em;" />
   114 		<input type="text" id="imgedit-sel-height-<?php echo $post_id; ?>" onkeyup="imageEdit.setNumSelection(<?php echo $post_id; ?>)" style="width:4em;" />
   148 		</span>
   115 		</span>
   149 	</p>
   116 	</p>
   150 	</div>
   117 	</div>
   151 
   118 
   153 		$thumb_img = wp_constrain_dimensions( $thumb['width'], $thumb['height'], 160, 120 );
   120 		$thumb_img = wp_constrain_dimensions( $thumb['width'], $thumb['height'], 160, 120 );
   154 	?>
   121 	?>
   155 
   122 
   156 	<div class="imgedit-group imgedit-applyto">
   123 	<div class="imgedit-group imgedit-applyto">
   157 	<div class="imgedit-group-top">
   124 	<div class="imgedit-group-top">
   158 		<strong><?php _e('Thumbnail Settings'); ?></strong>
   125 		<h3><?php _e('Thumbnail Settings'); ?> <a href="#" class="dashicons dashicons-editor-help imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);return false;"></a></h3>
   159 		<a class="imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);return false;" href="#"><?php _e('(help)'); ?></a>
   126 		<p class="imgedit-help"><?php _e('You can edit the image while preserving the thumbnail. For example, you may wish to have a square thumbnail that displays just a section of the image.'); ?></p>
   160 		<p class="imgedit-help"><?php _e('The thumbnail image can be cropped differently. For example it can be square or contain only a portion of the original image to showcase it better. Here you can select whether to apply changes to all image sizes or make the thumbnail different.'); ?></p>
       
   161 	</div>
   127 	</div>
   162 
   128 
   163 	<p>
   129 	<p>
   164 		<img src="<?php echo $thumb['url']; ?>" width="<?php echo $thumb_img[0]; ?>" height="<?php echo $thumb_img[1]; ?>" class="imgedit-size-preview" alt="" /><br /><?php _e('Current thumbnail'); ?>
   130 		<img src="<?php echo $thumb['url']; ?>" width="<?php echo $thumb_img[0]; ?>" height="<?php echo $thumb_img[1]; ?>" class="imgedit-size-preview" alt="" draggable="false" />
       
   131 		<br /><?php _e('Current thumbnail'); ?>
   165 	</p>
   132 	</p>
   166 
   133 
   167 	<p id="imgedit-save-target-<?php echo $post_id; ?>">
   134 	<p id="imgedit-save-target-<?php echo $post_id; ?>">
   168 		<strong><?php _e('Apply changes to:'); ?></strong><br />
   135 		<strong><?php _e('Apply changes to:'); ?></strong><br />
   169 
   136 
   181 	</p>
   148 	</p>
   182 	</div>
   149 	</div>
   183 
   150 
   184 	<?php } ?>
   151 	<?php } ?>
   185 
   152 
   186 	</td></tr>
   153 	</div>
   187 	</tbody></table>
   154 
       
   155 	<div class="imgedit-panel-content">
       
   156 		<?php echo $note; ?>
       
   157 		<div class="imgedit-menu">
       
   158 			<div onclick="imageEdit.crop(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-crop disabled" title="<?php esc_attr_e( 'Crop' ); ?>"></div><?php
       
   159 
       
   160 		// On some setups GD library does not provide imagerotate() - Ticket #11536
       
   161 		if ( wp_image_editor_supports( array( 'mime_type' => get_post_mime_type( $post_id ), 'methods' => array( 'rotate' ) ) ) ) { ?>
       
   162 			<div class="imgedit-rleft"  onclick="imageEdit.rotate( 90, <?php echo "$post_id, '$nonce'"; ?>, this)" title="<?php esc_attr_e( 'Rotate counter-clockwise' ); ?>"></div>
       
   163 			<div class="imgedit-rright" onclick="imageEdit.rotate(-90, <?php echo "$post_id, '$nonce'"; ?>, this)" title="<?php esc_attr_e( 'Rotate clockwise' ); ?>"></div>
       
   164 	<?php } else {
       
   165 			$note_no_rotate = esc_attr__('Image rotation is not supported by your web host.');
       
   166 	?>
       
   167 		    <div class="imgedit-rleft disabled"  title="<?php echo $note_no_rotate; ?>"></div>
       
   168 		    <div class="imgedit-rright disabled" title="<?php echo $note_no_rotate; ?>"></div>
       
   169 	<?php } ?>
       
   170 
       
   171 			<div onclick="imageEdit.flip(1, <?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-flipv" title="<?php esc_attr_e( 'Flip vertically' ); ?>"></div>
       
   172 			<div onclick="imageEdit.flip(2, <?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-fliph" title="<?php esc_attr_e( 'Flip horizontally' ); ?>"></div>
       
   173 
       
   174 			<div id="image-undo-<?php echo $post_id; ?>" onclick="imageEdit.undo(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-undo disabled" title="<?php esc_attr_e( 'Undo' ); ?>"></div>
       
   175 			<div id="image-redo-<?php echo $post_id; ?>" onclick="imageEdit.redo(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-redo disabled" title="<?php esc_attr_e( 'Redo' ); ?>"></div>
       
   176 			<br class="clear" />
       
   177 		</div>
       
   178 
       
   179 		<input type="hidden" id="imgedit-sizer-<?php echo $post_id; ?>" value="<?php echo $sizer; ?>" />
       
   180 		<input type="hidden" id="imgedit-history-<?php echo $post_id; ?>" value="" />
       
   181 		<input type="hidden" id="imgedit-undone-<?php echo $post_id; ?>" value="0" />
       
   182 		<input type="hidden" id="imgedit-selection-<?php echo $post_id; ?>" value="" />
       
   183 		<input type="hidden" id="imgedit-x-<?php echo $post_id; ?>" value="<?php echo isset( $meta['width'] ) ? $meta['width'] : 0; ?>" />
       
   184 		<input type="hidden" id="imgedit-y-<?php echo $post_id; ?>" value="<?php echo isset( $meta['height'] ) ? $meta['height'] : 0; ?>" />
       
   185 
       
   186 		<div id="imgedit-crop-<?php echo $post_id; ?>" class="imgedit-crop-wrap">
       
   187 		<img id="image-preview-<?php echo $post_id; ?>" onload="imageEdit.imgLoaded('<?php echo $post_id; ?>')" src="<?php echo admin_url( 'admin-ajax.php', 'relative' ); ?>?action=imgedit-preview&amp;_ajax_nonce=<?php echo $nonce; ?>&amp;postid=<?php echo $post_id; ?>&amp;rand=<?php echo rand(1, 99999); ?>" />
       
   188 		</div>
       
   189 
       
   190 		<div class="imgedit-submit">
       
   191 			<input type="button" onclick="imageEdit.close(<?php echo $post_id; ?>, 1)" class="button" value="<?php esc_attr_e( 'Cancel' ); ?>" />
       
   192 			<input type="button" onclick="imageEdit.save(<?php echo "$post_id, '$nonce'"; ?>)" disabled="disabled" class="button button-primary imgedit-submit-btn" value="<?php esc_attr_e( 'Save' ); ?>" />
       
   193 		</div>
       
   194 	</div>
       
   195 
       
   196 	</div>
   188 	<div class="imgedit-wait" id="imgedit-wait-<?php echo $post_id; ?>"></div>
   197 	<div class="imgedit-wait" id="imgedit-wait-<?php echo $post_id; ?>"></div>
   189 	<script type="text/javascript">jQuery( function() { imageEdit.init(<?php echo $post_id; ?>); });</script>
   198 	<script type="text/javascript">jQuery( function() { imageEdit.init(<?php echo $post_id; ?>); });</script>
   190 	<div class="hidden" id="imgedit-leaving-<?php echo $post_id; ?>"><?php _e("There are unsaved changes that will be lost. 'OK' to continue, 'Cancel' to return to the Image Editor."); ?></div>
   199 	<div class="hidden" id="imgedit-leaving-<?php echo $post_id; ?>"><?php _e("There are unsaved changes that will be lost. 'OK' to continue, 'Cancel' to return to the Image Editor."); ?></div>
   191 	</div>
   200 	</div>
   192 <?php
   201 <?php
   201  * @param int $post_id
   210  * @param int $post_id
   202  * @return boolean
   211  * @return boolean
   203  */
   212  */
   204 function wp_stream_image( $image, $mime_type, $post_id ) {
   213 function wp_stream_image( $image, $mime_type, $post_id ) {
   205 	if ( $image instanceof WP_Image_Editor ) {
   214 	if ( $image instanceof WP_Image_Editor ) {
   206 		$image = apply_filters('image_editor_save_pre', $image, $post_id);
   215 
       
   216 		/**
       
   217 		 * Filter the WP_Image_Editor instance for the image to be streamed to the browser.
       
   218 		 *
       
   219 		 * @since 3.5.0
       
   220 		 *
       
   221 		 * @param WP_Image_Editor $image   WP_Image_Editor instance.
       
   222 		 * @param int             $post_id Post ID.
       
   223 		 */
       
   224 		$image = apply_filters( 'image_editor_save_pre', $image, $post_id );
   207 
   225 
   208 		if ( is_wp_error( $image->stream( $mime_type ) ) )
   226 		if ( is_wp_error( $image->stream( $mime_type ) ) )
   209 			return false;
   227 			return false;
   210 
   228 
   211 		return true;
   229 		return true;
   212 	} else {
   230 	} else {
   213 		_deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) );
   231 		_deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) );
   214 
   232 
   215 		$image = apply_filters('image_save_pre', $image, $post_id);
   233 		/**
       
   234 		 * Filter the GD image resource to be streamed to the browser.
       
   235 		 *
       
   236 		 * @since 2.9.0
       
   237 		 * @deprecated 3.5.0 Use image_editor_save_pre instead.
       
   238 		 *
       
   239 		 * @param resource $image   Image resource to be streamed.
       
   240 		 * @param int      $post_id Post ID.
       
   241 		 */
       
   242 		$image = apply_filters( 'image_save_pre', $image, $post_id );
   216 
   243 
   217 		switch ( $mime_type ) {
   244 		switch ( $mime_type ) {
   218 			case 'image/jpeg':
   245 			case 'image/jpeg':
   219 				header( 'Content-Type: image/jpeg' );
   246 				header( 'Content-Type: image/jpeg' );
   220 				return imagejpeg( $image, null, 90 );
   247 				return imagejpeg( $image, null, 90 );
   239  * @param int $post_id
   266  * @param int $post_id
   240  * @return boolean
   267  * @return boolean
   241  */
   268  */
   242 function wp_save_image_file( $filename, $image, $mime_type, $post_id ) {
   269 function wp_save_image_file( $filename, $image, $mime_type, $post_id ) {
   243 	if ( $image instanceof WP_Image_Editor ) {
   270 	if ( $image instanceof WP_Image_Editor ) {
   244 		$image = apply_filters('image_editor_save_pre', $image, $post_id);
   271 
   245 		$saved = apply_filters('wp_save_image_editor_file', null, $filename, $image, $mime_type, $post_id);
   272 		/** This filter is documented in wp-admin/includes/image-edit.php */
       
   273 		$image = apply_filters( 'image_editor_save_pre', $image, $post_id );
       
   274 
       
   275 		/**
       
   276 		 * Filter whether to skip saving the image file.
       
   277 		 *
       
   278 		 * Returning a non-null value will short-circuit the save method,
       
   279 		 * returning that value instead.
       
   280 		 *
       
   281 		 * @since 3.5.0
       
   282 		 *
       
   283 		 * @param mixed           $override  Value to return instead of saving. Default null.
       
   284 		 * @param string          $filename  Name of the file to be saved.
       
   285 		 * @param WP_Image_Editor $image     WP_Image_Editor instance.
       
   286 		 * @param string          $mime_type Image mime type.
       
   287 		 * @param int             $post_id   Post ID.
       
   288 		 */
       
   289 		$saved = apply_filters( 'wp_save_image_editor_file', null, $filename, $image, $mime_type, $post_id );
   246 
   290 
   247 		if ( null !== $saved )
   291 		if ( null !== $saved )
   248 			return $saved;
   292 			return $saved;
   249 
   293 
   250 		return $image->save( $filename, $mime_type );
   294 		return $image->save( $filename, $mime_type );
   251 	} else {
   295 	} else {
   252 		_deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) );
   296 		_deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) );
   253 
   297 
   254 		$image = apply_filters('image_save_pre', $image, $post_id);
   298 		/** This filter is documented in wp-admin/includes/image-edit.php */
   255 		$saved = apply_filters('wp_save_image_file', null, $filename, $image, $mime_type, $post_id);
   299 		$image = apply_filters( 'image_save_pre', $image, $post_id );
       
   300 
       
   301 		/**
       
   302 		 * Filter whether to skip saving the image file.
       
   303 		 *
       
   304 		 * Returning a non-null value will short-circuit the save method,
       
   305 		 * returning that value instead.
       
   306 		 *
       
   307 		 * @since 2.9.0
       
   308 		 * @deprecated 3.5.0 Use wp_save_image_editor_file instead.
       
   309 		 *
       
   310 		 * @param mixed           $override  Value to return instead of saving. Default null.
       
   311 		 * @param string          $filename  Name of the file to be saved.
       
   312 		 * @param WP_Image_Editor $image     WP_Image_Editor instance.
       
   313 		 * @param string          $mime_type Image mime type.
       
   314 		 * @param int             $post_id   Post ID.
       
   315 		 */
       
   316 		$saved = apply_filters( 'wp_save_image_file', null, $filename, $image, $mime_type, $post_id );
   256 
   317 
   257 		if ( null !== $saved )
   318 		if ( null !== $saved )
   258 			return $saved;
   319 			return $saved;
   259 
   320 
   260 		switch ( $mime_type ) {
   321 		switch ( $mime_type ) {
   261 			case 'image/jpeg':
   322 			case 'image/jpeg':
       
   323 
       
   324 				/** This filter is documented in wp-includes/class-wp-image-editor.php */
   262 				return imagejpeg( $image, $filename, apply_filters( 'jpeg_quality', 90, 'edit_image' ) );
   325 				return imagejpeg( $image, $filename, apply_filters( 'jpeg_quality', 90, 'edit_image' ) );
   263 			case 'image/png':
   326 			case 'image/png':
   264 				return imagepng( $image, $filename );
   327 				return imagepng( $image, $filename );
   265 			case 'image/gif':
   328 			case 'image/gif':
   266 				return imagegif( $image, $filename );
   329 				return imagegif( $image, $filename );
   268 				return false;
   331 				return false;
   269 		}
   332 		}
   270 	}
   333 	}
   271 }
   334 }
   272 
   335 
       
   336 /**
       
   337  * Image preview ratio. Internal use only.
       
   338  *
       
   339  * @since 2.9.0
       
   340  *
       
   341  * @ignore
       
   342  * @param int $w Image width in pixels.
       
   343  * @param int $h Image height in pixels.
       
   344  * @return float|int Image preview ratio.
       
   345  */
   273 function _image_get_preview_ratio($w, $h) {
   346 function _image_get_preview_ratio($w, $h) {
   274 	$max = max($w, $h);
   347 	$max = max($w, $h);
   275 	return $max > 400 ? (400 / $max) : 1;
   348 	return $max > 400 ? (400 / $max) : 1;
   276 }
   349 }
   277 
   350 
   278 // @TODO: Returns GD resource, but is NOT public
   351 /**
       
   352  * Returns an image resource. Internal use only.
       
   353  *
       
   354  * @since 2.9.0
       
   355  *
       
   356  * @ignore
       
   357  * @param resource  $img   Image resource.
       
   358  * @param float|int $angle Image rotation angle, in degrees.
       
   359  * @return resource|false GD image resource, false otherwise.
       
   360  */
   279 function _rotate_image_resource($img, $angle) {
   361 function _rotate_image_resource($img, $angle) {
   280 	_deprecated_function( __FUNCTION__, '3.5', __( 'Use WP_Image_Editor::rotate' ) );
   362 	_deprecated_function( __FUNCTION__, '3.5', __( 'Use WP_Image_Editor::rotate' ) );
   281 	if ( function_exists('imagerotate') ) {
   363 	if ( function_exists('imagerotate') ) {
   282 		$rotated = imagerotate($img, $angle, 0);
   364 		$rotated = imagerotate($img, $angle, 0);
   283 		if ( is_resource($rotated) ) {
   365 		if ( is_resource($rotated) ) {
   287 	}
   369 	}
   288 	return $img;
   370 	return $img;
   289 }
   371 }
   290 
   372 
   291 /**
   373 /**
   292  * @TODO: Only used within image_edit_apply_changes
   374  * Flips an image resource. Internal use only.
   293  *		  and receives/returns GD Resource.
   375  *
   294  *		  Consider removal.
   376  * @since 2.9.0
   295  *
   377  *
   296  * @param GD_Resource $img
   378  * @ignore
   297  * @param boolean $horz
   379  * @param resource $img  Image resource.
   298  * @param boolean $vert
   380  * @param bool     $horz Whether to flip horizontally.
   299  * @return GD_Resource
   381  * @param bool     $vert Whether to flip vertically.
       
   382  * @return resource (maybe) flipped image resource.
   300  */
   383  */
   301 function _flip_image_resource($img, $horz, $vert) {
   384 function _flip_image_resource($img, $horz, $vert) {
   302 	_deprecated_function( __FUNCTION__, '3.5', __( 'Use WP_Image_Editor::flip' ) );
   385 	_deprecated_function( __FUNCTION__, '3.5', __( 'Use WP_Image_Editor::flip' ) );
   303 	$w = imagesx($img);
   386 	$w = imagesx($img);
   304 	$h = imagesy($img);
   387 	$h = imagesy($img);
   316 	}
   399 	}
   317 	return $img;
   400 	return $img;
   318 }
   401 }
   319 
   402 
   320 /**
   403 /**
   321  * @TODO: Only used within image_edit_apply_changes
   404  * Crops an image resource. Internal use only.
   322  *		  and receives/returns GD Resource.
   405  *
   323  *		  Consider removal.
   406  * @since 2.9.0
   324  *
   407  *
   325  * @param GD_Resource $img
   408  * @ignore
   326  * @param float $x
   409  * @param resource $img Image resource.
   327  * @param float $y
   410  * @param float    $x   Source point x-coordinate.
   328  * @param float $w
   411  * @param float    $y   Source point y-cooredinate.
   329  * @param float $h
   412  * @param float    $w   Source width.
   330  * @return GD_Resource
   413  * @param float    $h   Source height.
       
   414  * @return resource (maybe) cropped image resource.
   331  */
   415  */
   332 function _crop_image_resource($img, $x, $y, $w, $h) {
   416 function _crop_image_resource($img, $x, $y, $w, $h) {
   333 	$dst = wp_imagecreatetruecolor($w, $h);
   417 	$dst = wp_imagecreatetruecolor($w, $h);
   334 	if ( is_resource($dst) ) {
   418 	if ( is_resource($dst) ) {
   335 		if ( imagecopy($dst, $img, 0, 0, $x, $y, $w, $h) ) {
   419 		if ( imagecopy($dst, $img, 0, 0, $x, $y, $w, $h) ) {
   341 }
   425 }
   342 
   426 
   343 /**
   427 /**
   344  * Performs group of changes on Editor specified.
   428  * Performs group of changes on Editor specified.
   345  *
   429  *
   346  * @param WP_Image_Editor $image
   430  * @since 2.9.0
   347  * @param type $changes
   431  *
   348  * @return WP_Image_Editor
   432  * @param WP_Image_Editor $image   {@see WP_Image_Editor} instance.
       
   433  * @param array           $changes Array of change operations.
       
   434  * @return WP_Image_Editor {@see WP_Image_Editor} instance with changes applied.
   349  */
   435  */
   350 function image_edit_apply_changes( $image, $changes ) {
   436 function image_edit_apply_changes( $image, $changes ) {
   351 	if ( is_resource( $image ) )
   437 	if ( is_resource( $image ) )
   352 		_deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) );
   438 		_deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) );
   353 
   439 
   354 	if ( !is_array($changes) )
   440 	if ( !is_array($changes) )
   355 		return $image;
   441 		return $image;
   356 
   442 
   357 	// expand change operations
   443 	// Expand change operations.
   358 	foreach ( $changes as $key => $obj ) {
   444 	foreach ( $changes as $key => $obj ) {
   359 		if ( isset($obj->r) ) {
   445 		if ( isset($obj->r) ) {
   360 			$obj->type = 'rotate';
   446 			$obj->type = 'rotate';
   361 			$obj->angle = $obj->r;
   447 			$obj->angle = $obj->r;
   362 			unset($obj->r);
   448 			unset($obj->r);
   370 			unset($obj->c);
   456 			unset($obj->c);
   371 		}
   457 		}
   372 		$changes[$key] = $obj;
   458 		$changes[$key] = $obj;
   373 	}
   459 	}
   374 
   460 
   375 	// combine operations
   461 	// Combine operations.
   376 	if ( count($changes) > 1 ) {
   462 	if ( count($changes) > 1 ) {
   377 		$filtered = array($changes[0]);
   463 		$filtered = array($changes[0]);
   378 		for ( $i = 0, $j = 1; $j < count($changes); $j++ ) {
   464 		for ( $i = 0, $j = 1, $c = count( $changes ); $j < $c; $j++ ) {
   379 			$combined = false;
   465 			$combined = false;
   380 			if ( $filtered[$i]->type == $changes[$j]->type ) {
   466 			if ( $filtered[$i]->type == $changes[$j]->type ) {
   381 				switch ( $filtered[$i]->type ) {
   467 				switch ( $filtered[$i]->type ) {
   382 					case 'rotate':
   468 					case 'rotate':
   383 						$filtered[$i]->angle += $changes[$j]->angle;
   469 						$filtered[$i]->angle += $changes[$j]->angle;
   394 		}
   480 		}
   395 		$changes = $filtered;
   481 		$changes = $filtered;
   396 		unset($filtered);
   482 		unset($filtered);
   397 	}
   483 	}
   398 
   484 
   399 	// image resource before applying the changes
   485 	// Image resource before applying the changes.
   400 	if ( $image instanceof WP_Image_Editor )
   486 	if ( $image instanceof WP_Image_Editor ) {
   401 		$image = apply_filters('wp_image_editor_before_change', $image, $changes);
   487 
   402 	elseif ( is_resource( $image ) )
   488 		/**
   403 		$image = apply_filters('image_edit_before_change', $image, $changes);
   489 		 * Filter the WP_Image_Editor instance before applying changes to the image.
       
   490 		 *
       
   491 		 * @since 3.5.0
       
   492 		 *
       
   493 		 * @param WP_Image_Editor $image   WP_Image_Editor instance.
       
   494  		 * @param array           $changes Array of change operations.
       
   495 		 */
       
   496 		$image = apply_filters( 'wp_image_editor_before_change', $image, $changes );
       
   497 	} elseif ( is_resource( $image ) ) {
       
   498 
       
   499 		/**
       
   500 		 * Filter the GD image resource before applying changes to the image.
       
   501 		 *
       
   502 		 * @since 2.9.0
       
   503 		 * @deprecated 3.5.0 Use wp_image_editor_before_change instead.
       
   504 		 *
       
   505 		 * @param resource $image   GD image resource.
       
   506  		 * @param array    $changes Array of change operations.
       
   507 		 */
       
   508 		$image = apply_filters( 'image_edit_before_change', $image, $changes );
       
   509 	}
   404 
   510 
   405 	foreach ( $changes as $operation ) {
   511 	foreach ( $changes as $operation ) {
   406 		switch ( $operation->type ) {
   512 		switch ( $operation->type ) {
   407 			case 'rotate':
   513 			case 'rotate':
   408 				if ( $operation->angle != 0 ) {
   514 				if ( $operation->angle != 0 ) {
   448  * @param int $post_id
   554  * @param int $post_id
   449  * @return boolean
   555  * @return boolean
   450  */
   556  */
   451 function stream_preview_image( $post_id ) {
   557 function stream_preview_image( $post_id ) {
   452 	$post = get_post( $post_id );
   558 	$post = get_post( $post_id );
       
   559 
       
   560 	/** This filter is documented in wp-admin/admin.php */
   453 	@ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) );
   561 	@ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) );
   454 
   562 
   455 	$img = wp_get_image_editor( _load_image_to_edit_path( $post_id ) );
   563 	$img = wp_get_image_editor( _load_image_to_edit_path( $post_id ) );
   456 
   564 
   457     if ( is_wp_error( $img ) )
   565     if ( is_wp_error( $img ) )
   459 
   567 
   460 	$changes = !empty($_REQUEST['history']) ? json_decode( wp_unslash($_REQUEST['history']) ) : null;
   568 	$changes = !empty($_REQUEST['history']) ? json_decode( wp_unslash($_REQUEST['history']) ) : null;
   461 	if ( $changes )
   569 	if ( $changes )
   462 		$img = image_edit_apply_changes( $img, $changes );
   570 		$img = image_edit_apply_changes( $img, $changes );
   463 
   571 
   464 	// scale the image
   572 	// Scale the image.
   465 	$size = $img->get_size();
   573 	$size = $img->get_size();
   466 	$w = $size['width'];
   574 	$w = $size['width'];
   467 	$h = $size['height'];
   575 	$h = $size['height'];
   468 
   576 
   469 	$ratio = _image_get_preview_ratio( $w, $h );
   577 	$ratio = _image_get_preview_ratio( $w, $h );
   474 		return false;
   582 		return false;
   475 
   583 
   476 	return wp_stream_image( $img, $post->post_mime_type, $post_id );
   584 	return wp_stream_image( $img, $post->post_mime_type, $post_id );
   477 }
   585 }
   478 
   586 
       
   587 /**
       
   588  * Restores the metadata for a given attachment.
       
   589  *
       
   590  * @since 2.9.0
       
   591  *
       
   592  * @param int $post_id Attachment post ID.
       
   593  * @return stdClass Image restoration message object.
       
   594  */
   479 function wp_restore_image($post_id) {
   595 function wp_restore_image($post_id) {
   480 	$meta = wp_get_attachment_metadata($post_id);
   596 	$meta = wp_get_attachment_metadata($post_id);
   481 	$file = get_attached_file($post_id);
   597 	$file = get_attached_file($post_id);
   482 	$backup_sizes = get_post_meta( $post_id, '_wp_attachment_backup_sizes', true );
   598 	$backup_sizes = $old_backup_sizes = get_post_meta( $post_id, '_wp_attachment_backup_sizes', true );
   483 	$restored = false;
   599 	$restored = false;
   484 	$msg = new stdClass;
   600 	$msg = new stdClass;
   485 
   601 
   486 	if ( !is_array($backup_sizes) ) {
   602 	if ( !is_array($backup_sizes) ) {
   487 		$msg->error = __('Cannot load image metadata.');
   603 		$msg->error = __('Cannot load image metadata.');
   495 	if ( isset($backup_sizes['full-orig']) && is_array($backup_sizes['full-orig']) ) {
   611 	if ( isset($backup_sizes['full-orig']) && is_array($backup_sizes['full-orig']) ) {
   496 		$data = $backup_sizes['full-orig'];
   612 		$data = $backup_sizes['full-orig'];
   497 
   613 
   498 		if ( $parts['basename'] != $data['file'] ) {
   614 		if ( $parts['basename'] != $data['file'] ) {
   499 			if ( defined('IMAGE_EDIT_OVERWRITE') && IMAGE_EDIT_OVERWRITE ) {
   615 			if ( defined('IMAGE_EDIT_OVERWRITE') && IMAGE_EDIT_OVERWRITE ) {
   500 				// delete only if it's edited image
   616 
       
   617 				// Delete only if it's edited image.
   501 				if ( preg_match('/-e[0-9]{13}\./', $parts['basename']) ) {
   618 				if ( preg_match('/-e[0-9]{13}\./', $parts['basename']) ) {
   502 					/** This filter is documented in wp-admin/custom-header.php */
   619 					wp_delete_file( $file );
   503 					$delpath = apply_filters('wp_delete_file', $file);
       
   504 					@unlink($delpath);
       
   505 				}
   620 				}
   506 			} elseif ( isset( $meta['width'], $meta['height'] ) ) {
   621 			} elseif ( isset( $meta['width'], $meta['height'] ) ) {
   507 				$backup_sizes["full-$suffix"] = array('width' => $meta['width'], 'height' => $meta['height'], 'file' => $parts['basename']);
   622 				$backup_sizes["full-$suffix"] = array('width' => $meta['width'], 'height' => $meta['height'], 'file' => $parts['basename']);
   508 			}
   623 			}
   509 		}
   624 		}
   519 	foreach ( $default_sizes as $default_size ) {
   634 	foreach ( $default_sizes as $default_size ) {
   520 		if ( isset($backup_sizes["$default_size-orig"]) ) {
   635 		if ( isset($backup_sizes["$default_size-orig"]) ) {
   521 			$data = $backup_sizes["$default_size-orig"];
   636 			$data = $backup_sizes["$default_size-orig"];
   522 			if ( isset($meta['sizes'][$default_size]) && $meta['sizes'][$default_size]['file'] != $data['file'] ) {
   637 			if ( isset($meta['sizes'][$default_size]) && $meta['sizes'][$default_size]['file'] != $data['file'] ) {
   523 				if ( defined('IMAGE_EDIT_OVERWRITE') && IMAGE_EDIT_OVERWRITE ) {
   638 				if ( defined('IMAGE_EDIT_OVERWRITE') && IMAGE_EDIT_OVERWRITE ) {
   524 					// delete only if it's edited image
   639 
       
   640 					// Delete only if it's edited image
   525 					if ( preg_match('/-e[0-9]{13}-/', $meta['sizes'][$default_size]['file']) ) {
   641 					if ( preg_match('/-e[0-9]{13}-/', $meta['sizes'][$default_size]['file']) ) {
   526 						/** This filter is documented in wp-admin/custom-header.php */
   642 						$delete_file = path_join( $parts['dirname'], $meta['sizes'][$default_size]['file'] );
   527 						$delpath = apply_filters( 'wp_delete_file', path_join($parts['dirname'], $meta['sizes'][$default_size]['file']) );
   643 						wp_delete_file( $delete_file );
   528 						@unlink($delpath);
       
   529 					}
   644 					}
   530 				} else {
   645 				} else {
   531 					$backup_sizes["$default_size-{$suffix}"] = $meta['sizes'][$default_size];
   646 					$backup_sizes["$default_size-{$suffix}"] = $meta['sizes'][$default_size];
   532 				}
   647 				}
   533 			}
   648 			}
   536 		} else {
   651 		} else {
   537 			unset($meta['sizes'][$default_size]);
   652 			unset($meta['sizes'][$default_size]);
   538 		}
   653 		}
   539 	}
   654 	}
   540 
   655 
   541 	if ( !wp_update_attachment_metadata($post_id, $meta) || !update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes) ) {
   656 	if ( ! wp_update_attachment_metadata( $post_id, $meta ) ||
       
   657 		( $old_backup_sizes !== $backup_sizes && ! update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes ) ) ) {
       
   658 
   542 		$msg->error = __('Cannot save image metadata.');
   659 		$msg->error = __('Cannot save image metadata.');
   543 		return $msg;
   660 		return $msg;
   544 	}
   661 	}
   545 
   662 
   546 	if ( !$restored )
   663 	if ( !$restored )
   557  *
   674  *
   558  * @param int $post_id
   675  * @param int $post_id
   559  * @return \stdClass
   676  * @return \stdClass
   560  */
   677  */
   561 function wp_save_image( $post_id ) {
   678 function wp_save_image( $post_id ) {
       
   679 	global $_wp_additional_image_sizes;
       
   680 
   562 	$return = new stdClass;
   681 	$return = new stdClass;
   563 	$success = $delete = $scaled = $nocrop = false;
   682 	$success = $delete = $scaled = $nocrop = false;
   564 	$post = get_post( $post_id );
   683 	$post = get_post( $post_id );
   565 
   684 
   566 	$img = wp_get_image_editor( _load_image_to_edit_path( $post_id, 'full' ) );
   685 	$img = wp_get_image_editor( _load_image_to_edit_path( $post_id, 'full' ) );
   577 	if ( $scale && $fwidth > 0 && $fheight > 0 ) {
   696 	if ( $scale && $fwidth > 0 && $fheight > 0 ) {
   578 		$size = $img->get_size();
   697 		$size = $img->get_size();
   579 		$sX = $size['width'];
   698 		$sX = $size['width'];
   580 		$sY = $size['height'];
   699 		$sY = $size['height'];
   581 
   700 
   582 		// check if it has roughly the same w / h ratio
   701 		// Check if it has roughly the same w / h ratio.
   583 		$diff = round($sX / $sY, 2) - round($fwidth / $fheight, 2);
   702 		$diff = round($sX / $sY, 2) - round($fwidth / $fheight, 2);
   584 		if ( -0.1 < $diff && $diff < 0.1 ) {
   703 		if ( -0.1 < $diff && $diff < 0.1 ) {
   585 			// scale the full size image
   704 			// Scale the full size image.
   586 			if ( $img->resize( $fwidth, $fheight ) )
   705 			if ( $img->resize( $fwidth, $fheight ) )
   587 				$scaled = true;
   706 				$scaled = true;
   588 		}
   707 		}
   589 
   708 
   590 		if ( !$scaled ) {
   709 		if ( !$scaled ) {
   609 	}
   728 	}
   610 
   729 
   611 	if ( !is_array($backup_sizes) )
   730 	if ( !is_array($backup_sizes) )
   612 		$backup_sizes = array();
   731 		$backup_sizes = array();
   613 
   732 
   614 	// generate new filename
   733 	// Generate new filename.
   615 	$path = get_attached_file($post_id);
   734 	$path = get_attached_file($post_id);
   616 	$path_parts = pathinfo( $path );
   735 	$path_parts = pathinfo( $path );
   617 	$filename = $path_parts['filename'];
   736 	$filename = $path_parts['filename'];
   618 	$suffix = time() . rand(100, 999);
   737 	$suffix = time() . rand(100, 999);
   619 
   738 
   635 			else
   754 			else
   636 				break;
   755 				break;
   637 		}
   756 		}
   638 	}
   757 	}
   639 
   758 
   640 	// save the full-size file, also needed to create sub-sizes
   759 	// Save the full-size file, also needed to create sub-sizes.
   641 	if ( !wp_save_image_file($new_path, $img, $post->post_mime_type, $post_id) ) {
   760 	if ( !wp_save_image_file($new_path, $img, $post->post_mime_type, $post_id) ) {
   642 		$return->error = esc_js( __('Unable to save the image.') );
   761 		$return->error = esc_js( __('Unable to save the image.') );
   643 		return $return;
   762 		return $return;
   644 	}
   763 	}
   645 
   764 
   653 		}
   772 		}
   654 
   773 
   655 		if ( $tag )
   774 		if ( $tag )
   656 			$backup_sizes[$tag] = array('width' => $meta['width'], 'height' => $meta['height'], 'file' => $path_parts['basename']);
   775 			$backup_sizes[$tag] = array('width' => $meta['width'], 'height' => $meta['height'], 'file' => $path_parts['basename']);
   657 
   776 
   658 		$success = update_attached_file( $post_id, $new_path );
   777 		$success = ( $path === $new_path ) || update_attached_file( $post_id, $new_path );
   659 
   778 
   660 		$meta['file'] = _wp_relative_upload_path( $new_path );
   779 		$meta['file'] = _wp_relative_upload_path( $new_path );
   661 
   780 
   662 		$size = $img->get_size();
   781 		$size = $img->get_size();
   663 		$meta['width'] = $size['width'];
   782 		$meta['width'] = $size['width'];
   691 
   810 
   692 				if ( $tag )
   811 				if ( $tag )
   693 					$backup_sizes[$tag] = $meta['sizes'][$size];
   812 					$backup_sizes[$tag] = $meta['sizes'][$size];
   694 			}
   813 			}
   695 
   814 
   696 			$crop = $nocrop ? false : get_option("{$size}_crop");
   815 			if ( isset( $_wp_additional_image_sizes[ $size ] ) ) {
   697 			$_sizes[ $size ] = array( 'width' => get_option("{$size}_size_w"), 'height' => get_option("{$size}_size_h"), 'crop' => $crop );
   816 				$width  = intval( $_wp_additional_image_sizes[ $size ]['width'] );
       
   817 				$height = intval( $_wp_additional_image_sizes[ $size ]['height'] );
       
   818 				$crop   = ( $nocrop ) ? false : $_wp_additional_image_sizes[ $size ]['crop'];
       
   819 			} else {
       
   820 				$height = get_option( "{$size}_size_h" );
       
   821 				$width  = get_option( "{$size}_size_w" );
       
   822 				$crop   = ( $nocrop ) ? false : get_option( "{$size}_crop" );
       
   823 			}
       
   824 
       
   825 			$_sizes[ $size ] = array( 'width' => $width, 'height' => $height, 'crop' => $crop );
   698 		}
   826 		}
   699 
   827 
   700 		$meta['sizes'] = array_merge( $meta['sizes'], $img->multi_resize( $_sizes ) );
   828 		$meta['sizes'] = array_merge( $meta['sizes'], $img->multi_resize( $_sizes ) );
   701 	}
   829 	}
   702 
   830 
   711 			if ( ! empty( $_REQUEST['context'] ) && 'edit-attachment' == $_REQUEST['context'] ) {
   839 			if ( ! empty( $_REQUEST['context'] ) && 'edit-attachment' == $_REQUEST['context'] ) {
   712 				$thumb_url = wp_get_attachment_image_src( $post_id, array( 900, 600 ), true );
   840 				$thumb_url = wp_get_attachment_image_src( $post_id, array( 900, 600 ), true );
   713 				$return->thumbnail = $thumb_url[0];
   841 				$return->thumbnail = $thumb_url[0];
   714 			} else {
   842 			} else {
   715 				$file_url = wp_get_attachment_url($post_id);
   843 				$file_url = wp_get_attachment_url($post_id);
   716 				if ( $thumb = $meta['sizes']['thumbnail'] )
   844 				if ( ! empty( $meta['sizes']['thumbnail'] ) && $thumb = $meta['sizes']['thumbnail'] ) {
   717 					$return->thumbnail = path_join( dirname($file_url), $thumb['file'] );
   845 					$return->thumbnail = path_join( dirname($file_url), $thumb['file'] );
   718 				else
   846 				} else {
   719 					$return->thumbnail = "$file_url?w=128&h=128";
   847 					$return->thumbnail = "$file_url?w=128&h=128";
       
   848 				}
   720 			}
   849 			}
   721 		}
   850 		}
   722 	} else {
   851 	} else {
   723 		$delete = true;
   852 		$delete = true;
   724 	}
   853 	}
   725 
   854 
   726 	if ( $delete ) {
   855 	if ( $delete ) {
   727 		/** This filter is documented in wp-admin/custom-header.php */
   856 		wp_delete_file( $new_path );
   728 		$delpath = apply_filters('wp_delete_file', $new_path);
       
   729 		@unlink( $delpath );
       
   730 	}
   857 	}
   731 
   858 
   732 	$return->msg = esc_js( __('Image saved') );
   859 	$return->msg = esc_js( __('Image saved') );
   733 	return $return;
   860 	return $return;
   734 }
   861 }