Passed
Branch master (410c7b)
by Michael
03:30
created

Resizer   B

Complexity

Total Complexity 48

Size/Duplication

Total Lines 370
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 48
eloc 205
dl 0
loc 370
rs 8.5599
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
C resizeAndCrop() 0 110 11
C resizeImage() 0 97 13
B rotateImage() 0 53 11
C mergeImage() 0 69 13

How to fix   Complexity   

Complex Class

Complex classes like Resizer often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Resizer, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
namespace XoopsModules\Suico\Common;
6
7
/*
8
 You may not change or alter any portion of this comment or credits
9
 of supporting developers from this source code or any supporting source code
10
 which is considered copyrighted (c) material of the original comment or credit authors.
11
12
 This program is distributed in the hope that it will be useful,
13
 but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
*/
16
17
/**
18
 * Image resizer class for xoops
19
 *
20
 * @copyright      2000-2020 XOOPS Project (https://xoops.org)
21
 * @license        GPL 2.0 or later
22
 * @package        XOOPS common
23
 * @since          1.0
24
 * @min_xoops      2.5.9
25
 * @author         Goffy - Wedega - Email:<[email protected]> - Website:<https://wedega.com>
26
 */
27
class Resizer
28
{
29
    public $sourceFile = '';
30
31
    public $endFile = '';
32
33
    public $maxWidth = 0;
34
35
    public $maxHeight = 0;
36
37
    public $imageMimetype = '';
38
39
    public $jpgQuality = 90;
40
41
    public $mergeType = 0;
42
43
    public $mergePos = 0;
44
45
    public $degrees = 0;
46
47
    public $error = '';
48
49
    /**
50
     * resize image if size exceed given width/height
51
     * @return string|bool
52
     */
53
54
    public function resizeImage()
55
    {
56
        // check file extension
57
58
        switch ($this->imageMimetype) {
59
            case 'image/png':
60
                $img = \imagecreatefrompng($this->sourceFile);
61
                break;
62
            case 'image/jpeg':
63
                $img = \imagecreatefromjpeg($this->sourceFile);
64
                if (!$img) {
0 ignored issues
show
introduced by
$img is of type false|resource, thus it always evaluated to false.
Loading history...
65
                    $img = \imagecreatefromstring(file_get_contents($this->sourceFile));
66
                }
67
                break;
68
            case 'image/gif':
69
                $img = \imagecreatefromgif($this->sourceFile);
70
                break;
71
            default:
72
                return 'Unsupported format';
73
        }
74
75
        $width = \imagesx($img);
0 ignored issues
show
Bug introduced by
It seems like $img can also be of type false; however, parameter $image of imagesx() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

75
        $width = \imagesx(/** @scrutinizer ignore-type */ $img);
Loading history...
76
77
        $height = \imagesy($img);
0 ignored issues
show
Bug introduced by
It seems like $img can also be of type false; however, parameter $image of imagesy() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

77
        $height = \imagesy(/** @scrutinizer ignore-type */ $img);
Loading history...
78
79
        if ($width > $this->maxWidth || $height > $this->maxHeight) {
80
            // recalc image size based on this->maxWidth/this->maxHeight
81
82
            if ($width > $height) {
83
                if ($width < $this->maxWidth) {
84
                    $newWidth = $width;
85
                } else {
86
                    $newWidth = $this->maxWidth;
87
88
                    $divisor = $width / $newWidth;
89
90
                    $newHeight = (int)\floor($height / $divisor);
91
                }
92
            } elseif ($height < $this->maxHeight) {
93
                $newHeight = (int)$height;
94
            } else {
95
                $newHeight = $this->maxHeight;
96
97
                $divisor = $height / $newHeight;
98
99
                $newWidth = (int)\floor($width / $divisor);
100
            }
101
102
            // Create a new temporary image.
103
104
            $tmpimg = \imagecreatetruecolor($newWidth, $newHeight);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $newWidth does not seem to be defined for all execution paths leading up to this point.
Loading history...
Comprehensibility Best Practice introduced by
The variable $newHeight does not seem to be defined for all execution paths leading up to this point.
Loading history...
105
106
            imagealphablending($tmpimg, false);
0 ignored issues
show
Bug introduced by
It seems like $tmpimg can also be of type false; however, parameter $image of imagealphablending() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

106
            imagealphablending(/** @scrutinizer ignore-type */ $tmpimg, false);
Loading history...
107
108
            imagesavealpha($tmpimg, true);
0 ignored issues
show
Bug introduced by
It seems like $tmpimg can also be of type false; however, parameter $image of imagesavealpha() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

108
            imagesavealpha(/** @scrutinizer ignore-type */ $tmpimg, true);
Loading history...
109
110
            // Copy and resize old image into new image.
111
112
            \imagecopyresampled(
113
                $tmpimg,
0 ignored issues
show
Bug introduced by
It seems like $tmpimg can also be of type false; however, parameter $dst_image of imagecopyresampled() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

113
                /** @scrutinizer ignore-type */ $tmpimg,
Loading history...
114
                $img,
0 ignored issues
show
Bug introduced by
It seems like $img can also be of type false; however, parameter $src_image of imagecopyresampled() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

114
                /** @scrutinizer ignore-type */ $img,
Loading history...
115
                0,
116
                0,
117
                0,
118
                0,
119
                $newWidth,
120
                $newHeight,
121
                $width,
122
                $height
123
            );
124
125
            \unlink($this->endFile);
126
127
            //compressing the file
128
129
            switch ($this->imageMimetype) {
130
                case 'image/png':
131
                    \imagepng($tmpimg, $this->endFile, 0);
0 ignored issues
show
Bug introduced by
It seems like $tmpimg can also be of type false; however, parameter $image of imagepng() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

131
                    \imagepng(/** @scrutinizer ignore-type */ $tmpimg, $this->endFile, 0);
Loading history...
132
                    break;
133
                case 'image/jpeg':
134
                    \imagejpeg($tmpimg, $this->endFile, 100);
0 ignored issues
show
Bug introduced by
It seems like $tmpimg can also be of type false; however, parameter $image of imagejpeg() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

134
                    \imagejpeg(/** @scrutinizer ignore-type */ $tmpimg, $this->endFile, 100);
Loading history...
135
                    break;
136
                case 'image/gif':
137
                    \imagegif($tmpimg, $this->endFile);
0 ignored issues
show
Bug introduced by
It seems like $tmpimg can also be of type false; however, parameter $image of imagegif() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

137
                    \imagegif(/** @scrutinizer ignore-type */ $tmpimg, $this->endFile);
Loading history...
138
                    break;
139
            }
140
141
            // release the memory
142
143
            \imagedestroy($tmpimg);
0 ignored issues
show
Bug introduced by
It seems like $tmpimg can also be of type false; however, parameter $image of imagedestroy() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

143
            \imagedestroy(/** @scrutinizer ignore-type */ $tmpimg);
Loading history...
144
        } else {
145
            return 'copy';
146
        }
147
148
        \imagedestroy($img);
149
150
        return true;
151
    }
152
153
    /**
154
     * @return bool|string
155
     */
156
157
    public function resizeAndCrop()
158
    {
159
        // check file extension
160
161
        switch ($this->imageMimetype) {
162
            case 'image/png':
163
                $original = \imagecreatefrompng($this->sourceFile);
164
                break;
165
            case 'image/jpeg':
166
                $original = \imagecreatefromjpeg($this->sourceFile);
167
                break;
168
            case 'image/gif':
169
                $original = \imagecreatefromgif($this->sourceFile);
170
                break;
171
            default:
172
                return 'Unsupported format';
173
        }
174
175
        if (!$original) {
0 ignored issues
show
introduced by
$original is of type false|resource, thus it always evaluated to false.
Loading history...
176
            return false;
177
        }
178
179
        // GET ORIGINAL IMAGE DIMENSIONS
180
181
        [$original_w, $original_h] = \getimagesize($this->sourceFile);
182
183
        // RESIZE IMAGE AND PRESERVE PROPORTIONS
184
185
        $max_width_resize = $this->maxWidth;
186
187
        $max_height_resize = $this->maxHeight;
188
189
        if ($original_w > $original_h) {
190
            $max_height_ratio = $this->maxHeight / $original_h;
191
192
            $max_width_resize = (int)\round($original_w * $max_height_ratio);
193
        } else {
194
            $max_width_ratio = $this->maxWidth / $original_w;
195
196
            $max_height_resize = (int)\round($original_h * $max_width_ratio);
197
        }
198
199
        if ($max_width_resize < $this->maxWidth) {
200
            $max_height_ratio = $this->maxWidth / $max_width_resize;
201
202
            $max_height_resize = (int)\round($this->maxHeight * $max_height_ratio);
203
204
            $max_width_resize = $this->maxWidth;
205
        }
206
207
        // CREATE THE PROPORTIONAL IMAGE RESOURCE
208
209
        $thumb = \imagecreatetruecolor($max_width_resize, $max_height_resize);
210
211
        if (!\imagecopyresampled(
212
            $thumb,
213
            $original,
214
            0,
215
            0,
216
            0,
217
            0,
218
            $max_width_resize,
219
            $max_height_resize,
220
            $original_w,
221
            $original_h
222
        )) {
223
            return false;
224
        }
225
226
        // CREATE THE CENTERED CROPPED IMAGE TO THE SPECIFIED DIMENSIONS
227
228
        $final = \imagecreatetruecolor(
229
            $this->maxWidth,
230
            $this->maxHeight
231
        );
232
233
        $max_width_offset = 0;
234
235
        $max_height_offset = 0;
236
237
        if ($this->maxWidth < $max_width_resize) {
238
            $max_width_offset = (int)\round(($max_width_resize - $this->maxWidth) / 2);
239
        } else {
240
            $max_height_offset = (int)\round(($max_height_resize - $this->maxHeight) / 2);
241
        }
242
243
        if (!\imagecopy(
244
            $final,
245
            $thumb,
246
            0,
247
            0,
248
            $max_width_offset,
249
            $max_height_offset,
250
            $max_width_resize,
251
            $max_height_resize
252
        )) {
253
            return false;
254
        }
255
256
        // STORE THE FINAL IMAGE - WILL OVERWRITE $this->endFile
257
258
        if (!\imagejpeg(
259
            $final,
260
            $this->endFile,
261
            $this->jpgQuality
262
        )) {
263
            return false;
264
        }
265
266
        return true;
267
    }
268
269
    public function mergeImage()
270
    {
271
        $dest = \imagecreatefromjpeg($this->endFile);
272
273
        $src = \imagecreatefromjpeg($this->sourceFile);
274
275
        if (4 === $this->mergeType) {
276
            $imgWidth = (int)\round($this->maxWidth / 2 - 1);
277
278
            $imgHeight = (int)\round($this->maxHeight / 2 - 1);
279
280
            $posCol2 = (int)\round($this->maxWidth / 2 + 1);
281
282
            $posRow2 = (int)\round($this->maxHeight / 2 + 1);
283
284
            switch ($this->mergePos) {
285
                case 1:
286
                    \imagecopy($dest, $src, 0, 0, 0, 0, $imgWidth, $imgHeight); //top left
0 ignored issues
show
Bug introduced by
It seems like $src can also be of type false; however, parameter $src_im of imagecopy() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

286
                    \imagecopy($dest, /** @scrutinizer ignore-type */ $src, 0, 0, 0, 0, $imgWidth, $imgHeight); //top left
Loading history...
Bug introduced by
It seems like $dest can also be of type false; however, parameter $dst_im of imagecopy() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

286
                    \imagecopy(/** @scrutinizer ignore-type */ $dest, $src, 0, 0, 0, 0, $imgWidth, $imgHeight); //top left
Loading history...
287
                    break;
288
                case 2:
289
                    \imagecopy($dest, $src, $posCol2, 0, 0, 0, $imgWidth, $imgHeight); //top right
290
                    break;
291
                case 3:
292
                    \imagecopy($dest, $src, 0, $posRow2, 0, 0, $imgWidth, $imgHeight); //bottom left
293
                    break;
294
                case 4:
295
                    \imagecopy($dest, $src, $posCol2, $posRow2, 0, 0, $imgWidth, $imgHeight); //bottom right
296
                    break;
297
            }
298
        }
299
300
        if (6 === $this->mergeType) {
301
            $imgWidth = (int)\round($this->maxWidth / 3 - 1);
302
303
            $imgHeight = (int)\round($this->maxHeight / 2 - 1);
304
305
            $posCol2 = (int)\round($this->maxWidth / 3 + 1);
306
307
            $posCol3 = $posCol2 + (int)\round($this->maxWidth / 3 + 1);
308
309
            $posRow2 = (int)\round($this->maxHeight / 2 + 1);
310
311
            switch ($this->mergePos) {
312
                case 1:
313
                    \imagecopy($dest, $src, 0, 0, 0, 0, $imgWidth, $imgHeight); //top left
314
                    break;
315
                case 2:
316
                    \imagecopy($dest, $src, $posCol2, 0, 0, 0, $imgWidth, $imgHeight); //top center
317
                    break;
318
                case 3:
319
                    \imagecopy($dest, $src, $posCol3, 0, 0, 0, $imgWidth, $imgHeight); //top right
320
                    break;
321
                case 4:
322
                    \imagecopy($dest, $src, 0, $posRow2, 0, 0, $imgWidth, $imgHeight); //bottom left
323
                    break;
324
                case 5:
325
                    \imagecopy($dest, $src, $posCol2, $posRow2, 0, 0, $imgWidth, $imgHeight); //bottom center
326
                    break;
327
                case 6:
328
                    \imagecopy($dest, $src, $posCol3, $posRow2, 0, 0, $imgWidth, $imgHeight); //bottom right
329
                    break;
330
            }
331
        }
332
333
        \imagejpeg($dest, $this->endFile);
0 ignored issues
show
Bug introduced by
It seems like $dest can also be of type false; however, parameter $image of imagejpeg() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

333
        \imagejpeg(/** @scrutinizer ignore-type */ $dest, $this->endFile);
Loading history...
334
335
        \imagedestroy($src);
0 ignored issues
show
Bug introduced by
It seems like $src can also be of type false; however, parameter $image of imagedestroy() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

335
        \imagedestroy(/** @scrutinizer ignore-type */ $src);
Loading history...
336
337
        \imagedestroy($dest);
338
    }
339
340
    /**
341
     * @return bool|string
342
     */
343
344
    public function rotateImage()
345
    {
346
        // check file extension
347
348
        switch ($this->imageMimetype) {
349
            case 'image/png':
350
                $original = \imagecreatefrompng($this->sourceFile);
351
                break;
352
            case 'image/jpeg':
353
                $original = \imagecreatefromjpeg($this->sourceFile);
354
                break;
355
            case 'image/gif':
356
                $original = \imagecreatefromgif($this->sourceFile);
357
                break;
358
            default:
359
                return 'Unsupported format';
360
        }
361
362
        if (!$original) {
0 ignored issues
show
introduced by
$original is of type false|resource, thus it always evaluated to false.
Loading history...
363
            return false;
364
        }
365
366
        // Rotate
367
368
        $tmpimg = \imagerotate($original, $this->degrees, 0);
369
370
        \unlink($this->endFile);
371
372
        //compressing the file
373
374
        switch ($this->imageMimetype) {
375
            case 'image/png':
376
                if (!\imagepng($tmpimg, $this->endFile, 0)) {
377
                    return false;
378
                }
379
                break;
380
            case 'image/jpeg':
381
                if (!\imagejpeg($tmpimg, $this->endFile, $this->jpgQuality)) {
382
                    return false;
383
                }
384
                break;
385
            case 'image/gif':
386
                if (!\imagegif($tmpimg, $this->endFile)) {
387
                    return false;
388
                }
389
                break;
390
        }
391
392
        // release the memory
393
394
        \imagedestroy($tmpimg);
395
396
        return true;
397
    }
398
}
399