~canonical-sysadmins/wordpress/3.9.x

« back to all changes in this revision

Viewing changes to wp-admin/includes/image-edit.php

  • Committer: Chris Jones
  • Date: 2010-01-19 13:17:33 UTC
  • Revision ID: cmsj@tenshu.net-20100119131733-rf31jv9k1v0xzo2h
[CJ] Import wordpress 2.9.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/**
 
3
 * WordPress Image Editor
 
4
 *
 
5
 * @package WordPress
 
6
 * @subpackage Administration
 
7
 */
 
8
 
 
9
function wp_image_editor($post_id, $msg = false) {
 
10
        $nonce = wp_create_nonce("image_editor-$post_id");
 
11
        $meta = wp_get_attachment_metadata($post_id);
 
12
        $thumb = image_get_intermediate_size($post_id, 'thumbnail');
 
13
        $sub_sizes = isset($meta['sizes']) && is_array($meta['sizes']);
 
14
        $note = '';
 
15
 
 
16
        if ( is_array($meta) && isset($meta['width']) )
 
17
                $big = max( $meta['width'], $meta['height'] );
 
18
        else
 
19
                die( __('Image data does not exist. Please re-upload the image.') );
 
20
 
 
21
        $sizer = $big > 400 ? 400 / $big : 1;
 
22
 
 
23
        $backup_sizes = get_post_meta( $post_id, '_wp_attachment_backup_sizes', true );
 
24
        $can_restore = !empty($backup_sizes) && isset($backup_sizes['full-orig'])
 
25
                && $backup_sizes['full-orig']['file'] != basename($meta['file']);
 
26
 
 
27
        if ( $msg ) {
 
28
                if ( isset($msg->error) )
 
29
                        $note = "<div class='error'><p>$msg->error</p></div>";
 
30
                elseif ( isset($msg->msg) )
 
31
                        $note = "<div class='updated'><p>$msg->msg</p></div>";
 
32
        }
 
33
 
 
34
        ?>
 
35
        <div class="imgedit-wrap">
 
36
        <?php echo $note; ?>
 
37
        <table id="imgedit-panel-<?php echo $post_id; ?>"><tbody>
 
38
        <tr><td>
 
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
 
41
 
 
42
        // On some setups GD library does not provide imagerotate() - Ticket #11536   
 
43
        if ( function_exists('imagerotate') ) { ?>
 
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>
 
46
<?php } else {
 
47
                $note_gdlib = esc_attr__('Image rotation is not supported by your web host (function imagerotate() is missing)');
 
48
?>
 
49
            <div class="imgedit-rleft disabled"  title="<?php echo $note_gdlib; ?>"></div>
 
50
            <div class="imgedit-rright disabled" title="<?php echo $note_gdlib; ?>"></div>
 
51
<?php } ?>
 
52
 
 
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>
 
55
 
 
56
                <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>
 
57
                <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>
 
58
                <br class="clear" />
 
59
        </div>
 
60
 
 
61
        <input type="hidden" id="imgedit-sizer-<?php echo $post_id; ?>" value="<?php echo $sizer; ?>" />
 
62
        <input type="hidden" id="imgedit-minthumb-<?php echo $post_id; ?>" value="<?php echo ( get_option('thumbnail_size_w') . ':' . get_option('thumbnail_size_h') ); ?>" />
 
63
        <input type="hidden" id="imgedit-history-<?php echo $post_id; ?>" value="" />
 
64
        <input type="hidden" id="imgedit-undone-<?php echo $post_id; ?>" value="0" />
 
65
        <input type="hidden" id="imgedit-selection-<?php echo $post_id; ?>" value="" />
 
66
        <input type="hidden" id="imgedit-x-<?php echo $post_id; ?>" value="<?php echo $meta['width']; ?>" />
 
67
        <input type="hidden" id="imgedit-y-<?php echo $post_id; ?>" value="<?php echo $meta['height']; ?>" />
 
68
 
 
69
        <div id="imgedit-crop-<?php echo $post_id; ?>" class="imgedit-crop-wrap">
 
70
        <img id="image-preview-<?php echo $post_id; ?>" onload="imageEdit.imgLoaded('<?php echo $post_id; ?>')" src="<?php echo admin_url('admin-ajax.php'); ?>?action=imgedit-preview&amp;_ajax_nonce=<?php echo $nonce; ?>&amp;postid=<?php echo $post_id; ?>&amp;rand=<?php echo rand(1, 99999); ?>" />
 
71
        </div>
 
72
 
 
73
        <div class="imgedit-submit">
 
74
                <input type="button" onclick="imageEdit.close(<?php echo $post_id; ?>, 1)" class="button" value="<?php esc_attr_e( 'Cancel' ); ?>" />
 
75
                <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' ); ?>" />
 
76
        </div>
 
77
        </td>
 
78
 
 
79
        <td class="imgedit-settings">
 
80
        <div class="imgedit-group">
 
81
        <div class="imgedit-group-top">
 
82
                <a class="imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);return false;" href="#"><strong><?php _e('Scale Image'); ?></strong></a>
 
83
                <div class="imgedit-help">
 
84
                <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 if you make the image larger it may become fuzzy.'); ?></p>
 
85
                <p><?php printf( __('Original dimensions %s'), $meta['width'] . '&times;' . $meta['height'] ); ?></p>
 
86
                <div class="imgedit-submit">
 
87
                <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 $meta['width']; ?>" />&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 $meta['height']; ?>" />
 
88
                <span class="imgedit-scale-warn" id="imgedit-scale-warn-<?php echo $post_id; ?>">!</span></span>
 
89
                <input type="button" onclick="imageEdit.action(<?php echo "$post_id, '$nonce'"; ?>, 'scale')" class="button-primary" value="<?php esc_attr_e( 'Scale' ); ?>" />
 
90
                </div>
 
91
                </div>
 
92
        </div>
 
93
 
 
94
<?php if ( $can_restore ) { ?>
 
95
 
 
96
        <div class="imgedit-group-top">
 
97
                <a class="imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);return false;" href="#"><strong><?php _e('Restore Original Image'); ?></strong></a>
 
98
                <div class="imgedit-help">
 
99
                <p><?php _e('Discard any changes and restore the original image.'); 
 
100
 
 
101
                if ( !defined('IMAGE_EDIT_OVERWRITE') || !IMAGE_EDIT_OVERWRITE )
 
102
                        _e(' Previously edited copies of the image will not be deleted.');
 
103
 
 
104
                ?></p>
 
105
                <div class="imgedit-submit">
 
106
                <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; ?> />
 
107
                </div>
 
108
                </div>
 
109
        </div>
 
110
 
 
111
<?php } ?>
 
112
 
 
113
        </div>
 
114
 
 
115
        <div class="imgedit-group">
 
116
        <div class="imgedit-group-top">
 
117
                <strong><?php _e('Image Crop'); ?></strong>
 
118
                <a class="imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);return false;" href="#"><?php _e('(help)'); ?></a>
 
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>
 
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
 
 
130
                <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>
 
132
 
 
133
                <p><strong><?php _e('Crop Selection'); ?></strong><br />
 
134
                <?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>
 
135
                </div>
 
136
        </div>
 
137
 
 
138
        <p>
 
139
                <?php _e('Aspect ratio:'); ?>
 
140
                <span  class="nowrap">
 
141
                <input type="text" id="imgedit-crop-width-<?php echo $post_id; ?>" onkeyup="imageEdit.setRatioSelection(<?php echo $post_id; ?>, 0, this)" style="width:3em;" />
 
142
                :
 
143
                <input type="text" id="imgedit-crop-height-<?php echo $post_id; ?>" onkeyup="imageEdit.setRatioSelection(<?php echo $post_id; ?>, 1, this)" style="width:3em;" />
 
144
                </span>
 
145
        </p>
 
146
 
 
147
        <p id="imgedit-crop-sel-<?php echo $post_id; ?>">
 
148
                <?php _e('Selection:'); ?>
 
149
                <span  class="nowrap">
 
150
                <input type="text" id="imgedit-sel-width-<?php echo $post_id; ?>" onkeyup="imageEdit.setNumSelection(<?php echo $post_id; ?>)" style="width:4em;" />
 
151
                :
 
152
                <input type="text" id="imgedit-sel-height-<?php echo $post_id; ?>" onkeyup="imageEdit.setNumSelection(<?php echo $post_id; ?>)" style="width:4em;" />
 
153
                </span>
 
154
        </p>
 
155
        </div>
 
156
 
 
157
        <?php if ( $thumb && $sub_sizes ) {
 
158
                $thumb_img = wp_constrain_dimensions( $thumb['width'], $thumb['height'], 160, 120 );
 
159
        ?>
 
160
 
 
161
        <div class="imgedit-group imgedit-applyto">
 
162
        <div class="imgedit-group-top">
 
163
                <strong><?php _e('Thumbnail Settings'); ?></strong>
 
164
                <a class="imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);return false;" href="#"><?php _e('(help)'); ?></a>
 
165
                <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>
 
166
        </div>
 
167
 
 
168
        <p>
 
169
                <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'); ?>
 
170
        </p>
 
171
 
 
172
        <p id="imgedit-save-target-<?php echo $post_id; ?>">
 
173
                <strong><?php _e('Apply changes to:'); ?></strong><br />
 
174
 
 
175
                <label class="imgedit-label">
 
176
                <input type="radio" name="imgedit-target-<?php echo $post_id; ?>" value="all" checked="checked" />
 
177
                <?php _e('All image sizes'); ?></label>
 
178
 
 
179
                <label class="imgedit-label">
 
180
                <input type="radio" name="imgedit-target-<?php echo $post_id; ?>" value="thumbnail" />
 
181
                <?php _e('Thumbnail'); ?></label>
 
182
 
 
183
                <label class="imgedit-label">
 
184
                <input type="radio" name="imgedit-target-<?php echo $post_id; ?>" value="nothumb" />
 
185
                <?php _e('All sizes except thumbnail'); ?></label>
 
186
        </p>
 
187
        </div>
 
188
 
 
189
        <?php } ?>
 
190
 
 
191
        </td></tr>
 
192
        </tbody></table>
 
193
        <div class="imgedit-wait" id="imgedit-wait-<?php echo $post_id; ?>"></div>
 
194
        <script type="text/javascript">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>
 
196
        </div>
 
197
<?php
 
198
}
 
199
 
 
200
function load_image_to_edit($post_id, $mime_type, $size = 'full') {
 
201
        $filepath = get_attached_file($post_id);
 
202
 
 
203
        if ( $filepath && file_exists($filepath) ) {
 
204
                if ( 'full' != $size && ( $data = image_get_intermediate_size($post_id, $size) ) )
 
205
                        $filepath = path_join( dirname($filepath), $data['file'] );
 
206
        } elseif ( WP_Http_Fopen::test() ) {
 
207
                $filepath = wp_get_attachment_url($post_id);
 
208
        }
 
209
 
 
210
        $filepath = apply_filters('load_image_to_edit_path', $filepath, $post_id, $size);
 
211
        if ( empty($filepath) )
 
212
                return false;
 
213
 
 
214
        switch ( $mime_type ) {
 
215
                case 'image/jpeg':
 
216
                        $image = imagecreatefromjpeg($filepath);
 
217
                        break;
 
218
                case 'image/png':
 
219
                        $image = imagecreatefrompng($filepath);
 
220
                        break;
 
221
                case 'image/gif':
 
222
                        $image = imagecreatefromgif($filepath);
 
223
                        break;
 
224
                default:
 
225
                        $image = false;
 
226
                        break;
 
227
        }
 
228
        if ( is_resource($image) ) {
 
229
                $image = apply_filters('load_image_to_edit', $image, $post_id, $size);
 
230
                if ( function_exists('imagealphablending') && function_exists('imagesavealpha') ) {
 
231
                        imagealphablending($image, false);
 
232
                        imagesavealpha($image, true);
 
233
                }
 
234
        }
 
235
        return $image;
 
236
}
 
237
 
 
238
function wp_stream_image($image, $mime_type, $post_id) {
 
239
        $image = apply_filters('image_save_pre', $image, $post_id);
 
240
 
 
241
        switch ( $mime_type ) {
 
242
                case 'image/jpeg':
 
243
                        header('Content-Type: image/jpeg');
 
244
                        return imagejpeg($image, null, 90);
 
245
                case 'image/png':
 
246
                        header('Content-Type: image/png');
 
247
                        return imagepng($image);
 
248
                case 'image/gif':
 
249
                        header('Content-Type: image/gif');
 
250
                        return imagegif($image);
 
251
                default:
 
252
                        return false;
 
253
        }
 
254
}
 
255
 
 
256
function wp_save_image_file($filename, $image, $mime_type, $post_id) {
 
257
        $image = apply_filters('image_save_pre', $image, $post_id);
 
258
        $saved = apply_filters('wp_save_image_file', null, $filename, $image, $mime_type, $post_id);
 
259
        if ( null !== $saved )
 
260
                return $saved;
 
261
 
 
262
        switch ( $mime_type ) {
 
263
                case 'image/jpeg':
 
264
                        return imagejpeg( $image, $filename, apply_filters( 'jpeg_quality', 90, 'edit_image' ) );
 
265
                case 'image/png':
 
266
                        return imagepng($image, $filename);
 
267
                case 'image/gif':
 
268
                        return imagegif($image, $filename);
 
269
                default:
 
270
                        return false;
 
271
        }
 
272
}
 
273
 
 
274
function _image_get_preview_ratio($w, $h) {
 
275
        $max = max($w, $h);
 
276
        return $max > 400 ? (400 / $max) : 1;
 
277
}
 
278
 
 
279
function _rotate_image_resource($img, $angle) {
 
280
        if ( function_exists('imagerotate') ) {
 
281
                $rotated = imagerotate($img, $angle, 0);
 
282
                if ( is_resource($rotated) ) {
 
283
                        imagedestroy($img);
 
284
                        $img = $rotated;
 
285
                }
 
286
        }
 
287
        return $img;
 
288
}
 
289
 
 
290
 
 
291
function _flip_image_resource($img, $horz, $vert) {
 
292
        $w = imagesx($img);
 
293
        $h = imagesy($img);
 
294
        $dst = wp_imagecreatetruecolor($w, $h);
 
295
        if ( is_resource($dst) ) {
 
296
                $sx = $vert ? ($w - 1) : 0;
 
297
                $sy = $horz ? ($h - 1) : 0;
 
298
                $sw = $vert ? -$w : $w;
 
299
                $sh = $horz ? -$h : $h;
 
300
 
 
301
                if ( imagecopyresampled($dst, $img, 0, 0, $sx, $sy, $w, $h, $sw, $sh) ) {
 
302
                        imagedestroy($img);
 
303
                        $img = $dst;
 
304
                }
 
305
        }
 
306
        return $img;
 
307
}
 
308
 
 
309
function _crop_image_resource($img, $x, $y, $w, $h) {
 
310
        $dst = wp_imagecreatetruecolor($w, $h);
 
311
        if ( is_resource($dst) ) {
 
312
                if ( imagecopy($dst, $img, 0, 0, $x, $y, $w, $h) ) {
 
313
                        imagedestroy($img);
 
314
                        $img = $dst;
 
315
                }
 
316
        }
 
317
        return $img;
 
318
}
 
319
 
 
320
function image_edit_apply_changes($img, $changes) {
 
321
 
 
322
        if ( !is_array($changes) )
 
323
                return $img;
 
324
 
 
325
        // expand change operations
 
326
        foreach ( $changes as $key => $obj ) {
 
327
                if ( isset($obj->r) ) {
 
328
                        $obj->type = 'rotate';
 
329
                        $obj->angle = $obj->r;
 
330
                        unset($obj->r);
 
331
                } elseif ( isset($obj->f) ) {
 
332
                        $obj->type = 'flip';
 
333
                        $obj->axis = $obj->f;
 
334
                        unset($obj->f);
 
335
                } elseif ( isset($obj->c) ) {
 
336
                        $obj->type = 'crop';
 
337
                        $obj->sel = $obj->c;
 
338
                        unset($obj->c);
 
339
                }
 
340
                $changes[$key] = $obj;
 
341
        }
 
342
 
 
343
        // combine operations
 
344
        if ( count($changes) > 1 ) {
 
345
                $filtered = array($changes[0]);
 
346
                for ( $i = 0, $j = 1; $j < count($changes); $j++ ) {
 
347
                        $combined = false;
 
348
                        if ( $filtered[$i]->type == $changes[$j]->type ) {
 
349
                                switch ( $filtered[$i]->type ) {
 
350
                                        case 'rotate':
 
351
                                                $filtered[$i]->angle += $changes[$j]->angle;
 
352
                                                $combined = true;
 
353
                                                break;
 
354
                                        case 'flip':
 
355
                                                $filtered[$i]->axis ^= $changes[$j]->axis;
 
356
                                                $combined = true;
 
357
                                                break;
 
358
                                }
 
359
                        }
 
360
                        if ( !$combined )
 
361
                                $filtered[++$i] = $changes[$j];
 
362
                }
 
363
                $changes = $filtered;
 
364
                unset($filtered);
 
365
        }
 
366
 
 
367
        // image resource before applying the changes
 
368
        $img = apply_filters('image_edit_before_change', $img, $changes);
 
369
 
 
370
        foreach ( $changes as $operation ) {
 
371
                switch ( $operation->type ) {
 
372
                        case 'rotate':
 
373
                                if ( $operation->angle != 0 )
 
374
                                        $img = _rotate_image_resource($img, $operation->angle);
 
375
                                break;
 
376
                        case 'flip':
 
377
                                if ( $operation->axis != 0 )
 
378
                                        $img = _flip_image_resource($img, ($operation->axis & 1) != 0, ($operation->axis & 2) != 0);
 
379
                                break;
 
380
                        case 'crop':
 
381
                                $sel = $operation->sel;
 
382
                                $scale = 1 / _image_get_preview_ratio( imagesx($img), imagesy($img) ); // discard preview scaling
 
383
                                $img = _crop_image_resource($img, $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale);
 
384
                                break;
 
385
                }
 
386
        }
 
387
 
 
388
        return $img;
 
389
}
 
390
 
 
391
function stream_preview_image($post_id) {
 
392
        $post = get_post($post_id);
 
393
        @ini_set('memory_limit', '256M');
 
394
        $img = load_image_to_edit( $post_id, $post->post_mime_type, array(400, 400) );
 
395
 
 
396
        if ( !is_resource($img) )
 
397
                return false;
 
398
 
 
399
        $changes = !empty($_REQUEST['history']) ? json_decode( stripslashes($_REQUEST['history']) ) : null;
 
400
        if ( $changes )
 
401
                $img = image_edit_apply_changes($img, $changes);
 
402
 
 
403
        // scale the image
 
404
        $w = imagesx($img);
 
405
        $h = imagesy($img);
 
406
        $ratio = _image_get_preview_ratio($w, $h);
 
407
        $w2 = $w * $ratio;
 
408
        $h2 = $h * $ratio;
 
409
 
 
410
        $preview = wp_imagecreatetruecolor($w2, $h2);
 
411
        imagecopyresampled( $preview, $img, 0, 0, 0, 0, $w2, $h2, $w, $h );
 
412
        wp_stream_image($preview, $post->post_mime_type, $post_id);
 
413
 
 
414
        imagedestroy($preview);
 
415
        imagedestroy($img);
 
416
        return true;
 
417
}
 
418
 
 
419
function wp_restore_image($post_id) {
 
420
        $meta = wp_get_attachment_metadata($post_id);
 
421
        $file = get_attached_file($post_id);
 
422
        $backup_sizes = get_post_meta( $post_id, '_wp_attachment_backup_sizes', true );
 
423
        $restored = false;
 
424
        $msg = '';
 
425
 
 
426
        if ( !is_array($backup_sizes) ) {
 
427
                $msg->error = __('Cannot load image metadata.');
 
428
                return $msg;
 
429
        }
 
430
 
 
431
        $parts = pathinfo($file);
 
432
        $suffix = time() . rand(100, 999);
 
433
        $default_sizes = apply_filters( 'intermediate_image_sizes', array('large', 'medium', 'thumbnail') );
 
434
 
 
435
        if ( isset($backup_sizes['full-orig']) && is_array($backup_sizes['full-orig']) ) {
 
436
                $data = $backup_sizes['full-orig'];
 
437
 
 
438
                if ( $parts['basename'] != $data['file'] ) {
 
439
                        if ( defined('IMAGE_EDIT_OVERWRITE') && IMAGE_EDIT_OVERWRITE ) {
 
440
                                // delete only if it's edited image
 
441
                                if ( preg_match('/-e[0-9]{13}\./', $parts['basename']) ) {
 
442
                                        $delpath = apply_filters('wp_delete_file', $file);
 
443
                                        @unlink($delpath);
 
444
                                }
 
445
                        } else {
 
446
                                $backup_sizes["full-$suffix"] = array('width' => $meta['width'], 'height' => $meta['height'], 'file' => $parts['basename']);
 
447
                        }
 
448
                }
 
449
 
 
450
                $restored_file = path_join($parts['dirname'], $data['file']);
 
451
                $restored = update_attached_file($post_id, $restored_file);
 
452
 
 
453
                $meta['file'] = _wp_relative_upload_path( $restored_file );
 
454
                $meta['width'] = $data['width'];
 
455
                $meta['height'] = $data['height'];
 
456
                list ( $uwidth, $uheight ) = wp_shrink_dimensions($meta['width'], $meta['height']);
 
457
                $meta['hwstring_small'] = "height='$uheight' width='$uwidth'";
 
458
        }
 
459
 
 
460
        foreach ( $default_sizes as $default_size ) {
 
461
                if ( isset($backup_sizes["$default_size-orig"]) ) {
 
462
                        $data = $backup_sizes["$default_size-orig"];
 
463
                        if ( isset($meta['sizes'][$default_size]) && $meta['sizes'][$default_size]['file'] != $data['file'] ) {
 
464
                                if ( defined('IMAGE_EDIT_OVERWRITE') && IMAGE_EDIT_OVERWRITE ) {
 
465
                                        // delete only if it's edited image
 
466
                                        if ( preg_match('/-e[0-9]{13}-/', $meta['sizes'][$default_size]['file']) ) {
 
467
                                                $delpath = apply_filters( 'wp_delete_file', path_join($parts['dirname'], $meta['sizes'][$default_size]['file']) );
 
468
                                                @unlink($delpath);
 
469
                                        }
 
470
                                } else {
 
471
                                        $backup_sizes["$default_size-{$suffix}"] = $meta['sizes'][$default_size];
 
472
                                }
 
473
                        }
 
474
 
 
475
                        $meta['sizes'][$default_size] = $data;
 
476
                } else {
 
477
                        unset($meta['sizes'][$default_size]);
 
478
                }
 
479
        }
 
480
 
 
481
        if ( !wp_update_attachment_metadata($post_id, $meta) || !update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes) ) {
 
482
                $msg->error = __('Cannot save image metadata.');
 
483
                return $msg;
 
484
        }
 
485
 
 
486
        if ( !$restored )
 
487
                $msg->error = __('Image metadata is inconsistent.');
 
488
        else
 
489
                $msg->msg = __('Image restored successfully.');
 
490
 
 
491
        return $msg;
 
492
}
 
493
 
 
494
function wp_save_image($post_id) {
 
495
        $return = '';
 
496
        $success = $delete = $scaled = $nocrop = false;
 
497
        $post = get_post($post_id);
 
498
        @ini_set('memory_limit', '256M');
 
499
        $img = load_image_to_edit($post_id, $post->post_mime_type);
 
500
 
 
501
        if ( !is_resource($img) ) {
 
502
                $return->error = esc_js( __('Unable to create new image.') );
 
503
                return $return;
 
504
        }
 
505
 
 
506
        $fwidth = !empty($_REQUEST['fwidth']) ? intval($_REQUEST['fwidth']) : 0;
 
507
        $fheight = !empty($_REQUEST['fheight']) ? intval($_REQUEST['fheight']) : 0;
 
508
        $target = !empty($_REQUEST['target']) ? preg_replace('/[^a-z0-9_-]+/i', '', $_REQUEST['target']) : '';
 
509
        $scale = !empty($_REQUEST['do']) && 'scale' == $_REQUEST['do'];
 
510
 
 
511
        if ( $scale && $fwidth > 0 && $fheight > 0 ) {
 
512
                $sX = imagesx($img);
 
513
                $sY = imagesy($img);
 
514
 
 
515
                // check if it has roughly the same w / h ratio
 
516
                $diff = round($sX / $sY, 2) - round($fwidth / $fheight, 2);
 
517
                if ( -0.1 < $diff && $diff < 0.1 ) {
 
518
                        // scale the full size image
 
519
                        $dst = wp_imagecreatetruecolor($fwidth, $fheight);
 
520
                        if ( imagecopyresampled( $dst, $img, 0, 0, 0, 0, $fwidth, $fheight, $sX, $sY ) ) {
 
521
                                imagedestroy($img);
 
522
                                $img = $dst;
 
523
                                $scaled = true;
 
524
                        }
 
525
                }
 
526
 
 
527
                if ( !$scaled ) {
 
528
                        $return->error = esc_js( __('Error while saving the scaled image. Please reload the page and try again.') );
 
529
                        return $return;
 
530
                }
 
531
        } elseif ( !empty($_REQUEST['history']) ) {
 
532
                $changes = json_decode( stripslashes($_REQUEST['history']) );
 
533
                if ( $changes )
 
534
                        $img = image_edit_apply_changes($img, $changes);
 
535
        } else {
 
536
                $return->error = esc_js( __('Nothing to save, the image has not changed.') );
 
537
                return $return;
 
538
        }
 
539
 
 
540
        $meta = wp_get_attachment_metadata($post_id);
 
541
        $backup_sizes = get_post_meta( $post->ID, '_wp_attachment_backup_sizes', true );
 
542
 
 
543
        if ( !is_array($meta) ) {
 
544
                $return->error = esc_js( __('Image data does not exist. Please re-upload the image.') );
 
545
                return $return;
 
546
        }
 
547
 
 
548
        if ( !is_array($backup_sizes) )
 
549
                $backup_sizes = array();
 
550
 
 
551
        // generate new filename
 
552
        $path = get_attached_file($post_id);
 
553
        $path_parts = pathinfo52( $path );
 
554
        $filename = $path_parts['filename'];
 
555
        $suffix = time() . rand(100, 999);
 
556
 
 
557
        if ( defined('IMAGE_EDIT_OVERWRITE') && IMAGE_EDIT_OVERWRITE &&
 
558
                isset($backup_sizes['full-orig']) && $backup_sizes['full-orig']['file'] != $path_parts['basename'] ) {
 
559
 
 
560
                if ( 'thumbnail' == $target )
 
561
                        $new_path = "{$path_parts['dirname']}/{$filename}-temp.{$path_parts['extension']}";
 
562
                else
 
563
                        $new_path = $path;
 
564
        } else {
 
565
                while( true ) {
 
566
                        $filename = preg_replace( '/-e([0-9]+)$/', '', $filename );
 
567
                        $filename .= "-e{$suffix}";
 
568
                        $new_filename = "{$filename}.{$path_parts['extension']}";
 
569
                        $new_path = "{$path_parts['dirname']}/$new_filename";
 
570
                        if ( file_exists($new_path) )
 
571
                                $suffix++;
 
572
                        else
 
573
                                break;
 
574
                }
 
575
        }
 
576
 
 
577
        // save the full-size file, also needed to create sub-sizes
 
578
        if ( !wp_save_image_file($new_path, $img, $post->post_mime_type, $post_id) ) {
 
579
                $return->error = esc_js( __('Unable to save the image.') );
 
580
                return $return;
 
581
        }
 
582
 
 
583
        if ( 'nothumb' == $target || 'all' == $target || 'full' == $target || $scaled ) {
 
584
                $tag = false;
 
585
                if ( isset($backup_sizes['full-orig']) ) {
 
586
                        if ( ( !defined('IMAGE_EDIT_OVERWRITE') || !IMAGE_EDIT_OVERWRITE ) && $backup_sizes['full-orig']['file'] != $path_parts['basename'] )
 
587
                                $tag = "full-$suffix";
 
588
                } else {
 
589
                        $tag = 'full-orig';
 
590
                }
 
591
 
 
592
                if ( $tag )
 
593
                        $backup_sizes[$tag] = array('width' => $meta['width'], 'height' => $meta['height'], 'file' => $path_parts['basename']);
 
594
 
 
595
                $success = update_attached_file($post_id, $new_path);
 
596
 
 
597
                $meta['file'] = _wp_relative_upload_path($new_path);
 
598
                $meta['width'] = imagesx($img);
 
599
                $meta['height'] = imagesy($img);
 
600
 
 
601
                list ( $uwidth, $uheight ) = wp_shrink_dimensions($meta['width'], $meta['height']);
 
602
                $meta['hwstring_small'] = "height='$uheight' width='$uwidth'";
 
603
 
 
604
                if ( $success && ('nothumb' == $target || 'all' == $target) ) {
 
605
                        $sizes = apply_filters( 'intermediate_image_sizes', array('large', 'medium', 'thumbnail') );
 
606
                        if ( 'nothumb' == $target )
 
607
                                $sizes = array_diff( $sizes, array('thumbnail') );
 
608
                }
 
609
 
 
610
                $return->fw = $meta['width'];
 
611
                $return->fh = $meta['height'];
 
612
        } elseif ( 'thumbnail' == $target ) {
 
613
                $sizes = array( 'thumbnail' );
 
614
                $success = $delete = $nocrop = true;
 
615
        }
 
616
 
 
617
        if ( isset($sizes) ) {
 
618
                foreach ( $sizes as $size ) {
 
619
                        $tag = false;
 
620
                        if ( isset($meta['sizes'][$size]) ) {
 
621
                                if ( isset($backup_sizes["$size-orig"]) ) {
 
622
                                        if ( ( !defined('IMAGE_EDIT_OVERWRITE') || !IMAGE_EDIT_OVERWRITE ) && $backup_sizes["$size-orig"]['file'] != $meta['sizes'][$size]['file'] )
 
623
                                                $tag = "$size-$suffix";
 
624
                                } else {
 
625
                                        $tag = "$size-orig";
 
626
                                }
 
627
 
 
628
                                if ( $tag )
 
629
                                        $backup_sizes[$tag] = $meta['sizes'][$size];
 
630
                        }
 
631
 
 
632
                        $crop = $nocrop ? false : get_option("{$size}_crop");
 
633
                        $resized = image_make_intermediate_size($new_path, get_option("{$size}_size_w"), get_option("{$size}_size_h"), $crop );
 
634
 
 
635
                        if ( $resized )
 
636
                                $meta['sizes'][$size] = $resized;
 
637
                        else
 
638
                                unset($meta['sizes'][$size]);
 
639
                }
 
640
        }
 
641
 
 
642
        if ( $success ) {
 
643
                wp_update_attachment_metadata($post_id, $meta);
 
644
                update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes);
 
645
 
 
646
                if ( $target == 'thumbnail' || $target == 'all' || $target == 'full' ) {
 
647
                        $file_url = wp_get_attachment_url($post_id);
 
648
                        if ( $thumb = $meta['sizes']['thumbnail'] )
 
649
                                $return->thumbnail = path_join( dirname($file_url), $thumb['file'] );
 
650
                        else
 
651
                                $return->thumbnail = "$file_url?w=128&h=128";
 
652
                }
 
653
        } else {
 
654
                $delete = true;
 
655
        }
 
656
 
 
657
        if ( $delete ) {
 
658
                $delpath = apply_filters('wp_delete_file', $new_path);
 
659
                @unlink($delpath);
 
660
        }
 
661
 
 
662
        imagedestroy($img);
 
663
 
 
664
        $return->msg = esc_js( __('Image saved') );
 
665
        return $return;
 
666
}
 
667