source: trunk/plugins/ImageManager/Classes/ImageEditor.php @ 937

Last change on this file since 937 was 937, checked in by ray, 12 years ago

#1132 [ExtendedFileManager?] new Version

  • Property svn:keywords set to LastChangedDate LastChangedRevision LastChangedBy HeadURL Id
File size: 12.8 KB
Line 
1<?php
2/**
3 * Image Editor. Editing tools, crop, rotate, scale and save.
4 * @author $Author$
5 * @version $Id$
6 * @package ImageManager
7 */
8
9require_once('../ImageManager/Classes/Transform.php');
10
11/**
12 * Handles the basic image editing capbabilities.
13 * @author $Author$
14 * @version $Id$
15 * @package ImageManager
16 * @subpackage Editor
17 */
18class ImageEditor
19{
20        /**
21         * ImageManager instance.
22         */
23        var $manager;
24
25        /**
26         * user based on IP address
27         */
28        var $_uid;
29
30        /**
31         * tmp file storage time.
32         */
33        var $lapse_time =900; //15 mins
34
35        var $filesaved = 0;
36
37        /**
38         * Create a new ImageEditor instance. Editing requires a
39         * tmp file, which is saved in the current directory where the
40         * image is edited. The tmp file is assigned by md5 hash of the
41         * user IP address. This hashed is used as an ID for cleaning up
42         * the tmp files. In addition, any tmp files older than the
43         * the specified period will be deleted.
44         * @param ImageManager $manager the image manager, we need this
45         * for some file and path handling functions.
46         */
47        function ImageEditor($manager)
48        {
49                $this->manager = $manager;
50                $this->_uid = md5($_SERVER['REMOTE_ADDR']);
51        }
52       
53        /**
54         * Did we save a file?
55         * @return int 1 if the file was saved sucessfully,
56         * 0 no save operation, -1 file save error.
57         */
58        function isFileSaved()
59        {
60                Return $this->filesaved;
61        }
62
63        /**
64         * Process the image, if not action, just display the image.
65         * @return array with image information, empty array if not an image.
66         * <code>array('src'=>'url of the image', 'dimensions'=>'width="xx" height="yy"',
67         * 'file'=>'image file, relative', 'fullpath'=>'full path to the image');</code>
68         */
69        function processImage()
70        {
71                if(isset($_GET['img']))
72                        $relative = rawurldecode($_GET['img']);
73                else
74                        Return array();
75               
76                //$relative = '/Series2004NoteFront.jpg';
77
78                $imgURL = $this->manager->getFileURL($relative);
79                $fullpath = $this->manager->getFullPath($relative);
80               
81                $imgInfo = @getImageSize($fullpath);
82                if(!is_array($imgInfo))
83                        Return array();
84
85                $action = $this->getAction();
86
87                if(!is_null($action))
88                {
89                        $image = $this->processAction($action, $relative, $fullpath);
90                }
91                else
92                {
93                        $image['src'] = $imgURL;
94                        $image['dimensions'] = $imgInfo[3];
95                        $image['file'] = $relative;
96                        $image['fullpath'] = $fullpath;
97                        $image['filesize'] = @filesize($fullpath);
98                }
99
100                Return $image;
101        }
102
103        /**
104         * Process the actions, crop, scale(resize), rotate, flip, and save.
105         * When ever an action is performed, the result is save into a
106         * temporary image file, see createUnique on the filename specs.
107         * It does not return the saved file, alway returning the tmp file.
108         * @param string $action, should be 'crop', 'scale', 'rotate','flip', or 'save'
109         * @param string $relative the relative image filename
110         * @param string $fullpath the fullpath to the image file
111         * @return array with image information
112         * <code>array('src'=>'url of the image', 'dimensions'=>'width="xx" height="yy"',
113         * 'file'=>'image file, relative', 'fullpath'=>'full path to the image');</code>
114         */
115        function processAction($action, $relative, $fullpath)
116        {
117                $params = '';
118               
119                if(isset($_GET['params']))
120                        $params = $_GET['params'];
121
122                $values =  explode(',',$params);
123                $saveFile = $this->getSaveFileName($values[0]);
124
125                $img = Image_Transform::factory(IMAGE_CLASS);
126                $img->load($fullpath);
127                if ( is_callable($img,'paletteToTrueColorWithTransparency') && !imageistruecolor( $img->imageHandle))
128                {
129                        $img->paletteToTrueColorWithTransparency();
130                }
131                switch ($action)
132                {
133                        case 'crop':
134                                $img->crop(intval($values[0]),intval($values[1]),
135                                                        intval($values[2]),intval($values[3]));
136                        break;
137                        case 'scale':
138                                $img->resize(intval($values[0]),intval($values[1]));
139                                break;
140                        case 'rotate':
141                                $img->rotate(floatval($values[0]));
142                                break;
143                        case 'flip':
144                                if ($values[0] == 'hoz')
145                                        $img->flip(true);
146                                else if($values[0] == 'ver')
147                                        $img->flip(false);
148                                break;
149                        case 'save':
150                                if(!is_null($saveFile))
151                                {
152                                        $quality = intval($values[1]);
153                            if($quality <0) $quality = 85;
154                                        $newSaveFile = $this->makeRelative($relative, $saveFile);
155                                        $newSaveFile = $this->getUniqueFilename($newSaveFile);
156                                       
157                                        //get unique filename just returns the filename, so
158                                        //we need to make the relative path once more.
159                                        $newSaveFile = $this->makeRelative($relative, $newSaveFile);
160                                $image['saveFile'] = $newSaveFile;
161                                        $newSaveFullpath = $this->manager->getFullPath($newSaveFile);
162                                        if ( $values[0] == 'gif' && is_callable(array($img, 'preserveTransparencyForPalette')))
163                                        {
164                                                $img->preserveTransparencyForPalette();
165                                        }
166                                        $img->save($newSaveFullpath, $values[0], $quality);
167                                        if(is_file($newSaveFullpath))
168                                                $this->filesaved = 1;
169                                        else
170                                                $this->filesaved = -1;
171                                }
172                                break;
173                                case 'preview':
174                                        $quality = intval($values[1]);
175                                       
176                                       
177                                        $image['file'] = $relative;
178                                        $image['fullpath'] = $fullpath;
179                                       
180                                        //create the tmp image file
181                                        $filename = $this->createUnique($fullpath);
182                                        $newRelative = $this->makeRelative($relative, $filename);
183                                        $newFullpath = $this->manager->getFullPath($newRelative);
184                                        $newURL = $this->manager->getFileURL($newRelative);
185                                       
186                                       
187                                        if ( $values[0] == 'gif' && is_callable(array($img, 'preserveTransparencyForPalette')))
188                                        {
189                                                $img->preserveTransparencyForPalette();
190                                        }
191                                        $img->save($newFullpath, $values[0] );
192                                        $img->free();
193                       
194                                        //get the image information
195                                        $imgInfo = @getimagesize($newFullpath);
196                               
197                                        $image['src'] = $newURL;
198                                $image['width'] = $imgInfo[0];
199                                        $image['height'] = $imgInfo[1];
200                                        $image['dimensions'] = $imgInfo[3];
201                                        $image['file'] = $relative;
202                                        $image['fullpath'] = $fullpath;
203                                        $image['filesize'] = @filesize($newFullpath);
204
205                                        Return $image;
206       
207                                break;
208                }
209               
210                //create the tmp image file
211                $filename = $this->createUnique($fullpath);
212                $newRelative = $this->makeRelative($relative, $filename);
213                $newFullpath = $this->manager->getFullPath($newRelative);
214                $newURL = $this->manager->getFileURL($newRelative);
215
216                //save the file.
217                $img->save($newFullpath, 'png' );
218                $img->free();
219
220                //get the image information
221                $imgInfo = @getimagesize($newFullpath);
222
223                $image['src'] = $newURL;
224        $image['width'] = $imgInfo[0];
225                $image['height'] = $imgInfo[1];
226                $image['dimensions'] = $imgInfo[3];
227                $image['file'] = $newRelative;
228                $image['fullpath'] = $newFullpath;
229                $image['filesize'] = @filesize($newFullpath);
230                $image['type'] = image_type_to_mime_type($imgInfo[2]);
231               
232                Return $image;
233       
234        }
235
236        /**
237         * Get the file name base on the save name
238         * and the save type.
239         * @param string $type image type, 'jpeg', 'png', or 'gif'
240         * @return string the filename according to save type
241         */
242        function getSaveFileName($type)
243        {
244                if(!isset($_GET['file']))
245                        Return null;
246
247                $filename = Files::escape(rawurldecode($_GET['file']));
248                $index = strrpos($filename,'.');
249                $base = substr($filename,0,$index);
250                $ext = strtolower(substr($filename,$index+1,strlen($filename)));
251
252                if($type == 'jpeg' && !($ext=='jpeg' || $ext=='jpg'))
253                {
254                        Return $base.'.jpeg';
255                }
256                if($type=='png' && $ext != 'png')
257                        Return $base.'.png';
258                if($type=='gif' && $ext != 'gif')
259                        Return $base.'.gif';
260
261                Return $filename;
262        }
263
264        /**
265         * Get the default save file name, used by editor.php.
266         * @return string a suggestive filename, this should be unique
267         */
268        function getDefaultSaveFile()
269        {
270                if(isset($_GET['img']))
271                        $relative = rawurldecode($_GET['img']);
272                else
273                        Return null;
274
275                Return $this->getUniqueFilename($relative);
276        }
277
278        /**
279         * Get a unique filename. If the file exists, the filename
280         * base is appended with an increasing integer.
281         * @param string $relative the relative filename to the base_dir
282         * @return string a unique filename in the current path
283         */
284        function getUniqueFilename($relative)
285        {
286                $fullpath = $this->manager->getFullPath($relative);
287               
288                $pathinfo = pathinfo($fullpath);
289
290                $path = Files::fixPath($pathinfo['dirname']);
291                $file = Files::escape($pathinfo['basename']);
292               
293                $filename = $file;
294
295                $dotIndex = strrpos($file, '.');
296                $ext = '';
297
298                if(is_int($dotIndex))
299                {
300                        $ext = substr($file, $dotIndex);
301                        $base = substr($file, 0, $dotIndex);
302                }
303
304                $counter = 0;
305                while(is_file($path.$filename))
306                {
307                        $counter++;
308                        $filename = $base.'_'.$counter.$ext;
309                }
310               
311                Return $filename;
312               
313        }
314
315        /**
316         * Specifiy the original relative path, a new filename
317         * and return the new filename with relative path.
318         * i.e. $pathA (-filename) + $file
319         * @param string $pathA the relative file
320         * @param string $file the new filename
321         * @return string relative path with the new filename
322         */
323        function makeRelative($pathA, $file)
324        {
325                $index = strrpos($pathA,'/');
326                if(!is_int($index))
327                        Return $file;
328
329                $path = substr($pathA, 0, $index);
330                Return Files::fixPath($path).$file;
331        }
332
333        /**
334         * Get the action GET parameter
335         * @return string action parameter
336         */
337        function getAction()
338        {
339                $action = null;
340                if(isset($_GET['action']))
341                        $action = $_GET['action'];
342                Return $action;
343        }
344
345        /**
346         * Generate a unique string based on md5(microtime()).
347         * Well not so uniqe, as it is limited to 6 characters
348         * @return string unique string.
349         */
350    function uniqueStr()
351    {
352      return substr(md5(microtime()),0,6);
353    }
354
355        /**
356         * Create unique tmp image file name.
357         * The filename is based on the tmp file prefix
358         * specified in config.inc.php plus
359         * the UID (basically a md5 of the remote IP)
360         * and some random 6 character string.
361         * This function also calls to clean up the tmp files.
362         * @param string $file the fullpath to a file
363         * @return string a unique filename for that path
364         * NOTE: it only returns the filename, path no included.
365         */
366        function createUnique($file)
367        {
368                $pathinfo = pathinfo($file);
369                $path = Files::fixPath($pathinfo['dirname']);
370                $imgType = $this->getImageType($file);
371
372                $unique_str = $this->manager->getTmpPrefix().$this->_uid.'_'.$this->uniqueStr().".".$imgType;
373
374           //make sure the the unique temp file does not exists
375        while (file_exists($path.$unique_str))
376        {
377            $unique_str = $this->manager->getTmpPrefix().$this->_uid.'_'.$this->uniqueStr().".".$imgType;
378        }
379
380                $this->cleanUp($path,$pathinfo['basename']);
381
382                Return $unique_str;
383        }
384
385        /**
386         * Delete any tmp image files.
387         * @param string $path the full path
388         * where the clean should take place.
389         */
390        function cleanUp($path,$file)
391        {
392                $path = Files::fixPath($path);
393
394                if(!is_dir($path))
395                        Return false;
396
397                $d = @dir($path);
398               
399                $tmp = $this->manager->getTmpPrefix();
400                $tmpLen = strlen($tmp);
401
402                $prefix = $tmp.$this->_uid;
403                $len = strlen($prefix);
404
405                while (false !== ($entry = $d->read()))
406                {
407                        //echo $entry."<br>";
408                        if(is_file($path.$entry) && $this->manager->isTmpFile($entry))
409                        {
410                                if(substr($entry,0,$len)==$prefix && $entry != $file)
411                                        Files::delFile($path.$entry);
412                                else if(substr($entry,0,$tmpLen)==$tmp && $entry != $file)
413                                {
414                                        if(filemtime($path.$entry)+$this->lapse_time < time())
415                                                Files::delFile($path.$entry);
416                                }
417                        }
418                }
419                $d->close();
420        }
421
422        /**
423         * Get the image type base on an image file.
424         * @param string $file the full path to the image file.
425         * @return string of either 'gif', 'jpeg', 'png' or 'bmp'
426         * otherwise it will return null.
427         */
428        function getImageType($file)
429        {
430                $imageInfo = @getImageSize($file);
431
432                if(!is_array($imageInfo))
433                        Return null;
434
435                switch($imageInfo[2])
436                {
437                        case 1:
438                                Return 'gif';
439                        case 2:
440                                Return 'jpeg';
441                        case 3:
442                                Return 'png';
443                        case 6:
444                                Return 'bmp';
445                }
446
447                Return null;
448        }
449
450        /**
451         * Check if the specified image can be edit by GD
452         * mainly to check that GD can read and save GIFs
453         * @return int 0 if it is not a GIF file, 1 is GIF is editable, -1 if not editable.
454         */
455        function isGDEditable()
456        {
457                if(isset($_GET['img']))
458                        $relative = rawurldecode($_GET['img']);
459                else
460                        Return 0;
461                if(IMAGE_CLASS != 'GD')
462                        Return 0;
463
464                $fullpath = $this->manager->getFullPath($relative);
465 
466                $type = $this->getImageType($fullpath);
467                if($type != 'gif')
468                        Return 0;
469
470                if(function_exists('ImageCreateFrom'.$type)
471                        && function_exists('image'.$type))
472                        Return 1;
473                else
474                        Return -1;
475        }
476
477        /**
478         * Check if GIF can be edit by GD.
479         * @return int 0 if it is not using the GD library, 1 is GIF is editable, -1 if not editable.
480         */
481        function isGDGIFAble()
482        {
483                if(IMAGE_CLASS != 'GD')
484                        Return 0;
485
486                if(function_exists('ImageCreateFromGif')
487                        && function_exists('imagegif'))
488                        Return 1;
489                else
490                        Return -1;
491        }
492}
493
494?>
Note: See TracBrowser for help on using the repository browser.