Watimage API
  • Namespace
  • Class

Namespaces

  • Elboletaire
    • Watimage
      • Exception

Classes

  • Elboletaire\Watimage\Image
  • Elboletaire\Watimage\Normalize
  • Elboletaire\Watimage\Watermark
  • Elboletaire\Watimage\Watimage

Exceptions

  • Elboletaire\Watimage\Exception\ExtensionNotLoadedException
  • Elboletaire\Watimage\Exception\FileNotExistException
  • Elboletaire\Watimage\Exception\InvalidArgumentException
  • Elboletaire\Watimage\Exception\InvalidExtensionException
  • Elboletaire\Watimage\Exception\InvalidMimeException
  1 <?php
  2 namespace Elboletaire\Watimage;
  3 
  4 use Elboletaire\Watimage\Exception\InvalidArgumentException;
  5 
  6 /**
  7  * The Normalize class. It takes params in a lot of different ways, but it
  8  * always return our expected params :D
  9  *
 10  * @author Òscar Casajuana <elboletaire at underave dot net>
 11  * @copyright 2015 Òscar Casajuana <elboletaire at underave dot net>
 12  * @license https://opensource.org/licenses/MIT MIT
 13  * @link https://github.com/elboletaire/Watimage
 14  */
 15 class Normalize
 16 {
 17     /**
 18      * Returns the proper color array for the given color.
 19      *
 20      * It accepts any (or almost any) imaginable type.
 21      *
 22      * @param  mixed  $color Can be an array (sequential or associative) or
 23      *                       hexadecimal. In hexadecimal allows 3 and 6 characters
 24      *                       for rgb and 4 or 8 characters for rgba.
 25      * @return array         Containing all 4 color channels.
 26      * @throws InvalidArgumentException
 27      */
 28     public static function color($color)
 29     {
 30         if ($color === Image::COLOR_TRANSPARENT) {
 31             return [
 32                 'r' => 0,
 33                 'g' => 0,
 34                 'b' => 0,
 35                 'a' => 127
 36             ];
 37         }
 38 
 39         // rgb(a) arrays
 40         if (is_array($color) && in_array(count($color), [3, 4])) {
 41             $allowedKeys = [
 42                 'associative' => ['red', 'green', 'blue', 'alpha'],
 43                 'reduced'     => ['r', 'g', 'b', 'a'],
 44                 'numeric'     => [0, 1, 2, 3]
 45             ];
 46 
 47             foreach ($allowedKeys as $keys) {
 48                 list($r, $g, $b, $a) = $keys;
 49 
 50                 if (!isset($color[$r], $color[$g], $color[$b])) {
 51                     continue;
 52                 }
 53 
 54                 return [
 55                     'r' => self::fitInRange($color[$r], 0, 255),
 56                     'g' => self::fitInRange($color[$g], 0, 255),
 57                     'b' => self::fitInRange($color[$b], 0, 255),
 58                     'a' => self::fitInRange(isset($color[$a]) ? $color[$a] : 0, 0, 127),
 59                 ];
 60             }
 61 
 62             throw new InvalidArgumentException("Invalid array color value %s.", $color);
 63         }
 64 
 65         // hexadecimal
 66         if (!is_string($color)) {
 67             throw new InvalidArgumentException("Invalid color value \"%s\"", $color);
 68         }
 69 
 70         $color = ltrim($color, '#');
 71         if (in_array(strlen($color), [3, 4])) {
 72             $color = str_split($color);
 73             $color = array_map(function ($item) {
 74                 return str_repeat($item, 2);
 75             }, $color);
 76             $color = implode($color);
 77         }
 78         if (strlen($color) == 6) {
 79             list($r, $g, $b) = [
 80                 $color[0] . $color[1],
 81                 $color[2] .$color[3],
 82                 $color[4] . $color[5]
 83             ];
 84         } elseif (strlen($color) == 8) {
 85             list($r, $g, $b, $a) = [
 86                 $color[0] . $color[1],
 87                 $color[2] . $color[3],
 88                 $color[4] . $color[5],
 89                 $color[6] . $color[7]
 90             ];
 91         } else {
 92             throw new InvalidArgumentException("Invalid hexadecimal color value \"%s\"", $color);
 93         }
 94 
 95         return [
 96             'r' => hexdec($r),
 97             'g' => hexdec($g),
 98             'b' => hexdec($b),
 99             'a' => isset($a) ? hexdec($a) : 0
100         ];
101     }
102 
103     /**
104      * Normalizes crop arguments returning an array with them.
105      *
106      * You can pass arguments one by one or an array passing arguments
107      * however you like.
108      *
109      * @param  int $x      X position where start to crop.
110      * @param  int $y      Y position where start to crop.
111      * @param  int $width  New width of the image.
112      * @param  int $height New height of the image.
113      * @return array       Array with numeric keys for x, y, width & height
114      * @throws InvalidArgumentException
115      */
116     public static function crop($x, $y = null, $width = null, $height = null)
117     {
118         if (!isset($y, $width, $height) && is_array($x)) {
119             $values = $x;
120             $allowedKeys = [
121                 'associative' => ['x', 'y', 'width', 'height'],
122                 'reduced'     => ['x', 'y', 'w', 'h'],
123                 'numeric'     => [0, 1, 2, 3]
124             ];
125 
126             foreach ($allowedKeys as $keys) {
127                 list($x, $y, $width, $height) = $keys;
128                 if (isset($values[$x], $values[$y], $values[$width], $values[$height])) {
129                     return [
130                         $values[$x],
131                         $values[$y],
132                         $values[$width],
133                         $values[$height]
134                     ];
135                 }
136             }
137         }
138 
139         if (!isset($x, $y, $width, $height)) {
140             throw new InvalidArgumentException(
141                 "Invalid options for crop %s.",
142                 compact('x', 'y', 'width', 'height')
143             );
144         }
145 
146         return [$x, $y, $width, $height];
147     }
148 
149     /**
150      * Normalizes flip type from any of the allowed values.
151      *
152      * @param  mixed $type  Can be either:
153      *                      v, y, vertical or IMG_FLIP_VERTICAL
154      *                      h, x, horizontal or IMG_FLIP_HORIZONTAL
155      *                      b, xy, yx, both or IMG_FLIP_BOTH
156      * @return int
157      * @throws InvalidArgumentException
158      */
159     public static function flip($type)
160     {
161         switch (strtolower($type)) {
162             case 'x':
163             case 'h':
164             case 'horizontal':
165             case IMG_FLIP_HORIZONTAL:
166                 return IMG_FLIP_HORIZONTAL;
167                 break;
168 
169             case 'y':
170             case 'v':
171             case 'vertical':
172             case IMG_FLIP_VERTICAL:
173                 return IMG_FLIP_VERTICAL;
174                 break;
175 
176             case 'b':
177             case 'both':
178             case IMG_FLIP_BOTH:
179                 return IMG_FLIP_BOTH;
180                 break;
181 
182             default:
183                 throw new InvalidArgumentException("Incorrect flip type \"%s\"", $type);
184                 break;
185         }
186     }
187 
188     /**
189      * An alias of self::position but returning a customized message for Watermark.
190      *
191      * @param  mixed  $x Can be just x or an array containing both params.
192      * @param  int    $y Can only be y.
193      * @return array     With x and y in a sequential array.
194      * @throws InvalidArgumentException
195      */
196     public static function margin($x, $y = null)
197     {
198         try {
199             list($x, $y) = self::position($x, $y);
200         } catch (InvalidArgumentException $e) {
201             throw new InvalidArgumentException("Invalid margin %s.", compact('x', 'y'));
202         }
203 
204         return [$x, $y];
205     }
206 
207     /**
208      * Normalizes position (x and y).
209      *
210      * @param  mixed  $x Can be just x or an array containing both params.
211      * @param  int    $y Can only be y.
212      * @return array     With x and y in a sequential array.
213      * @throws InvalidArgumentException
214      */
215     public static function position($x, $y = null)
216     {
217         if (is_array($x)) {
218             if (isset($x['x']) || isset($x['y'])) {
219                 extract($x);
220             } else {
221                 @list($x, $y) = $x;
222             }
223         }
224 
225         if (is_numeric($x) && !isset($y)) {
226             $y = $x;
227         }
228 
229         if (!isset($x, $y) || !(is_numeric($x) && is_numeric($y))) {
230             throw new InvalidArgumentException("Invalid position %s.", compact('x', 'y'));
231         }
232 
233         return [$x, $y];
234     }
235 
236     /**
237      * Normalizes cropMeasures (origin X, origin Y, destiny X & destiny Y)
238      *
239      * @param  mixed $ox Can be just ox or an array containing all the params.
240      * @param  int   $oy Origin Y.
241      * @param  int   $dx Destiny X.
242      * @param  int   $dy Destiny Y.
243      * @return array
244      */
245     public static function cropMeasures($ox, $oy = null, $dx = null, $dy = null)
246     {
247         if (!isset($oy, $dx, $dy, $width, $height) && is_array($ox)) {
248             $values = $ox;
249             $allowedKeys = [
250                 'associative' => ['ox', 'oy', 'dx', 'dy'],
251                 'numeric'     => [0, 1, 2, 3]
252             ];
253 
254             foreach ($allowedKeys as $keys) {
255                 list($oxk, $oyk, $dxk, $dyk) = $keys;
256                 $isset = isset(
257                     $values[$oxk],
258                     $values[$oyk],
259                     $values[$dxk],
260                     $values[$dyk]
261                 );
262                 if (!$isset) {
263                     continue;
264                 }
265                 return [
266                     $values[$oxk],
267                     $values[$oyk],
268                     $values[$dxk],
269                     $values[$dyk]
270                 ];
271             }
272         }
273 
274         if (!isset($ox, $oy, $dx, $dy)) {
275             throw new InvalidArgumentException(
276                 "Invalid options for cropMeasures %s.",
277                 compact('ox', 'oy', 'dx', 'dy')
278             );
279         }
280 
281         return [$ox, $oy, $dx, $dy];
282     }
283 
284     /**
285      * Normalizes size (width and height).
286      *
287      * @param  mixed  $width  Can be just width or an array containing both params.
288      * @param  int    $height Can only be height.
289      * @return array          With width and height in a sequential array.
290      * @throws InvalidArgumentException
291      */
292     public static function size($width, $height = null)
293     {
294         if (!isset($height) && is_array($width)) {
295             $allowedKeys = [
296                 [0, 1],
297                 ['x', 'y'],
298                 ['w', 'h'],
299                 ['width', 'height'],
300             ];
301 
302             foreach ($allowedKeys as $keys) {
303                 list($x, $y) = $keys;
304 
305 
306                 if (isset($width[$x])) {
307                     if (isset($width[$y])) {
308                         $height = $width[$y];
309                     }
310                     $width = $width[$x];
311                     break;
312                 }
313             }
314         }
315 
316         if (isset($width) && !isset($height)) {
317             $height = $width;
318         }
319 
320         if (!isset($width, $height) || !(is_numeric($width) && is_numeric($height))) {
321             throw new InvalidArgumentException(
322                 "Invalid resize arguments %s",
323                 compact('width', 'height')
324             );
325         }
326 
327         return [
328             self::fitInRange($width, 0),
329             self::fitInRange($height, 0)
330         ];
331     }
332 
333     /**
334      * Checks that the given value is between our defined range.
335      *
336      * Can check just for min or max if setting the other value to false.
337      *
338      * @param  int  $value Value to be checked,
339      * @param  bool $min   Minimum value. False to just use max.
340      * @param  bool $max   Maximum value. False to just use min.
341      * @return int         The value itself.
342      */
343     public static function fitInRange($value, $min = false, $max = false)
344     {
345         if ($min !== false && $value < $min) {
346             $value = $min;
347         }
348 
349         if ($max !== false && $value > $max) {
350             $value = $max;
351         }
352 
353         return $value;
354     }
355 
356     /**
357      * Normalizes position + position ala css.
358      *
359      * @param  mixed $position Array with x,y or string ala CSS.
360      * @return mixed           Returns what you pass (array or string).
361      * @throws InvalidArgumentException
362      */
363     public static function cssPosition($position)
364     {
365         try {
366             $position = self::position($position);
367         } catch (InvalidArgumentException $e) {
368             if (!is_string($position)) {
369                 throw new InvalidArgumentException("Invalid watermark position %s.", $position);
370             }
371 
372             if (in_array($position, ['center', 'centered'])) {
373                 $position = 'center center';
374             }
375 
376             if (!preg_match('/((center|top|bottom|right|left) ?){2}/', $position)) {
377                 throw new InvalidArgumentException("Invalid watermark position %s.", $position);
378             }
379         }
380 
381         return $position;
382     }
383 
384     /**
385      * Returns proper size argument for Watermark.
386      *
387      * @param  mixed  $width  Can be a percentage, just width or an array containing both params.
388      * @param  int    $height Can only be height.
389      * @return mixed
390      */
391     public static function watermarkSize($width, $height = null)
392     {
393         try {
394             $width = self::size($width, $height);
395         } catch (InvalidArgumentException $e) {
396             if (!is_string($width) || !preg_match('/([0-9]{1,3}%|full)$/', $width)) {
397                 throw new InvalidArgumentException(
398                     "Invalid size arguments %s",
399                     compact('width', 'height')
400                 );
401             }
402         }
403 
404         return $width;
405     }
406 }
407 
Watimage API API documentation generated by ApiGen