XOOPS  2.6.0
php_image_magician.php
Go to the documentation of this file.
1 <?php
2  # ========================================================================#
3  #
4  # This work is licensed under the Creative Commons Attribution 3.0 Unported
5  # License. To view a copy of this license,
6  # visit http://creativecommons.org/licenses/by/3.0/ or send a letter to
7  # Creative Commons, 444 Castro Street, Suite 900, Mountain View, California,
8  # 94041, USA.
9  #
10  # All rights reserved.
11  #
12  # Author: Jarrod Oberto
13  # Version: 1.5.1
14  # Date: 10-05-11
15  # Purpose: Provide tools for image manipulation using GD
16  # Param In: See functions.
17  # Param Out: Produces a resized image
18  # Requires : Requires PHP GD library.
19  # Usage Example:
20  # include("lib/php_image_magician.php");
21  # $magicianObj = new resize('images/car.jpg');
22  # $magicianObj -> resizeImage(150, 100, 0);
23  # $magicianObj -> saveImage('images/car_small.jpg', 100);
24  #
25  # - See end of doc for more examples -
26  #
27  # Supported file types include: jpg, png, gif, bmp, psd (read)
28  #
29  #
30  #
31  # The following functions are taken from phpThumb() [available from
32  # http://phpthumb.sourceforge.net], and are used with written permission
33  # from James Heinrich.
34  # - GD2BMPstring
35  # - GetPixelColor
36  # - LittleEndian2String
37  #
38  # The following functions are from Marc Hibbins and are used with written
39  # permission (are also under the Attribution-ShareAlike
40  # [http://creativecommons.org/licenses/by-sa/3.0/] license.
41  # -
42  #
43  # PhpPsdReader is used with written permission from Tim de Koning.
44  # [http://www.kingsquare.nl/phppsdreader]
45  #
46  #
47  #
48  # Modificatoin history
49  # Date Initials Ver Description
50  # 10-05-11 J.C.O 0.0 Initial build
51  # 01-06-11 J.C.O 0.1.1 * Added reflections
52  # * Added Rounded corners
53  # * You can now use PNG interlacing
54  # * Added shadow
55  # * Added caption box
56  # * Added vintage filter
57  # * Added dynamic image resizing (resize on the fly)
58  # * minor bug fixes
59  # 05-06-11 J.C.O 0.1.1.1 * Fixed undefined variables
60  # 17-06-11 J.C.O 0.1.2 * Added image_batch_class.php class
61  # * Minor bug fixes
62  # 26-07-11 J.C.O 0.1.4 * Added support for external images
63  # * Can now set the crop poisition
64  # 03-08-11 J.C.O 0.1.5 * Added reset() method to reset resource to
65  # original input file.
66  # * Added method addTextToCaptionBox() to
67  # simplify adding text to a caption box.
68  # * Added experimental writeIPTC. (not finished)
69  # * Added experimental readIPTC. (not finished)
70  # 11-08-11 J.C.O * Added initial border presets.
71  # 30-08-11 J.C.O * Added 'auto' crop option to crop portrait
72  # images near the top.
73  # 08-09-11 J.C.O * Added cropImage() method to allow standalone
74  # cropping.
75  # 17-09-11 J.C.O * Added setCropFromTop() set method - set the
76  # percentage to crop from the top when using
77  # crop 'auto' option.
78  # * Added setTransparency() set method - allows you
79  # to turn transparency off (like when saving
80  # as a jpg).
81  # * Added setFillColor() set method - set the
82  # background color to use instead of transparency.
83  # 05-11-11 J.C.O 0.1.5.1 * Fixed interlacing option
84  # 0-07-12 J.C.O 1.0
85  #
86  # Known issues & Limitations:
87  # -------------------------------
88  # Not so much an issue, the image is destroyed on the deconstruct rather than
89  # when we have finished with it. The reason for this is that we don't know
90  # when we're finished with it as you can both save the image and display
91  # it directly to the screen (imagedestroy($this->imageResized))
92  #
93  # Opening BMP files is slow. A test with 884 bmp files processed in a loop
94  # takes forever - over 5 min. This test inlcuded opening the file, then
95  # getting and displaying its width and height.
96  #
97  # $forceStretch:
98  # -------------------------------
99  # On by default.
100  # $forceStretch can be disabled by calling method setForceStretch with false
101  # parameter. If disabled, if an images original size is smaller than the size
102  # specified by the user, the original size will be used. This is useful when
103  # dealing with small images.
104  #
105  # If enabled, images smaller than the size specified will be stretched to
106  # that size.
107  #
108  # Tips:
109  # -------------------------------
110  # * If you're resizing a transparent png and saving it as a jpg, set
111  # $keepTransparency to false with: $magicianObj->setTransparency(false);
112  #
113  # FEATURES:
114  # * EASY TO USE
115  # * BMP SUPPORT (read & write)
116  # * PSD (photoshop) support (read)
117  # * RESIZE IMAGES
118  # - Preserve transparency (png, gif)
119  # - Apply sharpening (jpg) (requires PHP >= 5.1.0)
120  # - Set image quality (jpg, png)
121  # - Resize modes:
122  # - exact size
123  # - resize by width (auto height)
124  # - resize by height (auto width)
125  # - auto (automatically determine the best of the above modes to use)
126  # - crop - resize as best as it can then crop the rest
127  # - Force stretching of smaller images (upscale)
128  # * APPLY FILTERS
129  # - Convert to grey scale
130  # - Convert to black and white
131  # - Convert to sepia
132  # - Convert to negative
133  # * ROTATE IMAGES
134  # - Rotate using predefined "left", "right", or "180"; or any custom degree amount
135  # * EXTRACT EXIF DATA (requires exif module)
136  # - make
137  # - model
138  # - date
139  # - exposure
140  # - aperture
141  # - f-stop
142  # - iso
143  # - focal length
144  # - exposure program
145  # - metering mode
146  # - flash status
147  # - creator
148  # - copyright
149  # * ADD WATERMARK
150  # - Specify exact x, y placement
151  # - Or, specify using one of the 9 pre-defined placements such as "tl"
152  # (for top left), "m" (for middle), "br" (for bottom right)
153  # - also specify padding from edge amount (optional).
154  # - Set opacity of watermark (png).
155  # * ADD BORDER
156  # * USE HEX WHEN SPECIFYING COLORS (eg: #ffffff)
157  # * SAVE IMAGE OR OUTPUT TO SCREEN
158  #
159  #
160  # ========================================================================#
161 
162 
163 class imageLib
164 {
165 
166  private $fileName;
167  private $image;
168  protected $imageResized;
169  private $widthOriginal; # Always be the original width
171  private $width; # Current width (width after resize)
172  private $height;
173  private $imageSize;
174  private $fileExtension;
175 
176  private $debug = true;
177  private $errorArray = array();
178 
179  private $forceStretch = true;
181 
182  private $transparentArray = array('.png', '.gif');
183  private $keepTransparency = true;
184  private $fillColorArray = array('r'=>255, 'g'=>255, 'b'=>255);
185 
186  private $sharpenArray = array('jpg');
187 
188  private $psdReaderPath;
190 
191  private $isInterlace;
192 
193  private $captionBoxPositionArray = array();
194 
195  private $fontDir = 'fonts';
196 
197  private $cropFromTopPercent = 10;
198 
199 
200 ## --------------------------------------------------------
201 
203  # Author: Jarrod Oberto
204  # Date: 27-02-08
205  # Purpose: Constructor
206  # Param in: $fileName: File name and path.
207  # Param out: n/a
208  # Reference:
209  # Notes:
210  #
211  {
212  if (!$this->testGDInstalled()) { if ($this->debug) { throw new Exception('The GD Library is not installed.'); }else{ throw new Exception(); }};
213 
214  $this->initialise();
215 
216  // *** Save the image file name. Only store this incase you want to display it
217  $this->fileName = $fileName;
218  $this->fileExtension = fix_strtolower(strrchr($fileName, '.'));
219 
220  // *** Open up the file
221  $this->image = $this->openImage($fileName);
222 
223 
224  // *** Assign here so we don't modify the original
225  $this->imageResized = $this->image;
226 
227  // *** If file is an image
228  if ($this->testIsImage($this->image))
229  {
230  // *** Get width and height
231  $this->width = imagesx($this->image);
232  $this->widthOriginal = imagesx($this->image);
233  $this->height = imagesy($this->image);
234  $this->heightOriginal = imagesy($this->image);
235 
236 
237  /* Added 15-09-08
238  * Get the filesize using this build in method.
239  * Stores an array of size
240  *
241  * $this->imageSize[1] = width
242  * $this->imageSize[2] = height
243  * $this->imageSize[3] = width x height
244  *
245  */
246  $this->imageSize = getimagesize($this->fileName);
247 
248  } else {
249  $this->errorArray[] = 'File is not an image';
250  }
251  }
252 
253 ## --------------------------------------------------------
254 
255  private function initialise () {
256 
257  $this->psdReaderPath = __DIR__ . '/classPhpPsdReader.php';
258  $this->filterOverlayPath = __DIR__ . '/filters';
259 
260  // *** Set if image should be interlaced or not.
261  $this->isInterlace = false;
262  }
263 
264 
265 
266 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
267  Resize
268 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
269 
270 
271  public function resizeImage($newWidth, $newHeight, $option = 0, $sharpen = false, $autoRotate = false)
272  # Author: Jarrod Oberto
273  # Date: 27-02-08
274  # Purpose: Resizes the image
275  # Param in: $newWidth:
276  # $newHeight:
277  # $option: 0 / exact = defined size;
278  # 1 / portrait = keep aspect set height;
279  # 2 / landscape = keep aspect set width;
280  # 3 / auto = auto;
281  # 4 / crop= resize and crop;
282  #
283  # $option can also be an array containing options for
284  # cropping. E.G., array('crop', 'r')
285  #
286  # This array only applies to 'crop' and the 'r' refers to
287  # "crop right". Other value include; tl, t, tr, l, m (default),
288  # r, bl, b, br, or you can specify your own co-ords (which
289  # isn't recommended.
290  #
291  # $sharpen: true: sharpen (jpg only);
292  # false: don't sharpen
293  # Param out: n/a
294  # Reference:
295  # Notes: To clarify the $option input:
296  # 0 = The exact height and width dimensions you set.
297  # 1 = Whatever height is passed in will be the height that
298  # is set. The width will be calculated and set automatically
299  # to a the value that keeps the original aspect ratio.
300  # 2 = The same but based on the width. We try make the image the
301  # biggest size we can while stil fitting inside the box size
302  # 3 = Depending whether the image is landscape or portrait, this
303  # will automatically determine whether to resize via
304  # dimension 1,2 or 0
305  # 4 = Will resize and then crop the image for best fit
306  #
307  # forceStretch can be applied to options 1,2,3 and 4
308  #
309  {
310 
311  // *** We can pass in an array of options to change the crop position
312  $cropPos = 'm';
313  if (is_array($option) && fix_strtolower($option[0]) == 'crop') {
314  $cropPos = $option[1]; # get the crop option
315  } else if (strpos($option, '-') !== false) {
316  // *** Or pass in a hyphen seperated option
317  $optionPiecesArray = explode('-', $option);
318  $cropPos = end($optionPiecesArray);
319  }
320 
321  // *** Check the option is valid
322  $option = $this->prepOption($option);
323 
324  // *** Make sure the file passed in is valid
325  if (!$this->image) { if ($this->debug) { throw new Exception('file ' . $this->getFileName() .' is missing or invalid'); }else{ throw new Exception(); }};
326 
327  // *** Get optimal width and height - based on $option
328  $dimensionsArray = $this->getDimensions($newWidth, $newHeight, $option);
329 
330  $optimalWidth = $dimensionsArray['optimalWidth'];
331  $optimalHeight = $dimensionsArray['optimalHeight'];
332 
333  // *** Resample - create image canvas of x, y size
334  $this->imageResized = imagecreatetruecolor($optimalWidth, $optimalHeight);
335  $this->keepTransparancy($optimalWidth, $optimalHeight, $this->imageResized);
336  imagecopyresampled($this->imageResized, $this->image, 0, 0, 0, 0, $optimalWidth, $optimalHeight, $this->width, $this->height);
337 
338 
339  // *** If '4', then crop too
340  if ($option == 4 || $option == 'crop') {
341 
342  if (($optimalWidth >= $newWidth && $optimalHeight >= $newHeight)) {
343  $this->crop($optimalWidth, $optimalHeight, $newWidth, $newHeight, $cropPos);
344  }
345  }
346 
347  // *** If Rotate.
348  if ($autoRotate) {
349 
350  $exifData = $this->getExif(false);
351  if (count($exifData) > 0) {
352 
353  switch($exifData['orientation']) {
354  case 8:
355  $this->imageResized = imagerotate($this->imageResized,90,0);
356  break;
357  case 3:
358  $this->imageResized = imagerotate($this->imageResized,180,0);
359  break;
360  case 6:
361  $this->imageResized = imagerotate($this->imageResized,-90,0);
362  break;
363  }
364  }
365  }
366 
367  // *** Sharpen image (if jpg and the user wishes to do so)
368  if ($sharpen && in_array($this->fileExtension, $this->sharpenArray)) {
369 
370  // *** Sharpen
371  $this->sharpen();
372  }
373  }
374 
375 ## --------------------------------------------------------
376 
377  public function cropImage($newWidth, $newHeight, $cropPos = 'm')
378  # Author: Jarrod Oberto
379  # Date: 08-09-11
380  # Purpose: Crops the image
381  # Param in: $newWidth: crop with
382  # $newHeight: crop height
383  # $cropPos: Can be any of the following:
384  # tl, t, tr, l, m, r, bl, b, br, auto
385  # Or:
386  # a custom position such as '30x50'
387  # Param out: n/a
388  # Reference:
389  # Notes:
390  #
391  {
392 
393  // *** Make sure the file passed in is valid
394  if (!$this->image) { if ($this->debug) { throw new Exception('file ' . $this->getFileName() .' is missing or invalid'); }else{ throw new Exception(); }};
395 
396  $this->imageResized = $this->image;
397  $this->crop($this->width, $this->height, $newWidth, $newHeight, $cropPos);
398 
399  }
400 
401 ## --------------------------------------------------------
402 
403  private function keepTransparancy($width, $height, $im)
404  # Author: Jarrod Oberto
405  # Date: 08-04-11
406  # Purpose: Keep transparency for png and gif image
407  # Param in:
408  # Param out: n/a
409  # Reference:
410  # Notes:
411  #
412  {
413  // *** If PNG, perform some transparency retention actions (gif untested)
414  if (in_array($this->fileExtension, $this->transparentArray) && $this->keepTransparency) {
415  imagealphablending($im, false);
416  imagesavealpha($im, true);
417  $transparent = imagecolorallocatealpha($im, 255, 255, 255, 127);
418  imagefilledrectangle($im, 0, 0, $width, $height, $transparent);
419  } else {
420  $color = imagecolorallocate($im, $this->fillColorArray['r'], $this->fillColorArray['g'], $this->fillColorArray['b']);
421  imagefilledrectangle($im, 0, 0, $width, $height, $color);
422  }
423  }
424 
425 ## --------------------------------------------------------
426 
427  private function crop($optimalWidth, $optimalHeight, $newWidth, $newHeight, $cropPos)
428  # Author: Jarrod Oberto
429  # Date: 15-09-08
430  # Purpose: Crops the image
431  # Param in: $newWidth:
432  # $newHeight:
433  # Param out: n/a
434  # Reference:
435  # Notes:
436  #
437  {
438 
439  // *** Get cropping co-ordinates
440  $cropArray = $this->getCropPlacing($optimalWidth, $optimalHeight, $newWidth, $newHeight, $cropPos);
441  $cropStartX = $cropArray['x'];
442  $cropStartY = $cropArray['y'];
443 
444  // *** Crop this bad boy
445  $crop = imagecreatetruecolor($newWidth , $newHeight);
446  $this->keepTransparancy($optimalWidth, $optimalHeight, $crop);
447  imagecopyresampled($crop, $this->imageResized, 0, 0, $cropStartX, $cropStartY, $newWidth, $newHeight , $newWidth, $newHeight);
448 
449  $this->imageResized = $crop;
450 
451  // *** Set new width and height to our variables
452  $this->width = $newWidth;
453  $this->height = $newHeight;
454 
455  }
456 
457 ## --------------------------------------------------------
458 
459  private function getCropPlacing($optimalWidth, $optimalHeight, $newWidth, $newHeight, $pos='m')
460  #
461  # Author: Jarrod Oberto
462  # Date: July 11
463  # Purpose: Set the cropping area.
464  # Params in:
465  # Params out: (array) the crop x and y co-ordinates.
466  # Notes: When specifying the exact pixel crop position (eg 10x15), be
467  # very careful as it's easy to crop out of the image leaving
468  # black borders.
469  #
470  {
471  $pos = fix_strtolower($pos);
472 
473  // *** If co-ords have been entered
474  if (strstr($pos, 'x')) {
475  $pos = str_replace(' ', '', $pos);
476 
477  $xyArray = explode('x', $pos);
478  list($cropStartX, $cropStartY) = $xyArray;
479 
480  } else {
481 
482  switch ($pos) {
483  case 'tl':
484  $cropStartX = 0;
485  $cropStartY = 0;
486  break;
487 
488  case 't':
489  $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
490  $cropStartY = 0;
491  break;
492 
493  case 'tr':
494  $cropStartX = $optimalWidth - $newWidth;
495  $cropStartY = 0;
496  break;
497 
498  case 'l':
499  $cropStartX = 0;
500  $cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 );
501  break;
502 
503  case 'm':
504  $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
505  $cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 );
506  break;
507 
508  case 'r':
509  $cropStartX = $optimalWidth - $newWidth;
510  $cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 );
511  break;
512 
513  case 'bl':
514  $cropStartX = 0;
515  $cropStartY = $optimalHeight - $newHeight;
516  break;
517 
518  case 'b':
519  $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
520  $cropStartY = $optimalHeight - $newHeight;
521  break;
522 
523  case 'br':
524  $cropStartX = $optimalWidth - $newWidth;
525  $cropStartY = $optimalHeight - $newHeight;
526  break;
527 
528  case 'auto':
529  // *** If image is a portrait crop from top, not center. v1.5
530  if ($optimalHeight > $optimalWidth) {
531  $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
532  $cropStartY = ($this->cropFromTopPercent /100) * $optimalHeight;
533  } else {
534 
535  // *** Else crop from the center
536  $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
537  $cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 );
538  }
539  break;
540 
541  default:
542  // *** Default to center
543  $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
544  $cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 );
545  break;
546  }
547  }
548 
549  return array('x' => $cropStartX, 'y' => $cropStartY);
550  }
551 
552 ## --------------------------------------------------------
553 
554  private function getDimensions($newWidth, $newHeight, $option)
555  # Author: Jarrod Oberto
556  # Date: 17-11-09
557  # Purpose: Get new image dimensions based on user specificaions
558  # Param in: $newWidth:
559  # $newHeight:
560  # Param out: Array of new width and height values
561  # Reference:
562  # Notes: If $option = 3 then this function is call recursivly
563  #
564  # To clarify the $option input:
565  # 0 = The exact height and width dimensions you set.
566  # 1 = Whatever height is passed in will be the height that
567  # is set. The width will be calculated and set automatically
568  # to a the value that keeps the original aspect ratio.
569  # 2 = The same but based on the width.
570  # 3 = Depending whether the image is landscape or portrait, this
571  # will automatically determine whether to resize via
572  # dimension 1,2 or 0.
573  # 4 = Resize the image as much as possible, then crop the
574  # remainder.
575  {
576 
577  switch (strval($option))
578  {
579  case '0':
580  case 'exact':
581  $optimalWidth = $newWidth;
582  $optimalHeight= $newHeight;
583  break;
584  case '1':
585  case 'portrait':
586  $dimensionsArray = $this->getSizeByFixedHeight($newWidth, $newHeight);
587  $optimalWidth = $dimensionsArray['optimalWidth'];
588  $optimalHeight = $dimensionsArray['optimalHeight'];
589  break;
590  case '2':
591  case 'landscape':
592  $dimensionsArray = $this->getSizeByFixedWidth($newWidth, $newHeight);
593  $optimalWidth = $dimensionsArray['optimalWidth'];
594  $optimalHeight = $dimensionsArray['optimalHeight'];
595  break;
596  case '3':
597  case 'auto':
598  $dimensionsArray = $this->getSizeByAuto($newWidth, $newHeight);
599  $optimalWidth = $dimensionsArray['optimalWidth'];
600  $optimalHeight = $dimensionsArray['optimalHeight'];
601  break;
602  case '4':
603  case 'crop':
604  $dimensionsArray = $this->getOptimalCrop($newWidth, $newHeight);
605  $optimalWidth = $dimensionsArray['optimalWidth'];
606  $optimalHeight = $dimensionsArray['optimalHeight'];
607  break;
608  }
609 
610  return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight);
611  }
612 
613 ## --------------------------------------------------------
614 
615  private function getSizeByFixedHeight($newWidth, $newHeight)
616  {
617  // *** If forcing is off...
618  if (!$this->forceStretch) {
619 
620  // *** ...check if actual height is less than target height
621  if ($this->height < $newHeight) {
622  return array('optimalWidth' => $this->width, 'optimalHeight' => $this->height);
623  }
624  }
625 
626  $ratio = $this->width / $this->height;
627 
628  $newWidth = $newHeight * $ratio;
629 
630  //return $newWidth;
631  return array('optimalWidth' => $newWidth, 'optimalHeight' => $newHeight);
632  }
633 
634 ## --------------------------------------------------------
635 
636  private function getSizeByFixedWidth($newWidth, $newHeight)
637  {
638  // *** If forcing is off...
639  if (!$this->forceStretch) {
640 
641  // *** ...check if actual width is less than target width
642  if ($this->width < $newWidth) {
643  return array('optimalWidth' => $this->width, 'optimalHeight' => $this->height);
644  }
645  }
646 
647  $ratio = $this->height / $this->width;
648 
649  $newHeight = $newWidth * $ratio;
650 
651  //return $newHeight;
652  return array('optimalWidth' => $newWidth, 'optimalHeight' => $newHeight);
653  }
654 
655 ## --------------------------------------------------------
656 
657  private function getSizeByAuto($newWidth, $newHeight)
658  # Author: Jarrod Oberto
659  # Date: 19-08-08
660  # Purpose: Depending on the height, choose to resize by 0, 1, or 2
661  # Param in: The new height and new width
662  # Notes:
663  #
664  {
665  // *** If forcing is off...
666  if (!$this->forceStretch) {
667 
668  // *** ...check if actual size is less than target size
669  if ($this->width < $newWidth && $this->height < $newHeight) {
670  return array('optimalWidth' => $this->width, 'optimalHeight' => $this->height);
671  }
672  }
673 
674  if ($this->height < $this->width)
675  // *** Image to be resized is wider (landscape)
676  {
677  //$optimalWidth = $newWidth;
678  //$optimalHeight= $this->getSizeByFixedWidth($newWidth);
679 
680  $dimensionsArray = $this->getSizeByFixedWidth($newWidth, $newHeight);
681  $optimalWidth = $dimensionsArray['optimalWidth'];
682  $optimalHeight = $dimensionsArray['optimalHeight'];
683  }
684  elseif ($this->height > $this->width)
685  // *** Image to be resized is taller (portrait)
686  {
687  //$optimalWidth = $this->getSizeByFixedHeight($newHeight);
688  //$optimalHeight= $newHeight;
689 
690  $dimensionsArray = $this->getSizeByFixedHeight($newWidth, $newHeight);
691  $optimalWidth = $dimensionsArray['optimalWidth'];
692  $optimalHeight = $dimensionsArray['optimalHeight'];
693  }
694  else
695  // *** Image to be resizerd is a square
696  {
697 
698  if ($newHeight < $newWidth) {
699  //$optimalWidth = $newWidth;
700  //$optimalHeight= $this->getSizeByFixedWidth($newWidth);
701  $dimensionsArray = $this->getSizeByFixedWidth($newWidth, $newHeight);
702  $optimalWidth = $dimensionsArray['optimalWidth'];
703  $optimalHeight = $dimensionsArray['optimalHeight'];
704  } else if ($newHeight > $newWidth) {
705  //$optimalWidth = $this->getSizeByFixedHeight($newHeight);
706  //$optimalHeight= $newHeight;
707  $dimensionsArray = $this->getSizeByFixedHeight($newWidth, $newHeight);
708  $optimalWidth = $dimensionsArray['optimalWidth'];
709  $optimalHeight = $dimensionsArray['optimalHeight'];
710  } else {
711  // *** Sqaure being resized to a square
712  $optimalWidth = $newWidth;
713  $optimalHeight= $newHeight;
714  }
715  }
716 
717  return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight);
718  }
719 
720 ## --------------------------------------------------------
721 
722  private function getOptimalCrop($newWidth, $newHeight)
723  # Author: Jarrod Oberto
724  # Date: 17-11-09
725  # Purpose: Get optimal crop dimensions
726  # Param in: width and height as requested by user (fig 3)
727  # Param out: Array of optimal width and height (fig 2)
728  # Reference:
729  # Notes: The optimal width and height return are not the same as the
730  # same as the width and height passed in. For example:
731  #
732  #
733  # |-----------------| |------------| |-------|
734  # | | => |**| |**| => | |
735  # | | |**| |**| | |
736  # | | |------------| |-------|
737  # |-----------------|
738  # original optimal crop
739  # size size size
740  # Fig 1 2 3
741  #
742  # 300 x 250 150 x 125 150 x 100
743  #
744  # The optimal size is the smallest size (that is closest to the crop size)
745  # while retaining proportion/ratio.
746  #
747  # The crop size is the optimal size that has been cropped on one axis to
748  # make the image the exact size specified by the user.
749  #
750  # * represent cropped area
751  #
752  {
753 
754  // *** If forcing is off...
755  if (!$this->forceStretch) {
756 
757  // *** ...check if actual size is less than target size
758  if ($this->width < $newWidth && $this->height < $newHeight) {
759  return array('optimalWidth' => $this->width, 'optimalHeight' => $this->height);
760  }
761  }
762 
763  $heightRatio = $this->height / $newHeight;
764  $widthRatio = $this->width / $newWidth;
765 
766  if ($heightRatio < $widthRatio) {
767  $optimalRatio = $heightRatio;
768  } else {
769  $optimalRatio = $widthRatio;
770  }
771 
772  $optimalHeight = round( $this->height / $optimalRatio );
773  $optimalWidth = round( $this->width / $optimalRatio );
774 
775  return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight);
776  }
777 
778 ## --------------------------------------------------------
779 
780  private function sharpen()
781  # Author: Jarrod Oberto
782  # Date: 08 04 2011
783  # Purpose: Sharpen image
784  # Param in: n/a
785  # Param out: n/a
786  # Reference:
787  # Notes:
788  # Credit: Incorporates Joe Lencioni (August 6, 2008) code
789  {
790 
791  if (version_compare(PHP_VERSION, '5.1.0') >= 0) {
792 
793  // ***
794  if ($this->aggresiveSharpening) { # A more aggressive sharpening solution
795 
796  $sharpenMatrix = array( array( -1, -1, -1 ),
797  array( -1, 16, -1 ),
798  array( -1, -1, -1 ) );
799  $divisor = 8;
800  $offset = 0;
801 
802  imageconvolution($this->imageResized, $sharpenMatrix, $divisor, $offset);
803  }
804  else # More subtle and personally more desirable
805  {
806  $sharpness = $this->findSharp($this->widthOriginal, $this->width);
807 
808  $sharpenMatrix = array(
809  array(-1, -2, -1),
810  array(-2, $sharpness + 12, -2), //Lessen the effect of a filter by increasing the value in the center cell
811  array(-1, -2, -1)
812  );
813  $divisor = $sharpness; // adjusts brightness
814  $offset = 0;
815  imageconvolution($this->imageResized, $sharpenMatrix, $divisor, $offset);
816  }
817  }
818  else
819  {
820  if ($this->debug) { throw new Exception('Sharpening required PHP 5.1.0 or greater.'); }
821  }
822  }
823 
824  ## --------------------------------------------------------
825 
826  private function sharpen2($level)
827  {
828  $sharpenMatrix = array(
829  array($level, $level, $level),
830  array($level, (8*$level)+1, $level), //Lessen the effect of a filter by increasing the value in the center cell
831  array($level, $level, $level)
832  );
833 
834  }
835 
836 ## --------------------------------------------------------
837 
838  private function findSharp($orig, $final)
839  # Author: Ryan Rud (http://adryrun.com)
840  # Purpose: Find optimal sharpness
841  # Param in: n/a
842  # Param out: n/a
843  # Reference:
844  # Notes:
845  #
846  {
847  $final = $final * (750.0 / $orig);
848  $a = 52;
849  $b = -0.27810650887573124;
850  $c = .00047337278106508946;
851 
852  $result = $a + $b * $final + $c * $final * $final;
853 
854  return max(round($result), 0);
855  }
856 
857 ## --------------------------------------------------------
858 
859  private function prepOption($option)
860  # Author: Jarrod Oberto
861  # Purpose: Prep option like change the passed in option to lowercase
862  # Param in: (str/int) $option: eg. 'exact', 'crop'. 0, 4
863  # Param out: lowercase string
864  # Reference:
865  # Notes:
866  #
867  {
868  if (is_array($option)) {
869  if (fix_strtolower($option[0]) == 'crop' && count($option) == 2) {
870  return 'crop';
871  } else {
872  throw new Exception('Crop resize option array is badly formatted.');
873  }
874  } else if (strpos($option, 'crop') !== false) {
875  return 'crop';
876  }
877 
878  if (is_string($option)) {
879  return fix_strtolower($option);
880  }
881 
882  return $option;
883  }
884 
885 
886 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
887  Presets
888 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
889 
890 #
891 # Preset are pre-defined templates you can apply to your image.
892 #
893 # These are inteded to be applied to thumbnail images.
894 #
895 
896 
897  public function borderPreset($preset)
898  {
899  switch ($preset)
900  {
901 
902  case 'simple':
903  $this->addBorder(7, '#fff');
904  $this->addBorder(6, '#f2f1f0');
905  $this->addBorder(2, '#fff');
906  $this->addBorder(1, '#ccc');
907  break;
908  default:
909  break;
910  }
911 
912  }
913 
914 
915 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
916  Draw border
917 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
918 
919  public function addBorder($thickness = 1, $rgbArray = array(255, 255, 255))
920  # Author: Jarrod Oberto
921  # Date: 05-05-11
922  # Purpose: Add a border to the image
923  # Param in:
924  # Param out:
925  # Reference:
926  # Notes: This border is added to the INSIDE of the image
927  #
928  {
929  if ($this->imageResized) {
930 
931  $rgbArray = $this->formatColor($rgbArray);
932  $r = $rgbArray['r'];
933  $g = $rgbArray['g'];
934  $b = $rgbArray['b'];
935 
936 
937  $x1 = 0;
938  $y1 = 0;
939  $x2 = ImageSX($this->imageResized) - 1;
940  $y2 = ImageSY($this->imageResized) - 1;
941 
942  $rgbArray = ImageColorAllocate($this->imageResized, $r, $g, $b);
943 
944 
945  for($i = 0; $i < $thickness; $i++) {
946  ImageRectangle($this->imageResized, $x1++, $y1++, $x2--, $y2--, $rgbArray);
947  }
948  }
949  }
950 
951 
952 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
953  Gray Scale
954 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
955 
956  public function greyScale()
957  # Author: Jarrod Oberto
958  # Date: 07-05-2011
959  # Purpose: Make image greyscale
960  # Param in: n/a
961  # Param out:
962  # Reference:
963  # Notes:
964  #
965  {
966  if ($this->imageResized) {
967  imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
968  }
969 
970  }
971 
972  ## --------------------------------------------------------
973 
974  public function greyScaleEnhanced()
975  # Author: Jarrod Oberto
976  # Date: 07-05-2011
977  # Purpose: Make image greyscale
978  # Param in: n/a
979  # Param out:
980  # Reference:
981  # Notes:
982  #
983  {
984  if ($this->imageResized) {
985  imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
986  imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -15);
987  imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, 2);
988  $this->sharpen($this->width);
989  }
990  }
991 
992  ## --------------------------------------------------------
993 
994  public function greyScaleDramatic()
995  # Alias of gd_filter_monopin
996  {
997  $this->gd_filter_monopin();
998  }
999 
1000 
1001 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1002  Black 'n White
1003 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1004 
1005  public function blackAndWhite()
1006  # Author: Jarrod Oberto
1007  # Date: 07-05-2011
1008  # Purpose: Make image black and white
1009  # Param in: n/a
1010  # Param out:
1011  # Reference:
1012  # Notes:
1013  #
1014  {
1015  if ($this->imageResized) {
1016 
1017  imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
1018  imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -1000);
1019  }
1020 
1021  }
1022 
1023 
1024 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1025  Negative
1026 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1027 
1028  public function negative()
1029  # Author: Jarrod Oberto
1030  # Date: 07-05-2011
1031  # Purpose: Make image negative
1032  # Param in: n/a
1033  # Param out:
1034  # Reference:
1035  # Notes:
1036  #
1037  {
1038  if ($this->imageResized) {
1039 
1040  imagefilter($this->imageResized, IMG_FILTER_NEGATE);
1041  }
1042 
1043  }
1044 
1045 
1046 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1047  Sepia
1048 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1049 
1050  public function sepia()
1051  # Author: Jarrod Oberto
1052  # Date: 07-05-2011
1053  # Purpose: Make image sepia
1054  # Param in: n/a
1055  # Param out:
1056  # Reference:
1057  # Notes:
1058  #
1059  {
1060  if ($this->imageResized) {
1061  imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
1062  imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, -10);
1063  imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -20);
1064  imagefilter($this->imageResized, IMG_FILTER_COLORIZE, 60, 30, -15);
1065  }
1066  }
1067 
1068  ## --------------------------------------------------------
1069 
1070  public function sepia2()
1071 
1072  {
1073  if ($this->imageResized) {
1074 
1075  $total = imagecolorstotal( $this->imageResized );
1076  for ( $i = 0; $i < $total; $i++ ) {
1077  $index = imagecolorsforindex( $this->imageResized, $i );
1078  $red = ( $index["red"] * 0.393 + $index["green"] * 0.769 + $index["blue"] * 0.189 ) / 1.351;
1079  $green = ( $index["red"] * 0.349 + $index["green"] * 0.686 + $index["blue"] * 0.168 ) / 1.203;
1080  $blue = ( $index["red"] * 0.272 + $index["green"] * 0.534 + $index["blue"] * 0.131 ) / 2.140;
1081  imagecolorset( $this->imageResized, $i, $red, $green, $blue );
1082  }
1083 
1084 
1085  }
1086  }
1087 
1088 
1089 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1090  Vintage
1091 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1092 
1093  public function vintage()
1094  # Alias of gd_filter_monopin
1095  {
1096  $this->gd_filter_vintage();
1097  }
1098 
1099 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1100  Presets By Marc Hibbins
1101 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1102 
1103 
1105  public function gd_filter_monopin()
1106  {
1107 
1108  if ($this->imageResized) {
1109  imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
1110  imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, -15);
1111  imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -15);
1112  $this->imageResized = $this->gd_apply_overlay($this->imageResized, 'vignette', 100);
1113  }
1114  }
1115 
1116  ## --------------------------------------------------------
1117 
1118  public function gd_filter_vintage()
1119  {
1120  if ($this->imageResized) {
1121  $this->imageResized = $this->gd_apply_overlay($this->imageResized, 'vignette', 45);
1122  imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, 20);
1123  imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -35);
1124  imagefilter($this->imageResized, IMG_FILTER_COLORIZE, 60, -10, 35);
1125  imagefilter($this->imageResized, IMG_FILTER_SMOOTH, 7);
1126  $this->imageResized = $this->gd_apply_overlay($this->imageResized, 'scratch', 10);
1127  }
1128  }
1129 
1130  ## --------------------------------------------------------
1131 
1133  private function gd_apply_overlay($im, $type, $amount)
1134  #
1135  # Original Author: Marc Hibbins
1136  # License: Attribution-ShareAlike 3.0
1137  # Purpose:
1138  # Params in:
1139  # Params out:
1140  # Notes:
1141  #
1142  {
1143  $width = imagesx($im);
1144  $height = imagesy($im);
1145  $filter = imagecreatetruecolor($width, $height);
1146 
1147  imagealphablending($filter, false);
1148  imagesavealpha($filter, true);
1149 
1150  $transparent = imagecolorallocatealpha($filter, 255, 255, 255, 127);
1151  imagefilledrectangle($filter, 0, 0, $width, $height, $transparent);
1152 
1153  // *** Resize overlay
1154  $overlay = $this->filterOverlayPath . '/' . $type . '.png';
1155  $png = imagecreatefrompng($overlay);
1156  imagecopyresampled($filter, $png, 0, 0, 0, 0, $width, $height, imagesx($png), imagesy($png));
1157 
1158  $comp = imagecreatetruecolor($width, $height);
1159  imagecopy($comp, $im, 0, 0, 0, 0, $width, $height);
1160  imagecopy($comp, $filter, 0, 0, 0, 0, $width, $height);
1161  imagecopymerge($im, $comp, 0, 0, 0, 0, $width, $height, $amount);
1162 
1163  imagedestroy($comp);
1164  return $im;
1165  }
1166 
1167 
1168 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1169  Colorise
1170 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1171 
1172  public function image_colorize($rgb) {
1173  imageTrueColorToPalette($this->imageResized,true,256);
1174  $numColors = imageColorsTotal($this->imageResized);
1175 
1176  for ($x = 0; $x < $numColors; $x++) {
1177  list($r,$g,$b) = array_values(imageColorsForIndex($this->imageResized,$x));
1178 
1179  // calculate grayscale in percent
1180  $grayscale = ($r + $g + $b) / 3 / 0xff;
1181 
1182  imageColorSet($this->imageResized,$x,
1183  $grayscale * $rgb[0],
1184  $grayscale * $rgb[1],
1185  $grayscale * $rgb[2]
1186  );
1187 
1188  }
1189 
1190  return true;
1191  }
1192 
1193 
1194 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1195  Reflection
1196 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1197 
1198  public function addReflection($reflectionHeight = 50, $startingTransparency = 30, $inside = false, $bgColor = '#fff', $stretch=false, $divider = 0)
1199  {
1200 
1201  // *** Convert color
1202  $rgbArray = $this->formatColor($bgColor);
1203  $r = $rgbArray['r'];
1204  $g = $rgbArray['g'];
1205  $b = $rgbArray['b'];
1206 
1207  $im = $this->imageResized;
1208  $li = imagecreatetruecolor($this->width, 1);
1209 
1210  $bgc = imagecolorallocate($li, $r, $g, $b);
1211  imagefilledrectangle($li, 0, 0, $this->width, 1, $bgc);
1212 
1213  $bg = imagecreatetruecolor($this->width, $reflectionHeight);
1214  $wh = imagecolorallocate($im, 255, 255, 255);
1215 
1216  $im = imagerotate($im, -180, $wh);
1217  imagecopyresampled($bg, $im, 0, 0, 0, 0, $this->width, $this->height, $this->width, $this->height);
1218 
1219  $im = $bg;
1220 
1221  $bg = imagecreatetruecolor($this->width, $reflectionHeight);
1222 
1223  for ($x = 0; $x < $this->width; $x++) {
1224  imagecopy($bg, $im, $x, 0, $this->width-$x -1, 0, 1, $reflectionHeight);
1225  }
1226  $im = $bg;
1227 
1228  $transaprencyAmount = $this->invertTransparency($startingTransparency, 100);
1229 
1230 
1231  // *** Fade
1232  if ($stretch) {
1233  $step = 100/($reflectionHeight + $startingTransparency);
1234  } else{
1235  $step = 100/$reflectionHeight;
1236  }
1237  for($i=0; $i<=$reflectionHeight; $i++){
1238 
1239  if($startingTransparency>100) $startingTransparency = 100;
1240  if($startingTransparency< 1) $startingTransparency = 1;
1241  imagecopymerge($bg, $li, 0, $i, 0, 0, $this->width, 1, $startingTransparency);
1242  $startingTransparency+=$step;
1243  }
1244 
1245  // *** Apply fade
1246  imagecopymerge($im, $li, 0, 0, 0, 0, $this->width, $divider, 100); // Divider
1247 
1248 
1249  // *** width, height of reflection.
1250  $x = imagesx($im);
1251  $y = imagesy($im);
1252 
1253 
1254  // *** Determines if the reflection should be displayed inside or outside the image
1255  if ($inside) {
1256 
1257  // Create new blank image with sizes.
1258  $final = imagecreatetruecolor($this->width, $this->height);
1259 
1260  imagecopymerge ($final, $this->imageResized, 0, 0, 0, $reflectionHeight, $this->width, $this->height - $reflectionHeight, 100);
1261  imagecopymerge ($final, $im, 0, $this->height - $reflectionHeight, 0, 0, $x, $y, 100);
1262 
1263  } else {
1264 
1265  // Create new blank image with sizes.
1266  $final = imagecreatetruecolor($this->width, $this->height + $y);
1267 
1268  imagecopymerge ($final, $this->imageResized, 0, 0, 0, 0, $this->width, $this->height, 100);
1269  imagecopymerge ($final, $im, 0, $this->height, 0, 0, $x, $y, 100);
1270  }
1271 
1272  $this->imageResized = $final;
1273 
1274  imagedestroy($li);
1275  imagedestroy($im);
1276  }
1277 
1278 
1279 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1280  Rotate
1281 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1282 
1283  public function rotate($value = 90, $bgColor = 'transparent')
1284  # Author: Jarrod Oberto
1285  # Date: 07-05-2011
1286  # Purpose: Rotate image
1287  # Param in: (mixed) $degrees: (int) number of degress to rotate image
1288  # (str) param "left": rotate left
1289  # (str) param "right": rotate right
1290  # (str) param "upside": upside-down image
1291  # Param out:
1292  # Reference:
1293  # Notes: The default direction of imageRotate() is counter clockwise.
1294  #
1295  {
1296  if ($this->imageResized) {
1297 
1298  if (is_integer($value)) {
1299  $degrees = $value;
1300  }
1301 
1302  // *** Convert color
1303  $rgbArray = $this->formatColor($bgColor);
1304  $r = $rgbArray['r'];
1305  $g = $rgbArray['g'];
1306  $b = $rgbArray['b'];
1307  if (isset($rgbArray['a'])) {$a = $rgbArray['a']; }
1308 
1309  if (is_string($value)) {
1310 
1311  $value = fix_strtolower($value);
1312 
1313  switch ($value) {
1314  case 'left':
1315  $degrees = 90;
1316  break;
1317  case 'right':
1318  $degrees = 270;
1319  break;
1320  case 'upside':
1321  $degrees = 180;
1322  break;
1323  default:
1324  break;
1325  }
1326 
1327  }
1328 
1329  // *** The default direction of imageRotate() is counter clockwise
1330  // * This makes it clockwise
1331  $degrees = 360 - $degrees;
1332 
1333  // *** Create background color
1334  $bg = ImageColorAllocateAlpha($this->imageResized, $r, $g, $b, $a);
1335 
1336  // *** Fill with background
1337  ImageFill($this->imageResized, 0, 0 , $bg);
1338 
1339  // *** Rotate
1340  $this->imageResized = imagerotate($this->imageResized, $degrees, $bg); // Rotate 45 degrees and allocated the transparent colour as the one to make transparent (obviously)
1341 
1342  // Ensure alpha transparency
1343  ImageSaveAlpha($this->imageResized,true);
1344 
1345  }
1346  }
1347 
1348 
1349 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1350  Round corners
1351 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1352 
1353  public function roundCorners($radius = 5, $bgColor = 'transparent')
1354  # Author: Jarrod Oberto
1355  # Date: 19-05-2011
1356  # Purpose: Create rounded corners on your image
1357  # Param in: (int) radius = the amount of curvature
1358  # (mixed) $bgColor = the corner background color
1359  # Param out: n/a
1360  # Reference:
1361  # Notes:
1362  #
1363  {
1364 
1365  // *** Check if the user wants transparency
1366  $isTransparent = false;
1367  if (!is_array($bgColor)) {
1368  if (fix_strtolower($bgColor) == 'transparent') {
1369  $isTransparent = true;
1370  }
1371  }
1372 
1373 
1374  // *** If we use transparency, we need to color our curved mask with a unique color
1375  if ($isTransparent) {
1376  $bgColor = $this->findUnusedGreen();
1377  }
1378 
1379  // *** Convert color
1380  $rgbArray = $this->formatColor($bgColor);
1381  $r = $rgbArray['r'];
1382  $g = $rgbArray['g'];
1383  $b = $rgbArray['b'];
1384  if (isset($rgbArray['a'])) {$a = $rgbArray['a']; }
1385 
1386 
1387 
1388  // *** Create top-left corner mask (square)
1389  $cornerImg = imagecreatetruecolor($radius, $radius);
1390  //$cornerImg = imagecreate($radius, $radius);
1391 
1392  //imagealphablending($cornerImg, true);
1393  //imagesavealpha($cornerImg, true);
1394 
1395  //imagealphablending($this->imageResized, false);
1396  //imagesavealpha($this->imageResized, true);
1397 
1398  // *** Give it a color
1399  $maskColor = imagecolorallocate($cornerImg, 0, 0, 0);
1400 
1401 
1402 
1403  // *** Replace the mask color (black) to transparent
1404  imagecolortransparent($cornerImg, $maskColor);
1405 
1406 
1407 
1408  // *** Create the image background color
1409  $imagebgColor = imagecolorallocate($cornerImg, $r, $g, $b);
1410 
1411 
1412 
1413  // *** Fill the corner area to the user defined color
1414  imagefill($cornerImg, 0, 0, $imagebgColor);
1415 
1416 
1417  imagefilledellipse($cornerImg, $radius, $radius, $radius * 2, $radius * 2, $maskColor );
1418 
1419 
1420  // *** Map to top left corner
1421  imagecopymerge($this->imageResized, $cornerImg, 0, 0, 0, 0, $radius, $radius, 100); #tl
1422 
1423  // *** Map rounded corner to other corners by rotating and applying the mask
1424  $cornerImg = imagerotate($cornerImg, 90, 0);
1425  imagecopymerge($this->imageResized, $cornerImg, 0, $this->height - $radius, 0, 0, $radius, $radius, 100); #bl
1426 
1427  $cornerImg = imagerotate($cornerImg, 90, 0);
1428  imagecopymerge($this->imageResized, $cornerImg, $this->width - $radius, $this->height - $radius, 0, 0, $radius, $radius, 100); #br
1429 
1430  $cornerImg = imagerotate($cornerImg, 90, 0);
1431  imagecopymerge($this->imageResized, $cornerImg, $this->width - $radius, 0, 0, 0, $radius, $radius, 100); #tr
1432 
1433 
1434  // *** If corners are to be transparent, we fill our chromakey color as transparent.
1435  if ($isTransparent) {
1436  //imagecolortransparent($this->imageResized, $imagebgColor);
1437  $this->imageResized = $this->transparentImage($this->imageResized);
1438  imagesavealpha($this->imageResized, true);
1439  }
1440 
1441  }
1442 
1443 
1444 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1445  Shadow
1446 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1447 
1448  public function addShadow($shadowAngle=45, $blur=15, $bgColor='transparent')
1449  #
1450  # Author: Jarrod Oberto (Adapted from Pascal Naidon)
1451  # Ref: http://www.les-stooges.org/pascal/webdesign/vignettes/index.php?la=en
1452  # Purpose: Add a drop shadow to your image
1453  # Params in: (int) $angle: the angle of the shadow
1454  # (int) $blur: the blur distance
1455  # (mixed) $bgColor: the color of the background
1456  # Params out:
1457  # Notes:
1458  #
1459  {
1460  // *** A higher number results in a smoother shadow
1461  define('STEPS', $blur*2);
1462 
1463  // *** Set the shadow distance
1464  $shadowDistance = $blur*0.25;
1465 
1466  // *** Set blur width and height
1467  $blurWidth = $blurHeight = $blur;
1468 
1469 
1470  if ($shadowAngle == 0) {
1471  $distWidth = 0;
1472  $distHeight = 0;
1473  } else {
1474  $distWidth = $shadowDistance * cos(deg2rad($shadowAngle));
1475  $distHeight = $shadowDistance * sin(deg2rad($shadowAngle));
1476  }
1477 
1478 
1479  // *** Convert color
1480  if (fix_strtolower($bgColor) != 'transparent') {
1481  $rgbArray = $this->formatColor($bgColor);
1482  $r0 = $rgbArray['r'];
1483  $g0 = $rgbArray['g'];
1484  $b0 = $rgbArray['b'];
1485  }
1486 
1487 
1489  $width = $this->width;
1490  $height = $this->height;
1491 
1492 
1493  $newImage = imagecreatetruecolor($width, $height);
1494  imagecopyresampled($newImage, $image, 0, 0, 0, 0, $width, $height, $width, $height);
1495 
1496 
1497  // *** RGB
1498  $rgb = imagecreatetruecolor($width+$blurWidth,$height+$blurHeight);
1499  $colour = imagecolorallocate($rgb, 0, 0, 0);
1500  imagefilledrectangle($rgb, 0, 0, $width+$blurWidth, $height+$blurHeight, $colour);
1501  $colour = imagecolorallocate($rgb, 255, 255, 255);
1502  //imagefilledrectangle($rgb, $blurWidth*0.5-$distWidth, $blurHeight*0.5-$distHeight, $width+$blurWidth*0.5-$distWidth, $height+$blurWidth*0.5-$distHeight, $colour);
1503  imagefilledrectangle($rgb, $blurWidth*0.5-$distWidth, $blurHeight*0.5-$distHeight, $width+$blurWidth*0.5-$distWidth, $height+$blurWidth*0.5-$distHeight, $colour);
1504  //imagecopymerge($rgb, $newImage, 1+$blurWidth*0.5-$distWidth, 1+$blurHeight*0.5-$distHeight, 0,0, $width, $height, 100);
1505  imagecopymerge($rgb, $newImage, $blurWidth*0.5-$distWidth, $blurHeight*0.5-$distHeight, 0,0, $width+$blurWidth, $height+$blurHeight, 100);
1506 
1507 
1508  // *** Shadow (alpha)
1509  $shadow = imagecreatetruecolor($width+$blurWidth,$height+$blurHeight);
1510  imagealphablending($shadow, false);
1511  $colour = imagecolorallocate($shadow, 0, 0, 0);
1512  imagefilledrectangle($shadow, 0, 0, $width+$blurWidth, $height+$blurHeight, $colour);
1513 
1514 
1515  for($i=0;$i<=STEPS;$i++) {
1516 
1517  $t = ((1.0*$i)/STEPS);
1518  $intensity = 255*$t*$t;
1519 
1520  $colour = imagecolorallocate($shadow, $intensity, $intensity, $intensity);
1521  $points = array(
1522  $blurWidth*$t, $blurHeight, // Point 1 (x, y)
1523  $blurWidth, $blurHeight*$t, // Point 2 (x, y)
1524  $width, $blurHeight*$t, // Point 3 (x, y)
1525  $width+$blurWidth*(1-$t), $blurHeight, // Point 4 (x, y)
1526  $width+$blurWidth*(1-$t), $height, // Point 5 (x, y)
1527  $width, $height+$blurHeight*(1-$t), // Point 6 (x, y)
1528  $blurWidth, $height+$blurHeight*(1-$t), // Point 7 (x, y)
1529  $blurWidth*$t, $height // Point 8 (x, y)
1530  );
1531  imagepolygon($shadow, $points, 8, $colour);
1532  }
1533 
1534  for($i=0;$i<=STEPS;$i++) {
1535 
1536  $t = ((1.0*$i)/STEPS);
1537  $intensity = 255*$t*$t;
1538 
1539  $colour = imagecolorallocate($shadow, $intensity, $intensity, $intensity);
1540  imagefilledarc($shadow, $blurWidth-1, $blurHeight-1, 2*(1-$t)*$blurWidth, 2*(1-$t)*$blurHeight, 180, 268, $colour, IMG_ARC_PIE);
1541  imagefilledarc($shadow, $width, $blurHeight-1, 2*(1-$t)*$blurWidth, 2*(1-$t)*$blurHeight, 270, 358, $colour, IMG_ARC_PIE);
1542  imagefilledarc($shadow, $width, $height, 2*(1-$t)*$blurWidth, 2*(1-$t)*$blurHeight, 0, 90, $colour, IMG_ARC_PIE);
1543  imagefilledarc($shadow, $blurWidth-1, $height, 2*(1-$t)*$blurWidth, 2*(1-$t)*$blurHeight, 90, 180, $colour, IMG_ARC_PIE);
1544  }
1545 
1546 
1547  $colour = imagecolorallocate($shadow, 255, 255, 255);
1548  imagefilledrectangle($shadow, $blurWidth, $blurHeight, $width, $height, $colour);
1549  imagefilledrectangle($shadow, $blurWidth*0.5-$distWidth, $blurHeight*0.5-$distHeight, $width+$blurWidth*0.5-1-$distWidth, $height+$blurHeight*0.5-1-$distHeight, $colour);
1550 
1551 
1552  // *** The magic
1553  imagealphablending($rgb, false);
1554 
1555  for ($theX=0;$theX<imagesx($rgb);$theX++){
1556  for ($theY=0;$theY<imagesy($rgb);$theY++){
1557 
1558  // *** Get the RGB values for every pixel of the RGB image
1559  $colArray = imagecolorat($rgb,$theX,$theY);
1560  $r = ($colArray >> 16) & 0xFF;
1561  $g = ($colArray >> 8) & 0xFF;
1562  $b = $colArray & 0xFF;
1563 
1564  // *** Get the alpha value for every pixel of the shadow image
1565  $colArray = imagecolorat($shadow,$theX,$theY);
1566  $a = $colArray & 0xFF;
1567  $a = 127-floor($a/2);
1568  $t = $a/128.0;
1569 
1570  // *** Create color
1571  if(fix_strtolower($bgColor) == 'transparent') {
1572  $myColour = imagecolorallocatealpha($rgb,$r,$g,$b,$a);
1573  } else {
1574  $myColour = imagecolorallocate($rgb,$r*(1.0-$t)+$r0*$t,$g*(1.0-$t)+$g0*$t,$b*(1.0-$t)+$b0*$t);
1575  }
1576 
1577  // *** Add color to new rgb image
1578  imagesetpixel($rgb, $theX, $theY, $myColour);
1579  }
1580  }
1581 
1582  imagealphablending($rgb, true);
1583  imagesavealpha($rgb, true);
1584 
1585  $this->imageResized = $rgb;
1586 
1587  imagedestroy($image);
1588  imagedestroy($newImage);
1589  imagedestroy($shadow);
1590  }
1591 
1592 
1593 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1594  Add Caption Box
1595 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1596 
1597  public function addCaptionBox($side='b', $thickness=50, $padding=0, $bgColor='#000', $transaprencyAmount=30)
1598  #
1599  # Author: Jarrod Oberto
1600  # Date: 26 May 2011
1601  # Purpose: Add a caption box
1602  # Params in: (str) $side: the side to add the caption box (t, r, b, or l).
1603  # (int) $thickness: how thick you want the caption box to be.
1604  # (mixed) $bgColor: The color of the caption box.
1605  # (int) $transaprencyAmount: The amount of transparency to be
1606  # applied.
1607  # Params out: n/a
1608  # Notes:
1609  #
1610  {
1611  $side = fix_strtolower($side);
1612 
1613  // *** Convert color
1614  $rgbArray = $this->formatColor($bgColor);
1615  $r = $rgbArray['r'];
1616  $g = $rgbArray['g'];
1617  $b = $rgbArray['b'];
1618 
1619  $positionArray = $this->calculateCaptionBoxPosition($side, $thickness, $padding);
1620 
1621  // *** Store incase we want to use method addTextToCaptionBox()
1622  $this->captionBoxPositionArray = $positionArray;
1623 
1624 
1625  $transaprencyAmount = $this->invertTransparency($transaprencyAmount, 127, false);
1626  $transparent = imagecolorallocatealpha($this->imageResized, $r, $g, $b, $transaprencyAmount);
1627  imagefilledrectangle($this->imageResized, $positionArray['x1'], $positionArray['y1'], $positionArray['x2'], $positionArray['y2'], $transparent);
1628  }
1629 
1630  ## --------------------------------------------------------
1631 
1632  public function addTextToCaptionBox($text, $fontColor='#fff', $fontSize = 12, $angle = 0, $font = null)
1633  #
1634  # Author: Jarrod Oberto
1635  # Date: 03 Aug 11
1636  # Purpose: Simplify adding text to a caption box by automatically
1637  # locating the center of the caption box
1638  # Params in: The usually text paams (less a couple)
1639  # Params out: n/a
1640  # Notes:
1641  #
1642  {
1643 
1644  // *** Get the caption box measurements
1645  if (count($this->captionBoxPositionArray) == 4) {
1646  $x1 = $this->captionBoxPositionArray['x1'];
1647  $x2 = $this->captionBoxPositionArray['x2'];
1648  $y1 = $this->captionBoxPositionArray['y1'];
1649  $y2 = $this->captionBoxPositionArray['y2'];
1650  } else {
1651  if ($this->debug) { throw new Exception('No caption box found.'); }else{ return false; }
1652  }
1653 
1654 
1655  // *** Get text font
1656  $font = $this->getTextFont($font);
1657 
1658  // *** Get text size
1659  $textSizeArray = $this->getTextSize($fontSize, $angle, $font, $text);
1660  $textWidth = $textSizeArray['width'];
1661  $textHeight = $textSizeArray['height'];
1662 
1663  // *** Find the width/height middle points
1664  $boxXMiddle = (($x2 - $x1) / 2);
1665  $boxYMiddle = (($y2 - $y1) / 2);
1666 
1667  // *** Box middle - half the text width/height
1668  $xPos = ($x1 + $boxXMiddle) - ($textWidth/2);
1669  $yPos = ($y1 + $boxYMiddle) - ($textHeight/2);
1670 
1671  $pos = $xPos . 'x' . $yPos;
1672 
1673  $this->addText($text, $pos, $padding = 0, $fontColor, $fontSize, $angle, $font);
1674 
1675  }
1676 
1677  ## --------------------------------------------------------
1678 
1679  private function calculateCaptionBoxPosition($side, $thickness, $padding)
1680  {
1681  $positionArray = array();
1682 
1683  switch ($side) {
1684  case 't':
1685  $positionArray['x1'] = 0;
1686  $positionArray['y1'] = $padding;
1687  $positionArray['x2'] = $this->width;
1688  $positionArray['y2'] = $thickness + $padding;
1689  break;
1690  case 'r':
1691  $positionArray['x1'] = $this->width - $thickness - $padding;
1692  $positionArray['y1'] = 0;
1693  $positionArray['x2'] = $this->width - $padding;
1694  $positionArray['y2'] = $this->height;
1695  break;
1696  case 'b':
1697  $positionArray['x1'] = 0;
1698  $positionArray['y1'] = $this->height - $thickness - $padding;
1699  $positionArray['x2'] = $this->width;
1700  $positionArray['y2'] = $this->height - $padding;
1701  break;
1702  case 'l':
1703  $positionArray['x1'] = $padding;
1704  $positionArray['y1'] = 0;
1705  $positionArray['x2'] = $thickness + $padding;
1706  $positionArray['y2'] = $this->height;
1707  break;
1708 
1709  default:
1710  break;
1711  }
1712 
1713  return $positionArray;
1714 
1715  }
1716 
1717 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1718  Get EXIF Data
1719 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1720 
1721  public function getExif($debug=false)
1722  # Author: Jarrod Oberto
1723  # Date: 07-05-2011
1724  # Purpose: Get image EXIF data
1725  # Param in: n/a
1726  # Param out: An associate array of EXIF data
1727  # Reference:
1728  # Notes:
1729  # 23 May 13 : added orientation flag -jco
1730  #
1731  {
1732 
1733  if (!$this->debug || !$debug) { $debug = false; }
1734 
1735  // *** Check all is good - check the EXIF library exists and the file exists, too.
1736  if (!$this->testEXIFInstalled()) { if ($debug) { throw new Exception('The EXIF Library is not installed.'); }else{ return array(); }};
1737  if (!file_exists($this->fileName)) { if ($debug) { throw new Exception('Image not found.'); }else{ return array(); }};
1738  if ($this->fileExtension != '.jpg') { if ($debug) { throw new Exception('Metadata not supported for this image type.'); }else{ return array(); }};
1739  $exifData = exif_read_data($this->fileName, 'IFD0');
1740 
1741  // *** Format the apperture value
1742  $ev = $exifData['ApertureValue'];
1743  $apPeicesArray = explode('/', $ev);
1744  if (count($apPeicesArray) == 2) {
1745  $apertureValue = round($apPeicesArray[0] / $apPeicesArray[1], 2, PHP_ROUND_HALF_DOWN) . ' EV';
1746  } else { $apertureValue = '';}
1747 
1748  // *** Format the focal length
1749  $focalLength = $exifData['FocalLength'];
1750  $flPeicesArray = explode('/', $focalLength);
1751  if (count($flPeicesArray) == 2) {
1752  $focalLength = $flPeicesArray[0] / $flPeicesArray[1] . '.0 mm';
1753  } else { $focalLength = '';}
1754 
1755  // *** Format fNumber
1756  $fNumber = $exifData['FNumber'];
1757  $fnPeicesArray = explode('/', $fNumber);
1758  if (count($fnPeicesArray) == 2) {
1759  $fNumber = $fnPeicesArray[0] / $fnPeicesArray[1];
1760  } else { $fNumber = '';}
1761 
1762  // *** Resolve ExposureProgram
1763  if (isset($exifData['ExposureProgram'])) { $ep = $exifData['ExposureProgram']; }
1764  if (isset($ep)) { $ep = $this->resolveExposureProgram($ep); }
1765 
1766 
1767  // *** Resolve MeteringMode
1768  $mm = $exifData['MeteringMode'];
1769  $mm = $this->resolveMeteringMode($mm);
1770 
1771  // *** Resolve Flash
1772  $flash = $exifData['Flash'];
1773  $flash = $this->resolveFlash($flash);
1774 
1775 
1776  if (isset($exifData['Make'])) {
1777  $exifDataArray['make'] = $exifData['Make'];
1778  } else { $exifDataArray['make'] = ''; }
1779 
1780  if (isset($exifData['Model'])) {
1781  $exifDataArray['model'] = $exifData['Model'];
1782  } else { $exifDataArray['model'] = ''; }
1783 
1784  if (isset($exifData['DateTime'])) {
1785  $exifDataArray['date'] = $exifData['DateTime'];
1786  } else { $exifDataArray['date'] = ''; }
1787 
1788  if (isset($exifData['ExposureTime'])) {
1789  $exifDataArray['exposure time'] = $exifData['ExposureTime'] . ' sec.';
1790  } else { $exifDataArray['exposure time'] = ''; }
1791 
1792  if ($apertureValue != '') {
1793  $exifDataArray['aperture value'] = $apertureValue;
1794  } else { $exifDataArray['aperture value'] = ''; }
1795 
1796  if (isset($exifData['COMPUTED']['ApertureFNumber'])) {
1797  $exifDataArray['f-stop'] = $exifData['COMPUTED']['ApertureFNumber'];
1798  } else { $exifDataArray['f-stop'] = ''; }
1799 
1800  if (isset($exifData['FNumber'])) {
1801  $exifDataArray['fnumber'] = $exifData['FNumber'];
1802  } else { $exifDataArray['fnumber'] = ''; }
1803 
1804  if ($fNumber != '') {
1805  $exifDataArray['fnumber value'] = $fNumber;
1806  } else { $exifDataArray['fnumber value'] = ''; }
1807 
1808  if (isset($exifData['ISOSpeedRatings'])) {
1809  $exifDataArray['iso'] = $exifData['ISOSpeedRatings'];
1810  } else { $exifDataArray['iso'] = ''; }
1811 
1812  if ($focalLength != '') {
1813  $exifDataArray['focal length'] = $focalLength;
1814  } else { $exifDataArray['focal length'] = ''; }
1815 
1816  if (isset($ep)) {
1817  $exifDataArray['exposure program'] = $ep;
1818  } else { $exifDataArray['exposure program'] = ''; }
1819 
1820  if ($mm != '') {
1821  $exifDataArray['metering mode'] = $mm;
1822  } else { $exifDataArray['metering mode'] = ''; }
1823 
1824  if ($flash != '') {
1825  $exifDataArray['flash status'] = $flash;
1826  } else { $exifDataArray['flash status'] = ''; }
1827 
1828  if (isset($exifData['Artist'])) {
1829  $exifDataArray['creator'] = $exifData['Artist'] ;
1830  } else { $exifDataArray['creator'] = ''; }
1831 
1832  if (isset($exifData['Copyright'])) {
1833  $exifDataArray['copyright'] = $exifData['Copyright'];
1834  } else { $exifDataArray['copyright'] = ''; }
1835 
1836  // *** Orientation
1837  if (isset($exifData['Orientation'])) {
1838  $exifDataArray['orientation'] = $exifData['Orientation'];
1839  } else { $exifDataArray['orientation'] = ''; }
1840 
1841  return $exifDataArray;
1842  }
1843 
1844  ## --------------------------------------------------------
1845 
1846  private function resolveExposureProgram($ep)
1847  {
1848  switch ($ep) {
1849  case 0:
1850  $ep = '';
1851  break;
1852  case 1:
1853  $ep = 'manual';
1854  break;
1855  case 2:
1856  $ep = 'normal program';
1857  break;
1858  case 3:
1859  $ep = 'aperture priority';
1860  break;
1861  case 4:
1862  $ep = 'shutter priority';
1863  break;
1864  case 5:
1865  $ep = 'creative program';
1866  break;
1867  case 6:
1868  $ep = 'action program';
1869  break;
1870  case 7:
1871  $ep = 'portrait mode';
1872  break;
1873  case 8:
1874  $ep = 'landscape mode';
1875  break;
1876 
1877  default:
1878  break;
1879  }
1880 
1881  return $ep;
1882  }
1883 
1884  ## --------------------------------------------------------
1885 
1886  private function resolveMeteringMode($mm)
1887  {
1888  switch ($mm) {
1889  case 0:
1890  $mm = 'unknown';
1891  break;
1892  case 1:
1893  $mm = 'average';
1894  break;
1895  case 2:
1896  $mm = 'center weighted average';
1897  break;
1898  case 3:
1899  $mm = 'spot';
1900  break;
1901  case 4:
1902  $mm = 'multi spot';
1903  break;
1904  case 5:
1905  $mm = 'pattern';
1906  break;
1907  case 6:
1908  $mm = 'partial';
1909  break;
1910  case 255:
1911  $mm = 'other';
1912  break;
1913 
1914  default:
1915  break;
1916  }
1917 
1918  return $mm;
1919  }
1920 
1921  ## --------------------------------------------------------
1922 
1923  private function resolveFlash($flash)
1924  {
1925  switch ($flash) {
1926  case 0:
1927  $flash = 'flash did not fire';
1928  break;
1929  case 1:
1930  $flash = 'flash fired';
1931  break;
1932  case 5:
1933  $flash = 'strobe return light not detected';
1934  break;
1935  case 7:
1936  $flash = 'strobe return light detected';
1937  break;
1938  case 9:
1939  $flash = 'flash fired, compulsory flash mode';
1940  break;
1941  case 13:
1942  $flash = 'flash fired, compulsory flash mode, return light not detected';
1943  break;
1944  case 15:
1945  $flash = 'flash fired, compulsory flash mode, return light detected';
1946  break;
1947  case 16:
1948  $flash = 'flash did not fire, compulsory flash mode';
1949  break;
1950  case 24:
1951  $flash = 'flash did not fire, auto mode';
1952  break;
1953  case 25:
1954  $flash = 'flash fired, auto mode';
1955  break;
1956  case 29:
1957  $flash = 'flash fired, auto mode, return light not detected';
1958  break;
1959  case 31:
1960  $flash = 'flash fired, auto mode, return light detected';
1961  break;
1962  case 32:
1963  $flash = 'no flash function';
1964  break;
1965  case 65:
1966  $flash = 'flash fired, red-eye reduction mode';
1967  break;
1968  case 69:
1969  $flash = 'flash fired, red-eye reduction mode, return light not detected';
1970  break;
1971  case 71:
1972  $flash = 'flash fired, red-eye reduction mode, return light detected';
1973  break;
1974  case 73:
1975  $flash = 'flash fired, compulsory flash mode, red-eye reduction mode';
1976  break;
1977  case 77:
1978  $flash = 'flash fired, compulsory flash mode, red-eye reduction mode, return light not detected';
1979  break;
1980  case 79:
1981  $flash = 'flash fired, compulsory flash mode, red-eye reduction mode, return light detected';
1982  break;
1983  case 89:
1984  $flash = 'flash fired, auto mode, red-eye reduction mode';
1985  break;
1986  case 93:
1987  $flash = 'flash fired, auto mode, return light not detected, red-eye reduction mode';
1988  break;
1989  case 95:
1990  $flash = 'flash fired, auto mode, return light detected, red-eye reduction mode';
1991  break;
1992 
1993  default:
1994  break;
1995  }
1996 
1997  return $flash;
1998 
1999  }
2000 
2001 
2002 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
2003  Get IPTC Data
2004 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
2005 
2006 
2007 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
2008  Write IPTC Data
2009 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
2010 
2011  public function writeIPTCcaption($value)
2012  # Caption
2013  {
2014  $this->writeIPTC(120, $value);
2015  }
2016 
2017  ## --------------------------------------------------------
2018 
2019  public function writeIPTCwriter($value)
2020  {
2021  //$this->writeIPTC(65, $value);
2022  }
2023 
2024  ## --------------------------------------------------------
2025 
2026  private function writeIPTC($dat, $value)
2027  {
2028 
2029  # LIMIT TO JPG
2030 
2031  $caption_block = $this->iptc_maketag(2, $dat, $value);
2032  $image_string = iptcembed($caption_block, $this->fileName);
2033  file_put_contents('iptc.jpg', $image_string);
2034  }
2035 
2036 ## --------------------------------------------------------
2037 
2038  private function iptc_maketag($rec,$dat,$val)
2039  # Author: Thies C. Arntzen
2040  # Purpose: Function to format the new IPTC text
2041  # Param in: $rec: Application record. (We’re working with #2)
2042  # $dat: Index. (120 for caption, 118 for contact. See the IPTC IIM
2043  # specification:
2044  # http://www.iptc.org/std/IIM/4.1/specification/IIMV4.1.pdf
2045  # $val: Value/data/text. Make sure this is within the length
2046  # constraints of the IPTC IIM specification
2047  # Ref: http://blog.peterhaza.no/working-with-image-meta-data-in-exif-and-iptc-headers-from-php/
2048  # http://php.net/manual/en/function.iptcembed.php
2049  #
2050  {
2051  $len = strlen($val);
2052  if ($len < 0x8000)
2053  return chr(0x1c).chr($rec).chr($dat).
2054  chr($len >> 8).
2055  chr($len & 0xff).
2056  $val;
2057  else
2058  return chr(0x1c).chr($rec).chr($dat).
2059  chr(0x80).chr(0x04).
2060  chr(($len >> 24) & 0xff).
2061  chr(($len >> 16) & 0xff).
2062  chr(($len >> 8 ) & 0xff).
2063  chr(($len ) & 0xff).
2064  $val;
2065  }
2066 
2067 
2068 
2069 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
2070  Write XMP Data
2071 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
2072 
2073  //http://xmpphptoolkit.sourceforge.net/
2074 
2075 
2076 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
2077  Add Text
2078 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
2079 
2080  public function addText($text, $pos = '20x20', $padding = 0, $fontColor='#fff', $fontSize = 12, $angle = 0, $font = null)
2081  # Author: Jarrod Oberto
2082  # Date: 18-11-09
2083  # Purpose: Add text to an image
2084  # Param in:
2085  # Param out:
2086  # Reference: http://php.net/manual/en/function.imagettftext.php
2087  # Notes: Make sure you supply the font.
2088  #
2089  {
2090 
2091  // *** Convert color
2092  $rgbArray = $this->formatColor($fontColor);
2093  $r = $rgbArray['r'];
2094  $g = $rgbArray['g'];
2095  $b = $rgbArray['b'];
2096 
2097  // *** Get text font
2098  $font = $this->getTextFont($font);
2099 
2100  // *** Get text size
2101  $textSizeArray = $this->getTextSize($fontSize, $angle, $font, $text);
2102  $textWidth = $textSizeArray['width'];
2103  $textHeight = $textSizeArray['height'];
2104 
2105  // *** Find co-ords to place text
2106  $posArray = $this->calculatePosition($pos, $padding, $textWidth, $textHeight, false);
2107  $x = $posArray['width'];
2108  $y = $posArray['height'];
2109 
2110  $fontColor = imagecolorallocate($this->imageResized, $r, $g, $b);
2111 
2112  // *** Add text
2113  imagettftext($this->imageResized, $fontSize, $angle, $x, $y, $fontColor, $font, $text);
2114  }
2115 
2116  ## --------------------------------------------------------
2117 
2118  private function getTextFont($font)
2119  {
2120  // *** Font path (shou
2121  $fontPath = __DIR__ . '/' . $this->fontDir;
2122 
2123 
2124  // *** The below is/may be needed depending on your version (see ref)
2125  putenv('GDFONTPATH=' . realpath('.'));
2126 
2127  // *** Check if the passed in font exsits...
2128  if ($font == null || !file_exists($font)) {
2129 
2130  // *** ...If not, default to this font.
2131  $font = $fontPath . '/arimo.ttf';
2132 
2133  // *** Check our default font exists...
2134  if (!file_exists($font)) {
2135 
2136  // *** If not, return false
2137  if ($this->debug) { throw new Exception('Font not found'); }else{ return false; }
2138  }
2139  }
2140 
2141  return $font;
2142 
2143  }
2144 
2145  ## --------------------------------------------------------
2146 
2147  private function getTextSize($fontSize, $angle, $font, $text)
2148  {
2149 
2150  // *** Define box (so we can get the width)
2151  $box = @imageTTFBbox($fontSize, $angle, $font, $text);
2152 
2153  // *** Get width of text from dimensions
2154  $textWidth = abs($box[4] - $box[0]);
2155 
2156  // *** Get height of text from dimensions (should also be same as $fontSize)
2157  $textHeight = abs($box[5] - $box[1]);
2158 
2159  return array('height' => $textHeight, 'width' => $textWidth);
2160  }
2161 
2162 
2163 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
2164  Add Watermark
2165 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
2166 
2167  public function addWatermark($watermarkImage, $pos, $padding = 0, $opacity = 0)
2168  # Author: Jarrod Oberto
2169  # Date: 18-11-09
2170  # Purpose: Add watermark image
2171  # Param in: (str) $watermark: The watermark image
2172  # (str) $pos: Could be a pre-determined position such as:
2173  # tl = top left,
2174  # t = top (middle),
2175  # tr = top right,
2176  # l = left,
2177  # m = middle,
2178  # r = right,
2179  # bl = bottom left,
2180  # b = bottom (middle),
2181  # br = bottom right
2182  # Or, it could be a co-ordinate position such as: 50x100
2183  #
2184  # (int) $padding: If using a pre-determined position you can
2185  # adjust the padding from the edges by passing an amount
2186  # in pixels. If using co-ordinates, this value is ignored.
2187  # Param out:
2188  # Reference: http://www.php.net/manual/en/image.examples-watermark.php
2189  # Notes: Based on example in reference.
2190  #
2191  #
2192  {
2193 
2194  // Load the stamp and the photo to apply the watermark to
2195  $stamp = $this->openImage ($watermarkImage); # stamp
2196  $im = $this->imageResized; # photo
2197 
2198  // *** Get stamps width and height
2199  $sx = imagesx($stamp);
2200  $sy = imagesy($stamp);
2201 
2202  // *** Find co-ords to place image
2203  $posArray = $this->calculatePosition($pos, $padding, $sx, $sy);
2204  $x = $posArray['width'];
2205  $y = $posArray['height'];
2206 
2207  // *** Set watermark opacity
2208  if (fix_strtolower(strrchr($watermarkImage, '.')) == '.png') {
2209 
2210  $opacity = $this->invertTransparency($opacity, 100);
2211  $this->filterOpacity($stamp, $opacity);
2212  }
2213 
2214  // Copy the watermark image onto our photo
2215  imagecopy($im, $stamp, $x, $y, 0, 0, imagesx($stamp), imagesy($stamp));
2216 
2217  }
2218 
2219  ## --------------------------------------------------------
2220 
2221  private function calculatePosition($pos, $padding, $assetWidth, $assetHeight, $upperLeft = true)
2222  #
2223  # Author: Jarrod Oberto
2224  # Date: 08-05-11
2225  # Purpose: Calculate the x, y pixel cordinates of the asset to place
2226  # Params in: (str) $pos: Either something like: "tl", "l", "br" or an
2227  # exact position like: "100x50"
2228  # (int) $padding: The amount of padding from the edge. Only
2229  # used for the predefined $pos.
2230  # (int) $assetWidth: The width of the asset to add to the image
2231  # (int) $assetHeight: The height of the asset to add to the image
2232  # (bol) $upperLeft: if true, the asset will be positioned based
2233  # on the upper left x, y coords. If false, it means you're
2234  # using the lower left as the basepoint and this will
2235  # convert it to the upper left position
2236  # Params out:
2237  # NOTE: this is done from the UPPER left corner!! But will convert lower
2238  # left basepoints to upper left if $upperleft is set to false
2239  #
2240  #
2241  {
2242  $pos = fix_strtolower($pos);
2243 
2244  // *** If co-ords have been entered
2245  if (strstr($pos, 'x')) {
2246  $pos = str_replace(' ', '', $pos);
2247 
2248  $xyArray = explode('x', $pos);
2249  list($width, $height) = $xyArray;
2250 
2251  } else {
2252 
2253  switch ($pos) {
2254  case 'tl':
2255  $width = 0 + $padding;
2256  $height = 0 + $padding;
2257  break;
2258 
2259  case 't':
2260  $width = ($this->width / 2) - ($assetWidth / 2);
2261  $height = 0 + $padding;
2262  break;
2263 
2264  case 'tr':
2265  $width = $this->width - $assetWidth - $padding;
2266  $height = 0 + $padding;;
2267  break;
2268 
2269  case 'l':
2270  $width = 0 + $padding;
2271  $height = ($this->height / 2) - ($assetHeight / 2);
2272  break;
2273 
2274  case 'm':
2275  $width = ($this->width / 2) - ($assetWidth / 2);
2276  $height = ($this->height / 2) - ($assetHeight / 2);
2277  break;
2278 
2279  case 'r':
2280  $width = $this->width - $assetWidth - $padding;
2281  $height = ($this->height / 2) - ($assetHeight / 2);
2282  break;
2283 
2284  case 'bl':
2285  $width = 0 + $padding;
2286  $height = $this->height - $assetHeight - $padding;
2287  break;
2288 
2289  case 'b':
2290  $width = ($this->width / 2) - ($assetWidth / 2);
2291  $height = $this->height - $assetHeight - $padding;
2292  break;
2293 
2294  case 'br':
2295  $width = $this->width - $assetWidth - $padding;
2296  $height = $this->height - $assetHeight - $padding;
2297  break;
2298 
2299  default:
2300  $width = 0;
2301  $height = 0;
2302  break;
2303  }
2304  }
2305 
2306  if (!$upperLeft) {
2307  $height = $height + $assetHeight;
2308  }
2309 
2310  return array('width' => $width, 'height' => $height);
2311  }
2312 
2313 
2314  ## --------------------------------------------------------
2315 
2316  private function filterOpacity(&$img, $opacity = 75)
2317  #
2318  # Author: aiden dot mail at freemail dot hu
2319  # Author date: 29-03-08 08:16
2320  # Date added: 08-05-11
2321  # Purpose: Change opacity of image
2322  # Params in: $img: Image resource id
2323  # (int) $opacity: the opacity amount: 0-100, 100 being not opaque.
2324  # Params out: (bool) true on success, else false
2325  # Ref: http://www.php.net/manual/en/function.imagefilter.php#82162
2326  # Notes: png only
2327  #
2328  {
2329 
2330  if (!isset($opacity)) {
2331  return false;
2332  }
2333 
2334  if ($opacity == 100) {
2335  return true;
2336  }
2337 
2338  $opacity /= 100;
2339 
2340  //get image width and height
2341  $w = imagesx($img);
2342  $h = imagesy($img);
2343 
2344  //turn alpha blending off
2345  imagealphablending($img, false);
2346 
2347  //find the most opaque pixel in the image (the one with the smallest alpha value)
2348  $minalpha = 127;
2349  for ($x = 0; $x < $w; $x++)
2350  for ($y = 0; $y < $h; $y++) {
2351  $alpha = ( imagecolorat($img, $x, $y) >> 24 ) & 0xFF;
2352  if ($alpha < $minalpha) {
2353  $minalpha = $alpha;
2354  }
2355  }
2356 
2357  //loop through image pixels and modify alpha for each
2358  for ($x = 0; $x < $w; $x++) {
2359  for ($y = 0; $y < $h; $y++) {
2360  //get current alpha value (represents the TANSPARENCY!)
2361  $colorxy = imagecolorat($img, $x, $y);
2362  $alpha = ( $colorxy >> 24 ) & 0xFF;
2363  //calculate new alpha
2364  if ($minalpha !== 127) {
2365  $alpha = 127 + 127 * $opacity * ( $alpha - 127 ) / ( 127 - $minalpha );
2366  } else {
2367  $alpha += 127 * $opacity;
2368  }
2369  //get the color index with new alpha
2370  $alphacolorxy = imagecolorallocatealpha($img, ( $colorxy >> 16 ) & 0xFF, ( $colorxy >> 8 ) & 0xFF, $colorxy & 0xFF, $alpha);
2371  //set pixel with the new color + opacity
2372  if (!imagesetpixel($img, $x, $y, $alphacolorxy)) {
2373 
2374  return false;
2375  }
2376  }
2377  }
2378 
2379  return true;
2380  }
2381 
2382 ## --------------------------------------------------------
2383 
2384  private function openImage($file)
2385  # Author: Jarrod Oberto
2386  # Date: 27-02-08
2387  # Purpose:
2388  # Param in:
2389  # Param out: n/a
2390  # Reference:
2391  # Notes:
2392  #
2393  {
2394 
2395  if (!file_exists($file) && !$this->checkStringStartsWith('http://', $file)) { if ($this->debug) { throw new Exception('Image not found.'); }else{ throw new Exception(); }};
2396 
2397  // *** Get extension
2398  $extension = strrchr($file, '.');
2399  $extension = fix_strtolower($extension);
2400  switch($extension)
2401  {
2402  case '.jpg':
2403  case '.jpeg':
2404  $img = @imagecreatefromjpeg($file);
2405  break;
2406  case '.gif':
2407  $img = @imagecreatefromgif($file);
2408  break;
2409  case '.png':
2410  $img = @imagecreatefrompng($file);
2411  break;
2412  case '.bmp':
2413  $img = @$this->imagecreatefrombmp($file);
2414  break;
2415  case '.psd':
2416  $img = @$this->imagecreatefrompsd($file);
2417  break;
2418 
2419 
2420  // ... etc
2421 
2422  default:
2423  $img = false;
2424  break;
2425  }
2426 
2427  return $img;
2428  }
2429 
2430 ## --------------------------------------------------------
2431 
2432  public function reset()
2433  #
2434  # Author: Jarrod Oberto
2435  # Date: 30-08-11
2436  # Purpose: Reset the resource (allow further editing)
2437  # Params in:
2438  # Params out:
2439  # Notes:
2440  #
2441  {
2442  $this->__construct($this->fileName);
2443  }
2444 
2445 ## --------------------------------------------------------
2446 
2447  public function saveImage($savePath, $imageQuality="100")
2448  # Author: Jarrod Oberto
2449  # Date: 27-02-08
2450  # Purpose: Saves the image
2451  # Param in: $savePath: Where to save the image including filename:
2452  # $imageQuality: image quality you want the image saved at 0-100
2453  # Param out: n/a
2454  # Reference:
2455  # Notes: * gif doesn't have a quality parameter
2456  # * jpg has a quality setting 0-100 (100 being the best)
2457  # * png has a quality setting 0-9 (0 being the best)
2458  #
2459  # * bmp files have no native support for bmp files. We use a
2460  # third party class to save as bmp.
2461  {
2462 
2463  // *** Perform a check or two.
2464  if (!is_resource($this->imageResized)) { if ($this->debug) { throw new Exception('saveImage: This is not a resource.'); }else{ throw new Exception(); }}
2465  $fileInfoArray = pathInfo($savePath);
2466  clearstatcache();
2467  if (!is_writable($fileInfoArray['dirname'])) { if ($this->debug) { throw new Exception('The path is not writable. Please check your permissions.'); }else{ throw new Exception(); }}
2468 
2469  // *** Get extension
2470  $extension = strrchr($savePath, '.');
2471  $extension = fix_strtolower($extension);
2472 
2473  $error = '';
2474 
2475  switch($extension)
2476  {
2477  case '.jpg':
2478  case '.jpeg':
2479  $this->checkInterlaceImage($this->isInterlace);
2480  if (imagetypes() & IMG_JPG) {
2481  imagejpeg($this->imageResized, $savePath, $imageQuality);
2482  } else { $error = 'jpg'; }
2483  break;
2484 
2485  case '.gif':
2486  $this->checkInterlaceImage($this->isInterlace);
2487  if (imagetypes() & IMG_GIF) {
2488  imagegif($this->imageResized, $savePath);
2489  } else { $error = 'gif'; }
2490  break;
2491 
2492  case '.png':
2493  // *** Scale quality from 0-100 to 0-9
2494  $scaleQuality = round(($imageQuality/100) * 9);
2495 
2496  // *** Invert qualit setting as 0 is best, not 9
2497  $invertScaleQuality = 9 - $scaleQuality;
2498 
2499  $this->checkInterlaceImage($this->isInterlace);
2500  if (imagetypes() & IMG_PNG) {
2501  imagepng($this->imageResized, $savePath, $invertScaleQuality);
2502  } else { $error = 'png'; }
2503  break;
2504 
2505  case '.bmp':
2506  file_put_contents($savePath, $this->GD2BMPstring($this->imageResized));
2507  break;
2508 
2509 
2510  // ... etc
2511 
2512  default:
2513  // *** No extension - No save.
2514  $this->errorArray[] = 'This file type (' . $extension . ') is not supported. File not saved.';
2515  break;
2516  }
2517 
2518  //imagedestroy($this->imageResized);
2519 
2520  // *** Display error if a file type is not supported.
2521  if ($error != '') {
2522  $this->errorArray[] = $error . ' support is NOT enabled. File not saved.';
2523  }
2524  }
2525 
2526 ## --------------------------------------------------------
2527 
2528  public function displayImage($fileType = 'jpg', $imageQuality="100")
2529  # Author: Jarrod Oberto
2530  # Date: 18-11-09
2531  # Purpose: Display images directly to the browser
2532  # Param in: The image type you want to display
2533  # Param out:
2534  # Reference:
2535  # Notes:
2536  #
2537  {
2538 
2539  if (!is_resource($this->imageResized)) { if ($this->debug) { throw new Exception('saveImage: This is not a resource.'); }else{ throw new Exception(); }}
2540 
2541  switch($fileType)
2542  {
2543  case 'jpg':
2544  case 'jpeg':
2545  header('Content-type: image/jpeg');
2546  imagejpeg($this->imageResized, '', $imageQuality);
2547  break;
2548  case 'gif':
2549  header('Content-type: image/gif');
2550  imagegif($this->imageResized);
2551  break;
2552  case 'png':
2553  header('Content-type: image/png');
2554 
2555  // *** Scale quality from 0-100 to 0-9
2556  $scaleQuality = round(($imageQuality/100) * 9);
2557 
2558  // *** Invert qualit setting as 0 is best, not 9
2559  $invertScaleQuality = 9 - $scaleQuality;
2560 
2561  imagepng($this->imageResized, '', $invertScaleQuality);
2562  break;
2563  case 'bmp':
2564  echo 'bmp file format is not supported.';
2565  break;
2566 
2567  // ... etc
2568 
2569  default:
2570  // *** No extension - No save.
2571  break;
2572  }
2573 
2574 
2575  //imagedestroy($this->imageResized);
2576  }
2577 
2578 ## --------------------------------------------------------
2579 
2580  public function setTransparency($bool)
2581  # Sep 2011
2582  {
2583  $this->keepTransparency = $bool;
2584  }
2585 
2586 ## --------------------------------------------------------
2587 
2588  public function setFillColor($value)
2589  # Sep 2011
2590  # Param in: (mixed) $value: (array) Could be an array of RGB
2591  # (str) Could be hex #ffffff or #fff, fff, ffffff
2592  #
2593  # If the keepTransparency is set to false, then no transparency is to be used.
2594  # This is ideal when you want to save as jpg.
2595  #
2596  # this method allows you to set the background color to use instead of
2597  # transparency.
2598  #
2599  {
2600  $colorArray = $this->formatColor($value);
2601  $this->fillColorArray = $colorArray;
2602  }
2603 
2604 ## --------------------------------------------------------
2605 
2606  public function setCropFromTop($value)
2607  # Sep 2011
2608  {
2609  $this->cropFromTopPercent = $value;
2610  }
2611 
2612 ## --------------------------------------------------------
2613 
2614  public function testGDInstalled()
2615  # Author: Jarrod Oberto
2616  # Date: 27-02-08
2617  # Purpose: Test to see if GD is installed
2618  # Param in: n/a
2619  # Param out: (bool) True is gd extension loaded otherwise false
2620  # Reference:
2621  # Notes:
2622  #
2623  {
2624  if(extension_loaded('gd') && function_exists('gd_info'))
2625  {
2626  $gdInstalled = true;
2627  }
2628  else
2629  {
2630  $gdInstalled = false;
2631  }
2632 
2633  return $gdInstalled;
2634  }
2635 
2636 ## --------------------------------------------------------
2637 
2638  public function testEXIFInstalled()
2639  # Author: Jarrod Oberto
2640  # Date: 08-05-11
2641  # Purpose: Test to see if EXIF is installed
2642  # Param in: n/a
2643  # Param out: (bool) True is exif extension loaded otherwise false
2644  # Reference:
2645  # Notes:
2646  #
2647  {
2648  if(extension_loaded('exif'))
2649  {
2650  $exifInstalled = true;
2651  }
2652  else
2653  {
2654  $exifInstalled = false;
2655  }
2656 
2657  return $exifInstalled;
2658  }
2659 
2660 ## --------------------------------------------------------
2661 
2662  public function testIsImage($image)
2663  # Author: Jarrod Oberto
2664  # Date: 27-02-08
2665  # Purpose: Test if file is an image
2666  # Param in: n/a
2667  # Param out: n/a
2668  # Reference:
2669  # Notes:
2670  #
2671  {
2672  if ($image)
2673  {
2674  $fileIsImage = true;
2675  }
2676  else
2677  {
2678  $fileIsImage = false;
2679  }
2680 
2681  return $fileIsImage;
2682  }
2683 
2684 ## --------------------------------------------------------
2685 
2686  public function testFunct()
2687  # Author: Jarrod Oberto
2688  # Date: 27-02-08
2689  # Purpose: Test Function
2690  # Param in: n/a
2691  # Param out: n/a
2692  # Reference:
2693  # Notes:
2694  #
2695  {
2696  echo $this->height;
2697  }
2698 
2699 ## --------------------------------------------------------
2700 
2701  public function setForceStretch($value)
2702  # Author: Jarrod Oberto
2703  # Date: 23-12-10
2704  # Purpose:
2705  # Param in: (bool) $value
2706  # Param out: n/a
2707  # Reference:
2708  # Notes:
2709  #
2710  {
2711  $this->forceStretch = $value;
2712  }
2713 
2714 ## --------------------------------------------------------
2715 
2716  public function setFile($fileName)
2717  # Author: Jarrod Oberto
2718  # Date: 28-02-08
2719  # Purpose:
2720  # Param in: n/a
2721  # Param out: n/a
2722  # Reference:
2723  # Notes:
2724  #
2725  {
2726  self::__construct($fileName);
2727  }
2728 
2729 ## --------------------------------------------------------
2730 
2731  public function getFileName()
2732  # Author: Jarrod Oberto
2733  # Date: 10-09-08
2734  # Purpose:
2735  # Param in: n/a
2736  # Param out: n/a
2737  # Reference:
2738  # Notes:
2739  #
2740  {
2741  return $this->fileName;
2742  }
2743 
2744 ## --------------------------------------------------------
2745 
2746  public function getHeight()
2747  {
2748  return $this->height;
2749  }
2750 
2751 ## --------------------------------------------------------
2752 
2753  public function getWidth()
2754  {
2755  return $this->width;
2756  }
2757 
2758 ## --------------------------------------------------------
2759 
2760  public function getOriginalHeight()
2761  {
2762  return $this->heightOriginal;
2763  }
2764 
2765 ## --------------------------------------------------------
2766 
2767  public function getOriginalWidth()
2768  {
2769  return $this->widthOriginal;
2770  }
2771 
2772 ## --------------------------------------------------------
2773 
2774  public function getErrors()
2775  # Author: Jarrod Oberto
2776  # Date: 19-11-09
2777  # Purpose: Returns the error array
2778  # Param in: n/a
2779  # Param out: Array of errors
2780  # Reference:
2781  # Notes:
2782  #
2783  {
2784  return $this->errorArray;
2785  }
2786 
2787 ## --------------------------------------------------------
2788 
2789  private function checkInterlaceImage($isEnabled)
2790  # jpg will use progressive (they don't use interace)
2791  {
2792  if ($isEnabled) {
2793  imageinterlace($this->imageResized, $isEnabled);
2794  }
2795  }
2796 
2797 ## --------------------------------------------------------
2798 
2799  protected function formatColor($value)
2800  # Author: Jarrod Oberto
2801  # Date: 09-05-11
2802  # Purpose: Determine color method passed in and return color as RGB
2803  # Param in: (mixed) $value: (array) Could be an array of RGB
2804  # (str) Could be hex #ffffff or #fff, fff, ffffff
2805  # Param out:
2806  # Reference:
2807  # Notes:
2808  #
2809  {
2810  $rgbArray = array();
2811 
2812  // *** If it's an array it should be R, G, B
2813  if (is_array($value)) {
2814 
2815  if (key($value) == 0 && count($value) == 3) {
2816 
2817  $rgbArray['r'] = $value[0];
2818  $rgbArray['g'] = $value[1];
2819  $rgbArray['b'] = $value[2];
2820 
2821  } else {
2822  $rgbArray = $value;
2823  }
2824  } else if (fix_strtolower($value) == 'transparent') {
2825 
2826  $rgbArray = array(
2827  'r' => 255,
2828  'g' => 255,
2829  'b' => 255,
2830  'a' => 127
2831  );
2832 
2833  } else {
2834 
2835  // *** ...Else it should be hex. Let's make it RGB
2836  $rgbArray = $this -> hex2dec($value);
2837  }
2838 
2839  return $rgbArray;
2840  }
2841 
2842  ## --------------------------------------------------------
2843 
2844  function hex2dec($hex)
2845  # Purpose: Convert #hex color to RGB
2846  {
2847  $color = str_replace('#', '', $hex);
2848 
2849  if (strlen($color) == 3) {
2850  $color = $color . $color;
2851  }
2852 
2853  $rgb = array(
2854  'r' => hexdec(substr($color, 0, 2)),
2855  'g' => hexdec(substr($color, 2, 2)),
2856  'b' => hexdec(substr($color, 4, 2)),
2857  'a' => 0
2858  );
2859  return $rgb;
2860  }
2861 
2862  ## --------------------------------------------------------
2863 
2864  private function createImageColor ($colorArray)
2865  {
2866  $r = $colorArray['r'];
2867  $g = $colorArray['g'];
2868  $b = $colorArray['b'];
2869 
2870  return imagecolorallocate($this->imageResized, $r, $g, $b);
2871  }
2872 
2873  ## --------------------------------------------------------
2874 
2875  private function testColorExists($colorArray)
2876  {
2877  $r = $colorArray['r'];
2878  $g = $colorArray['g'];
2879  $b = $colorArray['b'];
2880 
2881  if (imagecolorexact($this->imageResized, $r, $g, $b) == -1) {
2882  return false;
2883  } else {
2884  return true;
2885  }
2886  }
2887 
2888  ## --------------------------------------------------------
2889 
2890  private function findUnusedGreen()
2891  # Purpose: We find a green color suitable to use like green-screen effect.
2892  # Therefore, the color must not exist in the image.
2893  {
2894  $green = 255;
2895 
2896  do {
2897 
2898  $greenChroma = array(0, $green, 0);
2899  $colorArray = $this->formatColor($greenChroma);
2900  $match = $this->testColorExists($colorArray);
2901  $green--;
2902 
2903  } while ($match == false && $green > 0);
2904 
2905  // *** If no match, just bite the bullet and use green value of 255
2906  if (!$match) {
2907  $greenChroma = array(0, $green, 0);
2908  }
2909 
2910  return $greenChroma;
2911  }
2912 
2913  ## --------------------------------------------------------
2914 
2915  private function findUnusedBlue()
2916  # Purpose: We find a green color suitable to use like green-screen effect.
2917  # Therefore, the color must not exist in the image.
2918  {
2919  $blue = 255;
2920 
2921  do {
2922 
2923  $blueChroma = array(0, 0, $blue);
2924  $colorArray = $this->formatColor($blueChroma);
2925  $match = $this->testColorExists($colorArray);
2926  $blue--;
2927 
2928  } while ($match == false && $blue > 0);
2929 
2930  // *** If no match, just bite the bullet and use blue value of 255
2931  if (!$match) {
2932  $blueChroma = array(0, 0, $blue);
2933  }
2934 
2935  return $blueChroma;
2936  }
2937 
2938  ## --------------------------------------------------------
2939 
2940  private function invertTransparency($value, $originalMax, $invert=true)
2941  # Purpose: This does two things:
2942  # 1) Convert the range from 0-127 to 0-100
2943  # 2) Inverts value to 100 is not transparent while 0 is fully
2944  # transparent (like Photoshop)
2945  {
2946  // *** Test max range
2947  if ($value > $originalMax) {
2948  $value = $originalMax;
2949  }
2950 
2951  // *** Test min range
2952  if ($value < 0) {
2953  $value = 0;
2954  }
2955 
2956  if ($invert) {
2957  return $originalMax - (($value/100) * $originalMax);
2958  } else {
2959  return ($value/100) * $originalMax;
2960  }
2961  }
2962 
2963  ## --------------------------------------------------------
2964 
2965  private function transparentImage($src)
2966  {
2967  // *** making images with white bg transparent
2968  $r1 = 0;
2969  $g1 = 255;
2970  $b1 = 0;
2971  for ($x = 0; $x < imagesx($src); ++$x) {
2972  for ($y = 0; $y < imagesy($src); ++$y) {
2973  $color = imagecolorat($src, $x, $y);
2974  $r = ($color >> 16) & 0xFF;
2975  $g = ($color >> 8) & 0xFF;
2976  $b = $color & 0xFF;
2977  for ($i = 0; $i < 270; $i++) {
2978  //if ($r . $g . $b == ($r1 + $i) . ($g1 + $i) . ($b1 + $i)) {
2979  if ($r == 0 && $g == 255 && $b == 0) {
2980  //if ($g == 255) {
2981  $trans_colour = imagecolorallocatealpha($src, 0, 0, 0, 127);
2982  imagefill($src, $x, $y, $trans_colour);
2983  }
2984  }
2985  }
2986  }
2987 
2988  return $src;
2989  }
2990 
2991  ## --------------------------------------------------------
2992 
2993  function checkStringStartsWith($needle, $haystack)
2994  # Check if a string starts with a specific pattern
2995  {
2996  return (substr($haystack, 0, strlen($needle))==$needle);
2997  }
2998 
2999 
3000 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
3001  BMP SUPPORT (SAVING) - James Heinrich
3002 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
3003 
3004  private function GD2BMPstring(&$gd_image)
3005  # Author: James Heinrich
3006  # Purpose: Save file as type bmp
3007  # Param in: The image canvas (passed as ref)
3008  # Param out:
3009  # Reference:
3010  # Notes: This code was stripped out of two external files
3011  # (phpthumb.bmp.php,phpthumb.functions.php) and added below to
3012  # avoid dependancies.
3013  #
3014  {
3015  $imageX = ImageSX($gd_image);
3016  $imageY = ImageSY($gd_image);
3017 
3018  $BMP = '';
3019  for ($y = ($imageY - 1); $y >= 0; $y--) {
3020  $thisline = '';
3021  for ($x = 0; $x < $imageX; $x++) {
3022  $argb = $this->GetPixelColor($gd_image, $x, $y);
3023  $thisline .= chr($argb['blue']).chr($argb['green']).chr($argb['red']);
3024  }
3025  while (strlen($thisline) % 4) {
3026  $thisline .= "\x00";
3027  }
3028  $BMP .= $thisline;
3029  }
3030 
3031  $bmpSize = strlen($BMP) + 14 + 40;
3032  // BITMAPFILEHEADER [14 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_62uq.asp
3033  $BITMAPFILEHEADER = 'BM'; // WORD bfType;
3034  $BITMAPFILEHEADER .= $this->LittleEndian2String($bmpSize, 4); // DWORD bfSize;
3035  $BITMAPFILEHEADER .= $this->LittleEndian2String( 0, 2); // WORD bfReserved1;
3036  $BITMAPFILEHEADER .= $this->LittleEndian2String( 0, 2); // WORD bfReserved2;
3037  $BITMAPFILEHEADER .= $this->LittleEndian2String( 54, 4); // DWORD bfOffBits;
3038 
3039  // BITMAPINFOHEADER - [40 bytes] http://msdn.microsoft.com/library/en-us/gdi/bitmaps_1rw2.asp
3040  $BITMAPINFOHEADER = $this->LittleEndian2String( 40, 4); // DWORD biSize;
3041  $BITMAPINFOHEADER .= $this->LittleEndian2String( $imageX, 4); // LONG biWidth;
3042  $BITMAPINFOHEADER .= $this->LittleEndian2String( $imageY, 4); // LONG biHeight;
3043  $BITMAPINFOHEADER .= $this->LittleEndian2String( 1, 2); // WORD biPlanes;
3044  $BITMAPINFOHEADER .= $this->LittleEndian2String( 24, 2); // WORD biBitCount;
3045  $BITMAPINFOHEADER .= $this->LittleEndian2String( 0, 4); // DWORD biCompression;
3046  $BITMAPINFOHEADER .= $this->LittleEndian2String( 0, 4); // DWORD biSizeImage;
3047  $BITMAPINFOHEADER .= $this->LittleEndian2String( 2835, 4); // LONG biXPelsPerMeter;
3048  $BITMAPINFOHEADER .= $this->LittleEndian2String( 2835, 4); // LONG biYPelsPerMeter;
3049  $BITMAPINFOHEADER .= $this->LittleEndian2String( 0, 4); // DWORD biClrUsed;
3050  $BITMAPINFOHEADER .= $this->LittleEndian2String( 0, 4); // DWORD biClrImportant;
3051 
3052  return $BITMAPFILEHEADER.$BITMAPINFOHEADER.$BMP;
3053  }
3054 
3055 ## --------------------------------------------------------
3056 
3057  private function GetPixelColor(&$img, $x, $y)
3058  # Author: James Heinrich
3059  # Purpose:
3060  # Param in:
3061  # Param out:
3062  # Reference:
3063  # Notes:
3064  #
3065  {
3066  if (!is_resource($img)) {
3067  return false;
3068  }
3069  return @ImageColorsForIndex($img, @ImageColorAt($img, $x, $y));
3070  }
3071 
3072 ## --------------------------------------------------------
3073 
3074  private function LittleEndian2String($number, $minbytes=1)
3075  # Author: James Heinrich
3076  # Purpose: BMP SUPPORT (SAVING)
3077  # Param in:
3078  # Param out:
3079  # Reference:
3080  # Notes:
3081  #
3082  {
3083  $intstring = '';
3084  while ($number > 0) {
3085  $intstring = $intstring.chr($number & 255);
3086  $number >>= 8;
3087  }
3088  return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT);
3089  }
3090 
3091 
3092 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
3093  BMP SUPPORT (READING)
3094 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
3095 
3096  private function ImageCreateFromBMP($filename)
3097  # Author: DHKold
3098  # Date: The 15th of June 2005
3099  # Version: 2.0B
3100  # Purpose: To create an image from a BMP file.
3101  # Param in: BMP file to open.
3102  # Param out: Return a resource like the other ImageCreateFrom functions
3103  # Reference: http://us3.php.net/manual/en/function.imagecreate.php#53879
3104  # Bug fix: Author: domelca at terra dot es
3105  # Date: 06 March 2008
3106  # Fix: Correct 16bit BMP support
3107  # Notes:
3108  #
3109  {
3110 
3111  //Ouverture du fichier en mode binaire
3112  if (! $f1 = fopen($filename,"rb")) return FALSE;
3113 
3114  //1 : Chargement des ent�tes FICHIER
3115  $FILE = unpack("vfile_type/Vfile_size/Vreserved/Vbitmap_offset", fread($f1,14));
3116  if ($FILE['file_type'] != 19778) return FALSE;
3117 
3118  //2 : Chargement des ent�tes BMP
3119  $BMP = unpack('Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel'.
3120  '/Vcompression/Vsize_bitmap/Vhoriz_resolution'.
3121  '/Vvert_resolution/Vcolors_used/Vcolors_important', fread($f1,40));
3122  $BMP['colors'] = pow(2,$BMP['bits_per_pixel']);
3123 
3124  if ($BMP['size_bitmap'] == 0) $BMP['size_bitmap'] = $FILE['file_size'] - $FILE['bitmap_offset'];
3125 
3126  $BMP['bytes_per_pixel'] = $BMP['bits_per_pixel']/8;
3127  $BMP['bytes_per_pixel2'] = ceil($BMP['bytes_per_pixel']);
3128  $BMP['decal'] = ($BMP['width']*$BMP['bytes_per_pixel']/4);
3129  $BMP['decal'] -= floor($BMP['width']*$BMP['bytes_per_pixel']/4);
3130  $BMP['decal'] = 4-(4*$BMP['decal']);
3131 
3132  if ($BMP['decal'] == 4) $BMP['decal'] = 0;
3133 
3134  //3 : Chargement des couleurs de la palette
3135  $PALETTE = array();
3136  if ($BMP['colors'] < 16777216)
3137  {
3138  $PALETTE = unpack('V'.$BMP['colors'], fread($f1,$BMP['colors']*4));
3139  }
3140 
3141  //4 : Cr�ation de l'image
3142  $IMG = fread($f1,$BMP['size_bitmap']);
3143  $VIDE = chr(0);
3144 
3145  $res = imagecreatetruecolor($BMP['width'],$BMP['height']);
3146  $P = 0;
3147  $Y = $BMP['height']-1;
3148  while ($Y >= 0)
3149  {
3150  $X=0;
3151  while ($X < $BMP['width'])
3152  {
3153  if ($BMP['bits_per_pixel'] == 24)
3154  $COLOR = unpack("V",substr($IMG,$P,3).$VIDE);
3155  elseif ($BMP['bits_per_pixel'] == 16)
3156  {
3157 
3158  /*
3159  * BMP 16bit fix
3160  * =================
3161  *
3162  * Ref: http://us3.php.net/manual/en/function.imagecreate.php#81604
3163  *
3164  * Notes:
3165  * "don't work with bmp 16 bits_per_pixel. change pixel
3166  * generator for this."
3167  *
3168  */
3169 
3170  // *** Original code (don't work)
3171  //$COLOR = unpack("n",substr($IMG,$P,2));
3172  //$COLOR[1] = $PALETTE[$COLOR[1]+1];
3173 
3174  $COLOR = unpack("v",substr($IMG,$P,2));
3175  $blue = ($COLOR[1] & 0x001f) << 3;
3176  $green = ($COLOR[1] & 0x07e0) >> 3;
3177  $red = ($COLOR[1] & 0xf800) >> 8;
3178  $COLOR[1] = $red * 65536 + $green * 256 + $blue;
3179 
3180  }
3181  elseif ($BMP['bits_per_pixel'] == 8)
3182  {
3183  $COLOR = unpack("n",$VIDE.substr($IMG,$P,1));
3184  $COLOR[1] = $PALETTE[$COLOR[1]+1];
3185  }
3186  elseif ($BMP['bits_per_pixel'] == 4)
3187  {
3188  $COLOR = unpack("n",$VIDE.substr($IMG,floor($P),1));
3189  if (($P*2)%2 == 0) $COLOR[1] = ($COLOR[1] >> 4) ; else $COLOR[1] = ($COLOR[1] & 0x0F);
3190  $COLOR[1] = $PALETTE[$COLOR[1]+1];
3191  }
3192  elseif ($BMP['bits_per_pixel'] == 1)
3193  {
3194  $COLOR = unpack("n",$VIDE.substr($IMG,floor($P),1));
3195  if (($P*8)%8 == 0) $COLOR[1] = $COLOR[1] >>7;
3196  elseif (($P*8)%8 == 1) $COLOR[1] = ($COLOR[1] & 0x40)>>6;
3197  elseif (($P*8)%8 == 2) $COLOR[1] = ($COLOR[1] & 0x20)>>5;
3198  elseif (($P*8)%8 == 3) $COLOR[1] = ($COLOR[1] & 0x10)>>4;
3199  elseif (($P*8)%8 == 4) $COLOR[1] = ($COLOR[1] & 0x8)>>3;
3200  elseif (($P*8)%8 == 5) $COLOR[1] = ($COLOR[1] & 0x4)>>2;
3201  elseif (($P*8)%8 == 6) $COLOR[1] = ($COLOR[1] & 0x2)>>1;
3202  elseif (($P*8)%8 == 7) $COLOR[1] = ($COLOR[1] & 0x1);
3203  $COLOR[1] = $PALETTE[$COLOR[1]+1];
3204  }
3205  else
3206  return FALSE;
3207 
3208  imagesetpixel($res,$X,$Y,$COLOR[1]);
3209  $X++;
3210  $P += $BMP['bytes_per_pixel'];
3211  }
3212 
3213  $Y--;
3214  $P+=$BMP['decal'];
3215  }
3216  //Fermeture du fichier
3217  fclose($f1);
3218 
3219  return $res;
3220  }
3221 
3222 
3223 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
3224  PSD SUPPORT (READING)
3225 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
3226 
3227  private function imagecreatefrompsd($fileName)
3228  # Author: Tim de Koning
3229  # Version: 1.3
3230  # Purpose: To create an image from a PSD file.
3231  # Param in: PSD file to open.
3232  # Param out: Return a resource like the other ImageCreateFrom functions
3233  # Reference: http://www.kingsquare.nl/phppsdreader
3234  # Notes:
3235  #
3236  {
3237  if (file_exists($this->psdReaderPath)) {
3238 
3239 
3240  include_once($this->psdReaderPath);
3241 
3242  $psdReader = new PhpPsdReader($fileName);
3243 
3244  if (isset($psdReader->infoArray['error'])) return '';
3245  else return $psdReader->getImage();
3246  } else {
3247  return false;
3248  }
3249  }
3250 
3251 ## --------------------------------------------------------
3252 
3253  public function __destruct() {
3254  if (is_resource($this->imageResized)) {
3255  imagedestroy($this->imageResized);
3256  }
3257  }
3258 
3259 ## --------------------------------------------------------
3260 
3261 }
3262 
3263 
3264 
3265 
3266 /*
3267  * Example with some API calls (outdated):
3268  *
3269  *
3270  * ===============================
3271  * Compulsary
3272  * ===============================
3273  *
3274  * include("classes/resize_class.php");
3275  *
3276  * // *** Initialise object
3277  * $magicianObj = new resize('images/cars/large/a.jpg');
3278  *
3279  * // *** Turn off stretching (optional)
3280  * $magicianObj -> setForceStretch(false);
3281  *
3282  * // *** Resize object
3283  * $magicianObj -> resizeImage(150, 100, 0);
3284  *
3285  * ===============================
3286  * Image options - can run none, one, or all.
3287  * ===============================
3288  *
3289  * // *** Add watermark
3290  * $magicianObj -> addWatermark('stamp.png');
3291  *
3292  * // *** Add text
3293  * $magicianObj -> addText('testing...');
3294  *
3295  * ===============================
3296  * Output options - can run one, or the other, or both.
3297  * ===============================
3298  *
3299  * // *** Save image to disk
3300  * $magicianObj -> saveImage('images/cars/large/b.jpg', 100);
3301  *
3302  * // *** Or output to screen (params in can be jpg, gif, png)
3303  * $magicianObj -> displayImage('png');
3304  *
3305  * ===============================
3306  * Return options - return errors. nice for debuggin.
3307  * ===============================
3308  *
3309  * // *** Return error array
3310  * $errorArray = $magicianObj -> getErrors();
3311  *
3312  *
3313  * ===============================
3314  * Cleanup options - not really neccessary, but good practice
3315  * ===============================
3316  *
3317  * // *** Free used memory
3318  * $magicianObj -> __destruct();
3319  */
3320 ?>
if(empty($settings['ROOT_PATH'])) elseif(empty($settings['DB_PARAMETERS'])) $error
getOptimalCrop($newWidth, $newHeight)#Author
$i
Definition: dialog.php:68
if(!$dbm->isConnectable()) $res
if(!isset($xoops->paths[$path_type])) if($path_type== 'var') $file
Definition: browse.php:55
$result
Definition: pda.php:33
$text
Definition: qrrender.php:27
$index
Definition: menu.php:41
getSizeByAuto($newWidth, $newHeight)#Author
sharpen()#Author
else $filter
Definition: dialog.php:95
fix_strtolower($str)
Definition: utils.php:203
keepTransparancy($width, $height, $im)#Author
getSizeByFixedWidth($newWidth, $newHeight)
__construct($fileName)#Author
getSizeByFixedHeight($newWidth, $newHeight)
if($xoops->isActiveModule('images')) return false
return true
$type
Definition: misc.php:33
if($xoops->isUser()) else
Definition: admin.php:39
getCropPlacing($optimalWidth, $optimalHeight, $newWidth, $newHeight, $pos='m')##Author
resizeImage($newWidth, $newHeight, $option=0, $sharpen=false, $autoRotate=false)#Author
cropImage($newWidth, $newHeight, $cropPos= 'm')#Author
$bg
Definition: index.php:30
getDimensions($newWidth, $newHeight, $option)#Author
crop($optimalWidth, $optimalHeight, $newWidth, $newHeight, $cropPos)#Author
$xoops option
Definition: common.php:63