Completed
Push — master ( 339e22...8a2797 )
by Jonathan
02:46
created

Size::runCropResize()   B

Complexity

Conditions 6
Paths 32

Size

Total Lines 45
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 7.8984

Importance

Changes 3
Bugs 1 Features 2
Metric Value
c 3
b 1
f 2
dl 0
loc 45
ccs 20
cts 32
cp 0.625
rs 8.439
cc 6
eloc 26
nc 32
nop 3
crap 7.8984
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);
0 ignored issues
show
Unused Code introduced by
The call to Size::runCropResize() has too many arguments starting with $crop.

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.

Loading history...
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