web/wp-admin/includes/image-edit.php
changeset 204 09a1c134465b
parent 194 32102edaa81b
equal deleted inserted replaced
203:f507feede89a 204:09a1c134465b
    38 	<tr><td>
    38 	<tr><td>
    39 	<div class="imgedit-menu">
    39 	<div class="imgedit-menu">
    40 		<div onclick="imageEdit.crop(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-crop disabled" title="<?php esc_attr_e( 'Crop' ); ?>"></div><?php
    40 		<div onclick="imageEdit.crop(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-crop disabled" title="<?php esc_attr_e( 'Crop' ); ?>"></div><?php
    41 
    41 
    42 	// On some setups GD library does not provide imagerotate() - Ticket #11536
    42 	// On some setups GD library does not provide imagerotate() - Ticket #11536
    43 	if ( function_exists('imagerotate') ) { ?>
    43 	if ( wp_image_editor_supports( array( 'mime_type' => get_post_mime_type( $post_id ), 'methods' => array( 'rotate' ) ) ) ) { ?>
    44 		<div class="imgedit-rleft"  onclick="imageEdit.rotate( 90, <?php echo "$post_id, '$nonce'"; ?>, this)" title="<?php esc_attr_e( 'Rotate counter-clockwise' ); ?>"></div>
    44 		<div class="imgedit-rleft"  onclick="imageEdit.rotate( 90, <?php echo "$post_id, '$nonce'"; ?>, this)" title="<?php esc_attr_e( 'Rotate counter-clockwise' ); ?>"></div>
    45 		<div class="imgedit-rright" onclick="imageEdit.rotate(-90, <?php echo "$post_id, '$nonce'"; ?>, this)" title="<?php esc_attr_e( 'Rotate clockwise' ); ?>"></div>
    45 		<div class="imgedit-rright" onclick="imageEdit.rotate(-90, <?php echo "$post_id, '$nonce'"; ?>, this)" title="<?php esc_attr_e( 'Rotate clockwise' ); ?>"></div>
    46 <?php } else {
    46 <?php } else {
    47 		$note_gdlib = esc_attr__('Image rotation is not supported by your web host (function imagerotate() is missing)');
    47 		$note_no_rotate = esc_attr__('Image rotation is not supported by your web host.');
    48 ?>
    48 ?>
    49 	    <div class="imgedit-rleft disabled"  title="<?php echo $note_gdlib; ?>"></div>
    49 	    <div class="imgedit-rleft disabled"  title="<?php echo $note_no_rotate; ?>"></div>
    50 	    <div class="imgedit-rright disabled" title="<?php echo $note_gdlib; ?>"></div>
    50 	    <div class="imgedit-rright disabled" title="<?php echo $note_no_rotate; ?>"></div>
    51 <?php } ?>
    51 <?php } ?>
    52 
    52 
    53 		<div onclick="imageEdit.flip(1, <?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-flipv" title="<?php esc_attr_e( 'Flip vertically' ); ?>"></div>
    53 		<div onclick="imageEdit.flip(1, <?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-flipv" title="<?php esc_attr_e( 'Flip vertically' ); ?>"></div>
    54 		<div onclick="imageEdit.flip(2, <?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-fliph" title="<?php esc_attr_e( 'Flip horizontally' ); ?>"></div>
    54 		<div onclick="imageEdit.flip(2, <?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-fliph" title="<?php esc_attr_e( 'Flip horizontally' ); ?>"></div>
    55 
    55 
   116 	<div class="imgedit-group-top">
   116 	<div class="imgedit-group-top">
   117 		<strong><?php _e('Image Crop'); ?></strong>
   117 		<strong><?php _e('Image Crop'); ?></strong>
   118 		<a class="imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);return false;" href="#"><?php _e('(help)'); ?></a>
   118 		<a class="imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);return false;" href="#"><?php _e('(help)'); ?></a>
   119 		<div class="imgedit-help">
   119 		<div class="imgedit-help">
   120 		<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>
   120 		<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>
   121 		<strong><?php _e('Keyboard Shortcuts'); ?></strong>
       
   122 		<ul>
       
   123 		<li><?php _e('Arrow: move by 10px'); ?></li>
       
   124 		<li><?php _e('Shift + arrow: move by 1px'); ?></li>
       
   125 		<li><?php _e('Ctrl + arrow: resize by 10px'); ?></li>
       
   126 		<li><?php _e('Ctrl + Shift + arrow: resize by 1px'); ?></li>
       
   127 		<li><?php _e('Shift + drag: lock aspect ratio'); ?></li>
       
   128 		</ul>
       
   129 
   121 
   130 		<p><strong><?php _e('Crop Aspect Ratio'); ?></strong><br />
   122 		<p><strong><?php _e('Crop Aspect Ratio'); ?></strong><br />
   131 		<?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>
   123 		<?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>
   132 
   124 
   133 		<p><strong><?php _e('Crop Selection'); ?></strong><br />
   125 		<p><strong><?php _e('Crop Selection'); ?></strong><br />
   189 	<?php } ?>
   181 	<?php } ?>
   190 
   182 
   191 	</td></tr>
   183 	</td></tr>
   192 	</tbody></table>
   184 	</tbody></table>
   193 	<div class="imgedit-wait" id="imgedit-wait-<?php echo $post_id; ?>"></div>
   185 	<div class="imgedit-wait" id="imgedit-wait-<?php echo $post_id; ?>"></div>
   194 	<script type="text/javascript">imageEdit.init(<?php echo $post_id; ?>);</script>
   186 	<script type="text/javascript">jQuery( function() { imageEdit.init(<?php echo $post_id; ?>); });</script>
   195 	<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>
   187 	<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>
   196 	</div>
   188 	</div>
   197 <?php
   189 <?php
   198 }
   190 }
   199 
   191 
   200 function wp_stream_image($image, $mime_type, $post_id) {
   192 /**
   201 	$image = apply_filters('image_save_pre', $image, $post_id);
   193  * Streams image in WP_Image_Editor to browser.
   202 
   194  * Provided for backcompat reasons
   203 	switch ( $mime_type ) {
   195  *
   204 		case 'image/jpeg':
   196  * @param WP_Image_Editor $image
   205 			header('Content-Type: image/jpeg');
   197  * @param string $mime_type
   206 			return imagejpeg($image, null, 90);
   198  * @param int $post_id
   207 		case 'image/png':
   199  * @return boolean
   208 			header('Content-Type: image/png');
   200  */
   209 			return imagepng($image);
   201 function wp_stream_image( $image, $mime_type, $post_id ) {
   210 		case 'image/gif':
   202 	if ( $image instanceof WP_Image_Editor ) {
   211 			header('Content-Type: image/gif');
   203 		$image = apply_filters('image_editor_save_pre', $image, $post_id);
   212 			return imagegif($image);
   204 
   213 		default:
   205 		if ( is_wp_error( $image->stream( $mime_type ) ) )
   214 			return false;
   206 			return false;
   215 	}
   207 
   216 }
   208 		return true;
   217 
   209 	} else {
   218 function wp_save_image_file($filename, $image, $mime_type, $post_id) {
   210 		_deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) );
   219 	$image = apply_filters('image_save_pre', $image, $post_id);
   211 
   220 	$saved = apply_filters('wp_save_image_file', null, $filename, $image, $mime_type, $post_id);
   212 		$image = apply_filters('image_save_pre', $image, $post_id);
   221 	if ( null !== $saved )
   213 
   222 		return $saved;
   214 		switch ( $mime_type ) {
   223 
   215 			case 'image/jpeg':
   224 	switch ( $mime_type ) {
   216 				header( 'Content-Type: image/jpeg' );
   225 		case 'image/jpeg':
   217 				return imagejpeg( $image, null, 90 );
   226 			return imagejpeg( $image, $filename, apply_filters( 'jpeg_quality', 90, 'edit_image' ) );
   218 			case 'image/png':
   227 		case 'image/png':
   219 				header( 'Content-Type: image/png' );
   228 			return imagepng($image, $filename);
   220 				return imagepng( $image );
   229 		case 'image/gif':
   221 			case 'image/gif':
   230 			return imagegif($image, $filename);
   222 				header( 'Content-Type: image/gif' );
   231 		default:
   223 				return imagegif( $image );
   232 			return false;
   224 			default:
       
   225 				return false;
       
   226 		}
       
   227 	}
       
   228 }
       
   229 
       
   230 /**
       
   231  * Saves Image to File
       
   232  *
       
   233  * @param string $filename
       
   234  * @param WP_Image_Editor $image
       
   235  * @param string $mime_type
       
   236  * @param int $post_id
       
   237  * @return boolean
       
   238  */
       
   239 function wp_save_image_file( $filename, $image, $mime_type, $post_id ) {
       
   240 	if ( $image instanceof WP_Image_Editor ) {
       
   241 		$image = apply_filters('image_editor_save_pre', $image, $post_id);
       
   242 		$saved = apply_filters('wp_save_image_editor_file', null, $filename, $image, $mime_type, $post_id);
       
   243 
       
   244 		if ( null !== $saved )
       
   245 			return $saved;
       
   246 
       
   247 		return $image->save( $filename, $mime_type );
       
   248 	} else {
       
   249 		_deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) );
       
   250 
       
   251 		$image = apply_filters('image_save_pre', $image, $post_id);
       
   252 		$saved = apply_filters('wp_save_image_file', null, $filename, $image, $mime_type, $post_id);
       
   253 
       
   254 		if ( null !== $saved )
       
   255 			return $saved;
       
   256 
       
   257 		switch ( $mime_type ) {
       
   258 			case 'image/jpeg':
       
   259 				return imagejpeg( $image, $filename, apply_filters( 'jpeg_quality', 90, 'edit_image' ) );
       
   260 			case 'image/png':
       
   261 				return imagepng( $image, $filename );
       
   262 			case 'image/gif':
       
   263 				return imagegif( $image, $filename );
       
   264 			default:
       
   265 				return false;
       
   266 		}
   233 	}
   267 	}
   234 }
   268 }
   235 
   269 
   236 function _image_get_preview_ratio($w, $h) {
   270 function _image_get_preview_ratio($w, $h) {
   237 	$max = max($w, $h);
   271 	$max = max($w, $h);
   238 	return $max > 400 ? (400 / $max) : 1;
   272 	return $max > 400 ? (400 / $max) : 1;
   239 }
   273 }
   240 
   274 
       
   275 // @TODO: Returns GD resource, but is NOT public
   241 function _rotate_image_resource($img, $angle) {
   276 function _rotate_image_resource($img, $angle) {
       
   277 	_deprecated_function( __FUNCTION__, '3.5', __( 'Use WP_Image_Editor::rotate' ) );
   242 	if ( function_exists('imagerotate') ) {
   278 	if ( function_exists('imagerotate') ) {
   243 		$rotated = imagerotate($img, $angle, 0);
   279 		$rotated = imagerotate($img, $angle, 0);
   244 		if ( is_resource($rotated) ) {
   280 		if ( is_resource($rotated) ) {
   245 			imagedestroy($img);
   281 			imagedestroy($img);
   246 			$img = $rotated;
   282 			$img = $rotated;
   247 		}
   283 		}
   248 	}
   284 	}
   249 	return $img;
   285 	return $img;
   250 }
   286 }
   251 
   287 
       
   288 /**
       
   289  * @TODO: Only used within image_edit_apply_changes
       
   290  *		  and receives/returns GD Resource.
       
   291  *		  Consider removal.
       
   292  *
       
   293  * @param GD_Resource $img
       
   294  * @param boolean $horz
       
   295  * @param boolean $vert
       
   296  * @return GD_Resource
       
   297  */
   252 function _flip_image_resource($img, $horz, $vert) {
   298 function _flip_image_resource($img, $horz, $vert) {
       
   299 	_deprecated_function( __FUNCTION__, '3.5', __( 'Use WP_Image_Editor::flip' ) );
   253 	$w = imagesx($img);
   300 	$w = imagesx($img);
   254 	$h = imagesy($img);
   301 	$h = imagesy($img);
   255 	$dst = wp_imagecreatetruecolor($w, $h);
   302 	$dst = wp_imagecreatetruecolor($w, $h);
   256 	if ( is_resource($dst) ) {
   303 	if ( is_resource($dst) ) {
   257 		$sx = $vert ? ($w - 1) : 0;
   304 		$sx = $vert ? ($w - 1) : 0;
   265 		}
   312 		}
   266 	}
   313 	}
   267 	return $img;
   314 	return $img;
   268 }
   315 }
   269 
   316 
       
   317 /**
       
   318  * @TODO: Only used within image_edit_apply_changes
       
   319  *		  and receives/returns GD Resource.
       
   320  *		  Consider removal.
       
   321  *
       
   322  * @param GD_Resource $img
       
   323  * @param float $x
       
   324  * @param float $y
       
   325  * @param float $w
       
   326  * @param float $h
       
   327  * @return GD_Resource
       
   328  */
   270 function _crop_image_resource($img, $x, $y, $w, $h) {
   329 function _crop_image_resource($img, $x, $y, $w, $h) {
   271 	$dst = wp_imagecreatetruecolor($w, $h);
   330 	$dst = wp_imagecreatetruecolor($w, $h);
   272 	if ( is_resource($dst) ) {
   331 	if ( is_resource($dst) ) {
   273 		if ( imagecopy($dst, $img, 0, 0, $x, $y, $w, $h) ) {
   332 		if ( imagecopy($dst, $img, 0, 0, $x, $y, $w, $h) ) {
   274 			imagedestroy($img);
   333 			imagedestroy($img);
   276 		}
   335 		}
   277 	}
   336 	}
   278 	return $img;
   337 	return $img;
   279 }
   338 }
   280 
   339 
   281 function image_edit_apply_changes($img, $changes) {
   340 /**
       
   341  * Performs group of changes on Editor specified.
       
   342  *
       
   343  * @param WP_Image_Editor $image
       
   344  * @param type $changes
       
   345  * @return WP_Image_Editor
       
   346  */
       
   347 function image_edit_apply_changes( $image, $changes ) {
       
   348 	if ( is_resource( $image ) )
       
   349 		_deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) );
   282 
   350 
   283 	if ( !is_array($changes) )
   351 	if ( !is_array($changes) )
   284 		return $img;
   352 		return $image;
   285 
   353 
   286 	// expand change operations
   354 	// expand change operations
   287 	foreach ( $changes as $key => $obj ) {
   355 	foreach ( $changes as $key => $obj ) {
   288 		if ( isset($obj->r) ) {
   356 		if ( isset($obj->r) ) {
   289 			$obj->type = 'rotate';
   357 			$obj->type = 'rotate';
   324 		$changes = $filtered;
   392 		$changes = $filtered;
   325 		unset($filtered);
   393 		unset($filtered);
   326 	}
   394 	}
   327 
   395 
   328 	// image resource before applying the changes
   396 	// image resource before applying the changes
   329 	$img = apply_filters('image_edit_before_change', $img, $changes);
   397 	if ( $image instanceof WP_Image_Editor )
       
   398 		$image = apply_filters('wp_image_editor_before_change', $image, $changes);
       
   399 	elseif ( is_resource( $image ) )
       
   400 		$image = apply_filters('image_edit_before_change', $image, $changes);
   330 
   401 
   331 	foreach ( $changes as $operation ) {
   402 	foreach ( $changes as $operation ) {
   332 		switch ( $operation->type ) {
   403 		switch ( $operation->type ) {
   333 			case 'rotate':
   404 			case 'rotate':
   334 				if ( $operation->angle != 0 )
   405 				if ( $operation->angle != 0 ) {
   335 					$img = _rotate_image_resource($img, $operation->angle);
   406 					if ( $image instanceof WP_Image_Editor )
       
   407 						$image->rotate( $operation->angle );
       
   408 					else
       
   409 						$image = _rotate_image_resource( $image, $operation->angle );
       
   410 				}
   336 				break;
   411 				break;
   337 			case 'flip':
   412 			case 'flip':
   338 				if ( $operation->axis != 0 )
   413 				if ( $operation->axis != 0 )
   339 					$img = _flip_image_resource($img, ($operation->axis & 1) != 0, ($operation->axis & 2) != 0);
   414 					if ( $image instanceof WP_Image_Editor )
       
   415 						$image->flip( ($operation->axis & 1) != 0, ($operation->axis & 2) != 0 );
       
   416 					else
       
   417 						$image = _flip_image_resource( $image, ( $operation->axis & 1 ) != 0, ( $operation->axis & 2 ) != 0 );
   340 				break;
   418 				break;
   341 			case 'crop':
   419 			case 'crop':
   342 				$sel = $operation->sel;
   420 				$sel = $operation->sel;
   343 				$scale = 1 / _image_get_preview_ratio( imagesx($img), imagesy($img) ); // discard preview scaling
   421 
   344 				$img = _crop_image_resource($img, $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale);
   422 				if ( $image instanceof WP_Image_Editor ) {
       
   423 					$size = $image->get_size();
       
   424 					$w = $size['width'];
       
   425 					$h = $size['height'];
       
   426 
       
   427 					$scale = 1 / _image_get_preview_ratio( $w, $h ); // discard preview scaling
       
   428 					$image->crop( $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale );
       
   429 				} else {
       
   430 					$scale = 1 / _image_get_preview_ratio( imagesx( $image ), imagesy( $image ) ); // discard preview scaling
       
   431 					$image = _crop_image_resource( $image, $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale );
       
   432 				}
   345 				break;
   433 				break;
   346 		}
   434 		}
   347 	}
   435 	}
   348 
   436 
   349 	return $img;
   437 	return $image;
   350 }
   438 }
   351 
   439 
   352 function stream_preview_image($post_id) {
   440 
   353 	$post = get_post($post_id);
   441 /**
       
   442  * Streams image in post to browser, along with enqueued changes
       
   443  * in $_REQUEST['history']
       
   444  *
       
   445  * @param int $post_id
       
   446  * @return boolean
       
   447  */
       
   448 function stream_preview_image( $post_id ) {
       
   449 	$post = get_post( $post_id );
   354 	@ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) );
   450 	@ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) );
   355 	$img = load_image_to_edit( $post_id, $post->post_mime_type, array(400, 400) );
   451 
   356 
   452 	$img = wp_get_image_editor( _load_image_to_edit_path( $post_id ) );
   357 	if ( !is_resource($img) )
   453 
   358 		return false;
   454     if ( is_wp_error( $img ) )
       
   455         return false;
   359 
   456 
   360 	$changes = !empty($_REQUEST['history']) ? json_decode( stripslashes($_REQUEST['history']) ) : null;
   457 	$changes = !empty($_REQUEST['history']) ? json_decode( stripslashes($_REQUEST['history']) ) : null;
   361 	if ( $changes )
   458 	if ( $changes )
   362 		$img = image_edit_apply_changes($img, $changes);
   459 		$img = image_edit_apply_changes( $img, $changes );
   363 
   460 
   364 	// scale the image
   461 	// scale the image
   365 	$w = imagesx($img);
   462 	$size = $img->get_size();
   366 	$h = imagesy($img);
   463 	$w = $size['width'];
   367 	$ratio = _image_get_preview_ratio($w, $h);
   464 	$h = $size['height'];
       
   465 
       
   466 	$ratio = _image_get_preview_ratio( $w, $h );
   368 	$w2 = $w * $ratio;
   467 	$w2 = $w * $ratio;
   369 	$h2 = $h * $ratio;
   468 	$h2 = $h * $ratio;
   370 
   469 
   371 	$preview = wp_imagecreatetruecolor($w2, $h2);
   470 	if ( is_wp_error( $img->resize( $w2, $h2 ) ) )
   372 	imagecopyresampled( $preview, $img, 0, 0, 0, 0, $w2, $h2, $w, $h );
   471 		return false;
   373 	wp_stream_image($preview, $post->post_mime_type, $post_id);
   472 
   374 
   473 	return wp_stream_image( $img, $post->post_mime_type, $post_id );
   375 	imagedestroy($preview);
       
   376 	imagedestroy($img);
       
   377 	return true;
       
   378 }
   474 }
   379 
   475 
   380 function wp_restore_image($post_id) {
   476 function wp_restore_image($post_id) {
   381 	$meta = wp_get_attachment_metadata($post_id);
   477 	$meta = wp_get_attachment_metadata($post_id);
   382 	$file = get_attached_file($post_id);
   478 	$file = get_attached_file($post_id);
   412 		$restored = update_attached_file($post_id, $restored_file);
   508 		$restored = update_attached_file($post_id, $restored_file);
   413 
   509 
   414 		$meta['file'] = _wp_relative_upload_path( $restored_file );
   510 		$meta['file'] = _wp_relative_upload_path( $restored_file );
   415 		$meta['width'] = $data['width'];
   511 		$meta['width'] = $data['width'];
   416 		$meta['height'] = $data['height'];
   512 		$meta['height'] = $data['height'];
   417 		list ( $uwidth, $uheight ) = wp_constrain_dimensions($meta['width'], $meta['height'], 128, 96);
       
   418 		$meta['hwstring_small'] = "height='$uheight' width='$uwidth'";
       
   419 	}
   513 	}
   420 
   514 
   421 	foreach ( $default_sizes as $default_size ) {
   515 	foreach ( $default_sizes as $default_size ) {
   422 		if ( isset($backup_sizes["$default_size-orig"]) ) {
   516 		if ( isset($backup_sizes["$default_size-orig"]) ) {
   423 			$data = $backup_sizes["$default_size-orig"];
   517 			$data = $backup_sizes["$default_size-orig"];
   450 		$msg->msg = __('Image restored successfully.');
   544 		$msg->msg = __('Image restored successfully.');
   451 
   545 
   452 	return $msg;
   546 	return $msg;
   453 }
   547 }
   454 
   548 
   455 function wp_save_image($post_id) {
   549 /**
       
   550  * Saves image to post along with enqueued changes
       
   551  * in $_REQUEST['history']
       
   552  *
       
   553  * @param int $post_id
       
   554  * @return \stdClass
       
   555  */
       
   556 function wp_save_image( $post_id ) {
   456 	$return = new stdClass;
   557 	$return = new stdClass;
   457 	$success = $delete = $scaled = $nocrop = false;
   558 	$success = $delete = $scaled = $nocrop = false;
   458 	$post = get_post($post_id);
   559 	$post = get_post( $post_id );
   459 	@ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) );
   560 
   460 	$img = load_image_to_edit($post_id, $post->post_mime_type);
   561 	$img = wp_get_image_editor( _load_image_to_edit_path( $post_id, 'full' ) );
   461 
   562 	if ( is_wp_error( $img ) ) {
   462 	if ( !is_resource($img) ) {
       
   463 		$return->error = esc_js( __('Unable to create new image.') );
   563 		$return->error = esc_js( __('Unable to create new image.') );
   464 		return $return;
   564 		return $return;
   465 	}
   565 	}
   466 
   566 
   467 	$fwidth = !empty($_REQUEST['fwidth']) ? intval($_REQUEST['fwidth']) : 0;
   567 	$fwidth = !empty($_REQUEST['fwidth']) ? intval($_REQUEST['fwidth']) : 0;
   468 	$fheight = !empty($_REQUEST['fheight']) ? intval($_REQUEST['fheight']) : 0;
   568 	$fheight = !empty($_REQUEST['fheight']) ? intval($_REQUEST['fheight']) : 0;
   469 	$target = !empty($_REQUEST['target']) ? preg_replace('/[^a-z0-9_-]+/i', '', $_REQUEST['target']) : '';
   569 	$target = !empty($_REQUEST['target']) ? preg_replace('/[^a-z0-9_-]+/i', '', $_REQUEST['target']) : '';
   470 	$scale = !empty($_REQUEST['do']) && 'scale' == $_REQUEST['do'];
   570 	$scale = !empty($_REQUEST['do']) && 'scale' == $_REQUEST['do'];
   471 
   571 
   472 	if ( $scale && $fwidth > 0 && $fheight > 0 ) {
   572 	if ( $scale && $fwidth > 0 && $fheight > 0 ) {
   473 		$sX = imagesx($img);
   573 		$size = $img->get_size();
   474 		$sY = imagesy($img);
   574 		$sX = $size['width'];
       
   575 		$sY = $size['height'];
   475 
   576 
   476 		// check if it has roughly the same w / h ratio
   577 		// check if it has roughly the same w / h ratio
   477 		$diff = round($sX / $sY, 2) - round($fwidth / $fheight, 2);
   578 		$diff = round($sX / $sY, 2) - round($fwidth / $fheight, 2);
   478 		if ( -0.1 < $diff && $diff < 0.1 ) {
   579 		if ( -0.1 < $diff && $diff < 0.1 ) {
   479 			// scale the full size image
   580 			// scale the full size image
   480 			$dst = wp_imagecreatetruecolor($fwidth, $fheight);
   581 			if ( $img->resize( $fwidth, $fheight ) )
   481 			if ( imagecopyresampled( $dst, $img, 0, 0, 0, 0, $fwidth, $fheight, $sX, $sY ) ) {
       
   482 				imagedestroy($img);
       
   483 				$img = $dst;
       
   484 				$scaled = true;
   582 				$scaled = true;
   485 			}
       
   486 		}
   583 		}
   487 
   584 
   488 		if ( !$scaled ) {
   585 		if ( !$scaled ) {
   489 			$return->error = esc_js( __('Error while saving the scaled image. Please reload the page and try again.') );
   586 			$return->error = esc_js( __('Error while saving the scaled image. Please reload the page and try again.') );
   490 			return $return;
   587 			return $return;
   551 		}
   648 		}
   552 
   649 
   553 		if ( $tag )
   650 		if ( $tag )
   554 			$backup_sizes[$tag] = array('width' => $meta['width'], 'height' => $meta['height'], 'file' => $path_parts['basename']);
   651 			$backup_sizes[$tag] = array('width' => $meta['width'], 'height' => $meta['height'], 'file' => $path_parts['basename']);
   555 
   652 
   556 		$success = update_attached_file($post_id, $new_path);
   653 		$success = update_attached_file( $post_id, $new_path );
   557 
   654 
   558 		$meta['file'] = _wp_relative_upload_path($new_path);
   655 		$meta['file'] = _wp_relative_upload_path( $new_path );
   559 		$meta['width'] = imagesx($img);
   656 
   560 		$meta['height'] = imagesy($img);
   657 		$size = $img->get_size();
   561 
   658 		$meta['width'] = $size['width'];
   562 		list ( $uwidth, $uheight ) = wp_constrain_dimensions($meta['width'], $meta['height'], 128, 96);
   659 		$meta['height'] = $size['height'];
   563 		$meta['hwstring_small'] = "height='$uheight' width='$uwidth'";
       
   564 
   660 
   565 		if ( $success && ('nothumb' == $target || 'all' == $target) ) {
   661 		if ( $success && ('nothumb' == $target || 'all' == $target) ) {
   566 			$sizes = get_intermediate_image_sizes();
   662 			$sizes = get_intermediate_image_sizes();
   567 			if ( 'nothumb' == $target )
   663 			if ( 'nothumb' == $target )
   568 				$sizes = array_diff( $sizes, array('thumbnail') );
   664 				$sizes = array_diff( $sizes, array('thumbnail') );
   573 	} elseif ( 'thumbnail' == $target ) {
   669 	} elseif ( 'thumbnail' == $target ) {
   574 		$sizes = array( 'thumbnail' );
   670 		$sizes = array( 'thumbnail' );
   575 		$success = $delete = $nocrop = true;
   671 		$success = $delete = $nocrop = true;
   576 	}
   672 	}
   577 
   673 
   578 	if ( isset($sizes) ) {
   674 	if ( isset( $sizes ) ) {
       
   675 		$_sizes = array();
       
   676 
   579 		foreach ( $sizes as $size ) {
   677 		foreach ( $sizes as $size ) {
   580 			$tag = false;
   678 			$tag = false;
   581 			if ( isset($meta['sizes'][$size]) ) {
   679 			if ( isset( $meta['sizes'][$size] ) ) {
   582 				if ( isset($backup_sizes["$size-orig"]) ) {
   680 				if ( isset($backup_sizes["$size-orig"]) ) {
   583 					if ( ( !defined('IMAGE_EDIT_OVERWRITE') || !IMAGE_EDIT_OVERWRITE ) && $backup_sizes["$size-orig"]['file'] != $meta['sizes'][$size]['file'] )
   681 					if ( ( !defined('IMAGE_EDIT_OVERWRITE') || !IMAGE_EDIT_OVERWRITE ) && $backup_sizes["$size-orig"]['file'] != $meta['sizes'][$size]['file'] )
   584 						$tag = "$size-$suffix";
   682 						$tag = "$size-$suffix";
   585 				} else {
   683 				} else {
   586 					$tag = "$size-orig";
   684 					$tag = "$size-orig";
   589 				if ( $tag )
   687 				if ( $tag )
   590 					$backup_sizes[$tag] = $meta['sizes'][$size];
   688 					$backup_sizes[$tag] = $meta['sizes'][$size];
   591 			}
   689 			}
   592 
   690 
   593 			$crop = $nocrop ? false : get_option("{$size}_crop");
   691 			$crop = $nocrop ? false : get_option("{$size}_crop");
   594 			$resized = image_make_intermediate_size($new_path, get_option("{$size}_size_w"), get_option("{$size}_size_h"), $crop );
   692 			$_sizes[ $size ] = array( 'width' => get_option("{$size}_size_w"), 'height' => get_option("{$size}_size_h"), 'crop' => $crop );
   595 
   693 		}
   596 			if ( $resized )
   694 
   597 				$meta['sizes'][$size] = $resized;
   695 		$meta['sizes'] = $img->multi_resize( $_sizes );
   598 			else
   696 	}
   599 				unset($meta['sizes'][$size]);
   697 
   600 		}
   698 	unset( $img );
   601 	}
       
   602 
   699 
   603 	if ( $success ) {
   700 	if ( $success ) {
   604 		wp_update_attachment_metadata($post_id, $meta);
   701 		wp_update_attachment_metadata( $post_id, $meta );
   605 		update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes);
   702 		update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes);
   606 
   703 
   607 		if ( $target == 'thumbnail' || $target == 'all' || $target == 'full' ) {
   704 		if ( $target == 'thumbnail' || $target == 'all' || $target == 'full' ) {
   608 			$file_url = wp_get_attachment_url($post_id);
   705 			// Check if it's an image edit from attachment edit screen
   609 			if ( $thumb = $meta['sizes']['thumbnail'] )
   706 			if ( ! empty( $_REQUEST['context'] ) && 'edit-attachment' == $_REQUEST['context'] ) {
   610 				$return->thumbnail = path_join( dirname($file_url), $thumb['file'] );
   707 				$thumb_url = wp_get_attachment_image_src( $post_id, array( 900, 600 ), true );
   611 			else
   708 				$return->thumbnail = $thumb_url[0];
   612 				$return->thumbnail = "$file_url?w=128&h=128";
   709 			} else {
       
   710 				$file_url = wp_get_attachment_url($post_id);
       
   711 				if ( $thumb = $meta['sizes']['thumbnail'] )
       
   712 					$return->thumbnail = path_join( dirname($file_url), $thumb['file'] );
       
   713 				else
       
   714 					$return->thumbnail = "$file_url?w=128&h=128";
       
   715 			}
   613 		}
   716 		}
   614 	} else {
   717 	} else {
   615 		$delete = true;
   718 		$delete = true;
   616 	}
   719 	}
   617 
   720 
   618 	if ( $delete ) {
   721 	if ( $delete ) {
   619 		$delpath = apply_filters('wp_delete_file', $new_path);
   722 		$delpath = apply_filters('wp_delete_file', $new_path);
   620 		@unlink($delpath);
   723 		@unlink( $delpath );
   621 	}
   724 	}
   622 
       
   623 	imagedestroy($img);
       
   624 
   725 
   625 	$return->msg = esc_js( __('Image saved') );
   726 	$return->msg = esc_js( __('Image saved') );
   626 	return $return;
   727 	return $return;
   627 }
   728 }