1 <?php
2 namespace Elboletaire\Watimage;
3
4 use Elboletaire\Watimage\Exception\InvalidArgumentException;
5
6 7 8 9 10 11 12 13 14
15 class Normalize
16 {
17 18 19 20 21 22 23 24 25 26 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
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
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 105 106 107 108 109 110 111 112 113 114 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 151 152 153 154 155 156 157 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 190 191 192 193 194 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 209 210 211 212 213 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 238 239 240 241 242 243 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 286 287 288 289 290 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 335 336 337 338 339 340 341 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 358 359 360 361 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 386 387 388 389 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