1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace League\Glide\Manipulators; |
4
|
|
|
|
5
|
|
|
use Intervention\Image\Image; |
6
|
|
|
|
7
|
|
|
/** |
8
|
|
|
* @property string $dpr |
9
|
|
|
* @property string $fit |
10
|
|
|
* @property string $h |
11
|
|
|
* @property string $w |
12
|
|
|
*/ |
13
|
|
|
class Size extends BaseManipulator |
14
|
|
|
{ |
15
|
|
|
/** |
16
|
|
|
* Maximum image size in pixels. |
17
|
|
|
* @var int|null |
18
|
|
|
*/ |
19
|
|
|
protected $maxImageSize; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Create Size instance. |
23
|
|
|
* @param int|null $maxImageSize Maximum image size in pixels. |
24
|
|
|
*/ |
25
|
66 |
|
public function __construct($maxImageSize = null) |
26
|
|
|
{ |
27
|
66 |
|
$this->maxImageSize = $maxImageSize; |
28
|
66 |
|
} |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* Set the maximum image size. |
32
|
|
|
* @param int|null Maximum image size in pixels. |
33
|
|
|
*/ |
34
|
6 |
|
public function setMaxImageSize($maxImageSize) |
35
|
|
|
{ |
36
|
6 |
|
$this->maxImageSize = $maxImageSize; |
37
|
6 |
|
} |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* Get the maximum image size. |
41
|
|
|
* @return int|null Maximum image size in pixels. |
42
|
|
|
*/ |
43
|
6 |
|
public function getMaxImageSize() |
44
|
|
|
{ |
45
|
6 |
|
return $this->maxImageSize; |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* Perform size image manipulation. |
50
|
|
|
* @param Image $image The source image. |
51
|
|
|
* @return Image The manipulated image. |
52
|
|
|
*/ |
53
|
6 |
|
public function run(Image $image) |
54
|
|
|
{ |
55
|
6 |
|
$width = $this->getWidth(); |
56
|
6 |
|
$height = $this->getHeight(); |
57
|
6 |
|
$fit = $this->getFit(); |
58
|
6 |
|
$dpr = $this->getDpr(); |
59
|
|
|
|
60
|
6 |
|
list($width, $height) = $this->resolveMissingDimensions($image, $width, $height); |
61
|
6 |
|
list($width, $height) = $this->applyDpr($width, $height, $dpr); |
62
|
6 |
|
list($width, $height) = $this->limitImageSize($width, $height); |
63
|
|
|
|
64
|
6 |
|
if (round($width) !== round($image->width()) or |
65
|
6 |
|
round($height) !== round($image->height())) { |
66
|
6 |
|
$image = $this->runResize($image, $fit, round($width), round($height)); |
67
|
4 |
|
} |
68
|
|
|
|
69
|
6 |
|
return $image; |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* Resolve width. |
74
|
|
|
* @return string The resolved width. |
75
|
|
|
*/ |
76
|
9 |
|
public function getWidth() |
77
|
|
|
{ |
78
|
9 |
|
if (!is_numeric($this->w)) { |
79
|
3 |
|
return; |
80
|
|
|
} |
81
|
|
|
|
82
|
9 |
|
if ($this->w <= 0) { |
83
|
3 |
|
return; |
84
|
|
|
} |
85
|
|
|
|
86
|
9 |
|
return (double) $this->w; |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* Resolve height. |
91
|
|
|
* @return string The resolved height. |
92
|
|
|
*/ |
93
|
9 |
|
public function getHeight() |
94
|
|
|
{ |
95
|
9 |
|
if (!is_numeric($this->h)) { |
96
|
6 |
|
return; |
97
|
|
|
} |
98
|
|
|
|
99
|
6 |
|
if ($this->h <= 0) { |
100
|
3 |
|
return; |
101
|
|
|
} |
102
|
|
|
|
103
|
6 |
|
return (double) $this->h; |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* Resolve fit. |
108
|
|
|
* @return string The resolved fit. |
109
|
|
|
*/ |
110
|
9 |
|
public function getFit() |
111
|
|
|
{ |
112
|
9 |
|
if (in_array($this->fit, ['contain', 'fill', 'max', 'stretch'], true)) { |
113
|
3 |
|
return $this->fit; |
114
|
|
|
} |
115
|
|
|
|
116
|
9 |
|
if (preg_match('/^(crop)(-top-left|-top|-top-right|-left|-center|-right|-bottom-left|-bottom|-bottom-right|-[\d]{1,3}-[\d]{1,3})*$/', $this->fit)) { |
117
|
3 |
|
return 'crop'; |
118
|
|
|
} |
119
|
|
|
|
120
|
9 |
|
return 'contain'; |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* Resolve crop. |
125
|
|
|
* @return string|array The resolved crop. |
126
|
|
|
*/ |
127
|
9 |
|
public function getCrop() |
128
|
|
|
{ |
129
|
|
|
$cropMethods = [ |
130
|
9 |
|
'crop-top-left' => [0, 0], |
131
|
6 |
|
'crop-top' => [50, 0], |
132
|
6 |
|
'crop-top-right' => [100, 0], |
133
|
6 |
|
'crop-left' => [0, 50], |
134
|
6 |
|
'crop-center' => [50, 50], |
135
|
6 |
|
'crop-right' => [100, 50], |
136
|
6 |
|
'crop-bottom-left' => [0, 100], |
137
|
6 |
|
'crop-bottom' => [50, 100], |
138
|
6 |
|
'crop-bottom-right' => [100, 100], |
139
|
6 |
|
]; |
140
|
|
|
|
141
|
9 |
|
if (array_key_exists($this->fit, $cropMethods)) { |
142
|
3 |
|
return $cropMethods[$this->fit]; |
143
|
|
|
} |
144
|
|
|
|
145
|
9 |
|
if (preg_match('/^crop-([\d]{1,3})-([\d]{1,3})*$/', $this->fit, $matches)) { |
146
|
3 |
|
if ($matches[1] > 100 or $matches[2] > 100) { |
147
|
3 |
|
return [50, 50]; |
148
|
|
|
} |
149
|
|
|
|
150
|
3 |
|
return [(int) $matches[1], (int) $matches[2]]; |
151
|
|
|
} |
152
|
|
|
|
153
|
9 |
|
return [50, 50]; |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* Resolve the device pixel ratio. |
158
|
|
|
* @return double The device pixel ratio. |
159
|
|
|
*/ |
160
|
9 |
|
public function getDpr() |
161
|
|
|
{ |
162
|
9 |
|
if (!is_numeric($this->dpr)) { |
163
|
9 |
|
return 1.0; |
164
|
|
|
} |
165
|
|
|
|
166
|
3 |
|
if ($this->dpr < 0 or $this->dpr > 8) { |
167
|
3 |
|
return 1.0; |
168
|
|
|
} |
169
|
|
|
|
170
|
3 |
|
return (double) $this->dpr; |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
/** |
174
|
|
|
* Resolve missing image dimensions. |
175
|
|
|
* @param Image $image The source image. |
176
|
|
|
* @param double|null $width The image width. |
177
|
|
|
* @param double|null $height The image height. |
178
|
|
|
* @return double[] The resolved width and height. |
179
|
|
|
*/ |
180
|
9 |
|
public function resolveMissingDimensions(Image $image, $width, $height) |
181
|
|
|
{ |
182
|
9 |
|
if (!$width and !$height) { |
183
|
3 |
|
$width = $image->width(); |
184
|
3 |
|
$height = $image->height(); |
185
|
2 |
|
} |
186
|
|
|
|
187
|
9 |
|
if (!$width) { |
188
|
3 |
|
$width = $height * ($image->width() / $image->height()); |
189
|
2 |
|
} |
190
|
|
|
|
191
|
9 |
|
if (!$height) { |
192
|
6 |
|
$height = $width / ($image->width() / $image->height()); |
193
|
4 |
|
} |
194
|
|
|
|
195
|
|
|
return [ |
196
|
9 |
|
(double) $width, |
197
|
9 |
|
(double) $height, |
198
|
6 |
|
]; |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
/** |
202
|
|
|
* Apply the device pixel ratio. |
203
|
|
|
* @param double $width The target image width. |
204
|
|
|
* @param double $height The target image height. |
205
|
|
|
* @param double $dpr The device pixel ratio. |
206
|
|
|
* @return double[] The modified width and height. |
207
|
|
|
*/ |
208
|
6 |
|
public function applyDpr($width, $height, $dpr) |
209
|
|
|
{ |
210
|
6 |
|
$width = $width * $dpr; |
211
|
6 |
|
$height = $height * $dpr; |
212
|
|
|
|
213
|
|
|
return [ |
214
|
6 |
|
(double) $width, |
215
|
6 |
|
(double) $height, |
216
|
4 |
|
]; |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
/** |
220
|
|
|
* Limit image size to maximum allowed image size. |
221
|
|
|
* @param double $width The image width. |
222
|
|
|
* @param double $height The image height. |
223
|
|
|
* @return double[] The limited width and height. |
224
|
|
|
*/ |
225
|
9 |
|
public function limitImageSize($width, $height) |
226
|
|
|
{ |
227
|
9 |
|
if ($this->maxImageSize !== null) { |
228
|
3 |
|
$imageSize = $width * $height; |
229
|
|
|
|
230
|
3 |
|
if ($imageSize > $this->maxImageSize) { |
231
|
3 |
|
$width = $width / sqrt($imageSize / $this->maxImageSize); |
232
|
3 |
|
$height = $height / sqrt($imageSize / $this->maxImageSize); |
233
|
2 |
|
} |
234
|
2 |
|
} |
235
|
|
|
|
236
|
|
|
return [ |
237
|
9 |
|
(double) $width, |
238
|
9 |
|
(double) $height, |
239
|
6 |
|
]; |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
/** |
243
|
|
|
* Perform resize image manipulation. |
244
|
|
|
* @param Image $image The source image. |
245
|
|
|
* @param string $fit The fit. |
246
|
|
|
* @param string $width The width. |
247
|
|
|
* @param string $height The height. |
248
|
|
|
* @param string|null $crop The crop. |
249
|
|
|
* @return Image The manipulated image. |
250
|
|
|
*/ |
251
|
9 |
|
public function runResize(Image $image, $fit, $width, $height, $crop = null) |
252
|
|
|
{ |
253
|
9 |
|
if ($fit === 'contain') { |
254
|
9 |
|
return $this->runContainResize($image, $width, $height); |
255
|
|
|
} |
256
|
|
|
|
257
|
3 |
|
if ($fit === 'fill') { |
258
|
3 |
|
return $this->runFillResize($image, $width, $height); |
259
|
|
|
} |
260
|
|
|
|
261
|
3 |
|
if ($fit === 'max') { |
262
|
3 |
|
return $this->runMaxResize($image, $width, $height); |
263
|
|
|
} |
264
|
|
|
|
265
|
3 |
|
if ($fit === 'stretch') { |
266
|
3 |
|
return $this->runStretchResize($image, $width, $height); |
267
|
|
|
} |
268
|
|
|
|
269
|
3 |
|
if ($fit === 'crop') { |
270
|
3 |
|
return $this->runCropResize($image, $width, $height, $crop); |
|
|
|
|
271
|
|
|
} |
272
|
|
|
|
273
|
3 |
|
return $image; |
274
|
|
|
} |
275
|
|
|
|
276
|
|
|
/** |
277
|
|
|
* Perform contain resize image manipulation. |
278
|
|
|
* @param Image $image The source image. |
279
|
|
|
* @param string $width The width. |
280
|
|
|
* @param string $height The height. |
281
|
|
|
* @return Image The manipulated image. |
282
|
|
|
*/ |
283
|
12 |
|
public function runContainResize(Image $image, $width, $height) |
284
|
|
|
{ |
285
|
|
|
return $image->resize($width, $height, function ($constraint) { |
286
|
|
|
$constraint->aspectRatio(); |
287
|
12 |
|
}); |
288
|
|
|
} |
289
|
|
|
|
290
|
|
|
/** |
291
|
|
|
* Perform max resize image manipulation. |
292
|
|
|
* @param Image $image The source image. |
293
|
|
|
* @param string $width The width. |
294
|
|
|
* @param string $height The height. |
295
|
|
|
* @return Image The manipulated image. |
296
|
|
|
*/ |
297
|
9 |
|
public function runMaxResize(Image $image, $width, $height) |
298
|
|
|
{ |
299
|
|
|
return $image->resize($width, $height, function ($constraint) { |
300
|
|
|
$constraint->aspectRatio(); |
301
|
|
|
$constraint->upsize(); |
302
|
9 |
|
}); |
303
|
|
|
} |
304
|
|
|
|
305
|
|
|
/** |
306
|
|
|
* Perform fill resize image manipulation. |
307
|
|
|
* @param Image $image The source image. |
308
|
|
|
* @param string $width The width. |
309
|
|
|
* @param string $height The height. |
310
|
|
|
* @return Image The manipulated image. |
311
|
|
|
*/ |
312
|
6 |
|
public function runFillResize($image, $width, $height) |
313
|
|
|
{ |
314
|
6 |
|
$image = $this->runMaxResize($image, $width, $height); |
315
|
|
|
|
316
|
6 |
|
return $image->resizeCanvas($width, $height, 'center'); |
317
|
|
|
} |
318
|
|
|
|
319
|
|
|
/** |
320
|
|
|
* Perform stretch resize image manipulation. |
321
|
|
|
* @param Image $image The source image. |
322
|
|
|
* @param string $width The width. |
323
|
|
|
* @param string $height The height. |
324
|
|
|
* @return Image The manipulated image. |
325
|
|
|
*/ |
326
|
6 |
|
public function runStretchResize(Image $image, $width, $height) |
327
|
|
|
{ |
328
|
6 |
|
return $image->resize($width, $height); |
329
|
|
|
} |
330
|
|
|
|
331
|
|
|
/** |
332
|
|
|
* Perform crop resize image manipulation. |
333
|
|
|
* @param Image $image The source image. |
334
|
|
|
* @param string $width The width. |
335
|
|
|
* @param string $height The height. |
336
|
|
|
* @return Image The manipulated image. |
337
|
|
|
*/ |
338
|
6 |
|
public function runCropResize(Image $image, $width, $height) |
339
|
|
|
{ |
340
|
6 |
|
list($offset_percentage_x, $offset_percentage_y) = $this->getCrop(); |
341
|
|
|
|
342
|
6 |
|
$resize_width = $width; |
343
|
6 |
|
$resize_height = $width * ($image->height() / $image->width()); |
344
|
|
|
|
345
|
6 |
|
if ($height > $resize_height) { |
346
|
|
|
$resize_width = $height * ($image->width() / $image->height()); |
347
|
|
|
$resize_height = $height; |
348
|
|
|
} |
349
|
|
|
|
350
|
6 |
|
$image->resize($resize_width, $resize_height, function ($constraint) { |
351
|
|
|
$constraint->aspectRatio(); |
352
|
6 |
|
}); |
353
|
|
|
|
354
|
6 |
|
$offset_x = round(($image->width() * $offset_percentage_x / 100) - ($width / 2)); |
355
|
6 |
|
$offset_y = round(($image->height() * $offset_percentage_y / 100) - ($height / 2)); |
356
|
|
|
|
357
|
6 |
|
$max_offset_x = $image->width() - $width; |
358
|
6 |
|
$max_offset_y = $image->height() - $height; |
359
|
|
|
|
360
|
6 |
|
if ($offset_x < 0) { |
361
|
|
|
$offset_x = 0; |
362
|
|
|
} |
363
|
|
|
|
364
|
6 |
|
if ($offset_y < 0) { |
365
|
|
|
$offset_y = 0; |
366
|
|
|
} |
367
|
|
|
|
368
|
6 |
|
if ($offset_x > $max_offset_x) { |
369
|
|
|
$offset_x = $max_offset_x; |
370
|
|
|
} |
371
|
|
|
|
372
|
6 |
|
if ($offset_y > $max_offset_y) { |
373
|
|
|
$offset_y = $max_offset_y; |
374
|
|
|
} |
375
|
|
|
|
376
|
6 |
|
return $image->crop( |
377
|
4 |
|
$width, |
378
|
4 |
|
$height, |
379
|
4 |
|
$offset_x, |
380
|
|
|
$offset_y |
381
|
4 |
|
); |
382
|
|
|
} |
383
|
|
|
} |
384
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.