Passed
Push — webservicelpcreate ( d8cb35 )
by
unknown
13:48
created

Image::crop()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 26
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 18
nc 2
nop 1
dl 0
loc 26
rs 9.6666
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
/**
5
 * Image class
6
 * This class provides a layer to manage images.
7
 *
8
 * @author Julio Montoya <[email protected]>
9
 *
10
 * @todo move in a DB configuration setting
11
 */
12
class Image
13
{
14
    public $image_wrapper = null;
15
16
    /**
17
     * Image constructor.
18
     *
19
     * @param string $path
20
     */
21
    public function __construct($path)
22
    {
23
        if (IMAGE_PROCESSOR == 'gd') {
24
            $this->image_wrapper = new GDWrapper($path);
25
        } else {
26
            if (class_exists('Imagick')) {
27
                $this->image_wrapper = new ImagickWrapper($path);
28
            } else {
29
                echo Display::return_message(
30
                    'Class Imagick not found',
31
                    'warning'
32
                );
33
                exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
34
            }
35
        }
36
    }
37
38
    public function resize($max_size_for_picture)
39
    {
40
        $image_size = $this->get_image_size($this->image_wrapper->path);
41
        $width = $image_size['width'];
42
        $height = $image_size['height'];
43
        if ($width >= $height) {
44
            if ($width >= $max_size_for_picture) {
45
                // scale height
46
                $new_height = round($height * ($max_size_for_picture / $width));
47
                $this->image_wrapper->resize(
48
                    $max_size_for_picture,
49
                    $new_height,
50
                    0
51
                );
52
            }
53
        } else { // height > $width
54
            if ($height >= $max_size_for_picture) {
55
                // scale width
56
                $new_width = round($width * ($max_size_for_picture / $height));
57
                $this->image_wrapper->resize(
58
                    $new_width,
59
                    $max_size_for_picture,
60
                    0
61
                );
62
            }
63
        }
64
    }
65
66
    /**
67
     * @param string $cropParameters
68
     *
69
     * @return bool
70
     */
71
    public function crop($cropParameters)
72
    {
73
        $image_size = $this->get_image_size($this->image_wrapper->path);
74
        $src_width = $image_size['width'];
75
        $src_height = $image_size['height'];
76
        $cropParameters = explode(',', $cropParameters);
77
78
        if (isset($cropParameters[0]) && isset($cropParameters[1])) {
79
            $x = intval($cropParameters[0]);
80
            $y = intval($cropParameters[1]);
81
            $width = intval($cropParameters[2]);
82
            $height = intval($cropParameters[3]);
83
84
            $image = $this->image_wrapper->crop(
85
                $x,
86
                $y,
87
                $width,
88
                $height,
89
                $src_width,
90
                $src_height
91
            );
92
93
            return $image;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $image also could return the type integer which is incompatible with the documented return type boolean.
Loading history...
94
        }
95
96
        return false;
97
    }
98
99
    /**
100
     * @param string $file
101
     * @param int    $compress
102
     * @param null   $convert_file_to
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $convert_file_to is correct as it would always require null to be passed?
Loading history...
103
     *
104
     * @return bool
105
     */
106
    public function send_image(
107
        $file = '',
108
        $compress = -1,
109
        $convert_file_to = null
110
    ) {
111
        return $this->image_wrapper->send_image(
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->image_wrap...ress, $convert_file_to) also could return the type integer which is incompatible with the documented return type boolean.
Loading history...
112
            $file,
113
            $compress,
114
            $convert_file_to
115
        );
116
    }
117
118
    /**
119
     * @return array
120
     */
121
    public function get_image_size()
122
    {
123
        return $this->image_wrapper->get_image_size();
124
    }
125
126
    /**
127
     * @return array
128
     */
129
    public function get_image_info()
130
    {
131
        return $this->image_wrapper->get_image_info();
132
    }
133
134
    public function convert2bw()
135
    {
136
        $this->image_wrapper->convert2bw();
137
    }
138
}
139
140
/**
141
 * Image wrapper class.
142
 */
143
abstract class ImageWrapper
144
{
145
    public $debug = true;
146
    public $path;
147
    public $width;
148
    public $height;
149
    public $type;
150
    public $allowed_extensions = ['jpeg', 'jpg', 'png', 'gif'];
151
    public $image_validated = false;
152
153
    public function __construct($path)
154
    {
155
        if (empty($path)) {
156
            return false;
157
        }
158
        $this->path = $path;
159
        $this->set_image_wrapper(); //Creates image obj
160
    }
161
162
    abstract public function set_image_wrapper();
163
164
    abstract public function fill_image_info();
165
166
    abstract public function get_image_size();
167
168
    abstract public function resize($thumbw, $thumbh, $border, $specific_size = false);
169
170
    abstract public function crop($x, $y, $width, $height, $src_width, $src_height);
171
172
    abstract public function send_image($file = '', $compress = -1, $convert_file_to = null);
173
174
    /**
175
     * @return array
176
     */
177
    public function get_image_info()
178
    {
179
        return [
180
            'width' => $this->width,
181
            'height' => $this->height,
182
            'type' => $this->type,
183
        ];
184
    }
185
}
186
187
/**
188
 * Imagick Chamilo wrapper.
189
 *
190
 * @author jmontoya
191
 */
192
class ImagickWrapper extends ImageWrapper
193
{
194
    public $image;
195
    public $filter = Imagick::FILTER_LANCZOS;
196
197
    /**
198
     * ImagickWrapper constructor.
199
     *
200
     * @param $path
201
     */
202
    public function __construct($path)
203
    {
204
        parent::__construct($path);
205
    }
206
207
    public function set_image_wrapper()
208
    {
209
        if ($this->debug) {
210
            error_log('Image::set_image_wrapper loaded');
211
        }
212
        try {
213
            if (file_exists($this->path)) {
214
                $this->image = new Imagick($this->path);
215
216
                if ($this->image) {
217
                    $this->fill_image_info(); //Fills height, width and type
218
                }
219
            } else {
220
                if ($this->debug) {
221
                    error_log('Image::image does not exist');
222
                }
223
            }
224
        } catch (ImagickException $e) {
225
            if ($this->debug) {
226
                error_log($e->getMessage());
227
            }
228
        }
229
    }
230
231
    public function fill_image_info()
232
    {
233
        $image_info = $this->image->identifyImage();
234
        $this->width = $image_info['geometry']['width'];
235
        $this->height = $image_info['geometry']['height'];
236
        $this->type = strtolower($this->image->getImageFormat());
237
238
        if (in_array($this->type, $this->allowed_extensions)) {
239
            $this->image_validated = true;
240
            if ($this->debug) {
241
                error_log('image_validated true');
242
            }
243
        }
244
    }
245
246
    public function get_image_size()
247
    {
248
        $imagesize = ['width' => 0, 'height' => 0];
249
        if ($this->image_validated) {
250
            $imagesize = $this->image->getImageGeometry();
251
        }
252
253
        return $imagesize;
254
    }
255
256
    //@todo implement border logic case for Imagick
257
    public function resize($thumbw, $thumbh, $border, $specific_size = false)
258
    {
259
        if (!$this->image_validated) {
260
            return false;
261
        }
262
263
        if ($specific_size) {
264
            $width = $thumbw;
265
            $height = $thumbh;
266
        } else {
267
            $scale = ($this->width > 0 && $this->height > 0) ? min($thumbw / $this->width, $thumbh / $this->height) : 0;
268
            $width = (int) ($this->width * $scale);
269
            $height = (int) ($this->height * $scale);
270
        }
271
        $result = $this->image->resizeImage($width, $height, $this->filter, 1);
272
        $this->width = $thumbw;
273
        $this->height = $thumbh;
274
    }
275
276
    /**
277
     * @author José Loguercio <[email protected]>
278
     *
279
     * @param int $x          coordinate of the cropped region top left corner
280
     * @param int $y          coordinate of the cropped region top left corner
281
     * @param int $width      the width of the crop
282
     * @param int $height     the height of the crop
283
     * @param int $src_width  the source width of the original image
284
     * @param int $src_height the source height of the original image
285
     *
286
     * @return bool
287
     */
288
    public function crop($x, $y, $width, $height, $src_width, $src_height)
289
    {
290
        if (!$this->image_validated) {
291
            return false;
292
        }
293
        $this->image->cropimage($width, $height, $x, $y);
294
        $this->width = $width;
295
        $this->height = $height;
296
297
        return true;
298
    }
299
300
    public function send_image(
301
        $file = '',
302
        $compress = -1,
303
        $convert_file_to = null
304
    ) {
305
        if (!$this->image_validated) {
306
            return false;
307
        }
308
        $type = $this->type;
309
        if (!empty($convert_file_to) && in_array($convert_file_to, $this->allowed_extensions)) {
310
            $type = $convert_file_to;
311
        }
312
        switch ($type) {
313
            case 'jpeg':
314
            case 'jpg':
315
                if (!$file) {
316
                    header("Content-type: image/jpeg");
317
                }
318
                break;
319
            case 'png':
320
                if (!$file) {
321
                    header("Content-type: image/png");
322
                }
323
                break;
324
            case 'gif':
325
                if (!$file) {
326
                    header("Content-type: image/gif");
327
                }
328
                break;
329
        }
330
        $result = false;
331
        try {
332
            $result = $this->image->writeImage($file);
333
        } catch (ImagickException $e) {
334
            if ($this->debug) {
335
                error_log($e->getMessage());
336
            }
337
        }
338
339
        if (!$file) {
340
            echo $this->image;
341
            $this->image->clear();
342
            $this->image->destroy();
343
        } else {
344
            $this->image->clear();
345
            $this->image->destroy();
346
347
            return $result;
348
        }
349
    }
350
}
351
352
/**
353
 * php-gd wrapper.
354
 */
355
class GDWrapper extends ImageWrapper
356
{
357
    public $bg;
358
359
    /**
360
     * GDWrapper constructor.
361
     *
362
     * @param $path
363
     */
364
    public function __construct($path)
365
    {
366
        parent::__construct($path);
367
    }
368
369
    public function set_image_wrapper()
370
    {
371
        $handler = null;
372
        $this->fill_image_info();
373
374
        switch ($this->type) {
375
            case 0:
376
                $handler = false;
377
                break;
378
            case 1:
379
                $handler = @imagecreatefromgif($this->path);
380
                $this->type = 'gif';
381
                break;
382
            case 2:
383
                $handler = @imagecreatefromjpeg($this->path);
384
                $this->type = 'jpg';
385
                break;
386
            case 3:
387
                $handler = @imagecreatefrompng($this->path);
388
                $this->type = 'png';
389
                break;
390
        }
391
        if ($handler) {
392
            $this->image_validated = true;
393
            $this->bg = $handler;
394
            @imagealphablending($this->bg, false);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for imagealphablending(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

394
            /** @scrutinizer ignore-unhandled */ @imagealphablending($this->bg, false);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
395
            @imagesavealpha($this->bg, true);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for imagesavealpha(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

395
            /** @scrutinizer ignore-unhandled */ @imagesavealpha($this->bg, true);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
396
        }
397
    }
398
399
    /**
400
     * @return array
401
     */
402
    public function get_image_size()
403
    {
404
        $return_array = ['width' => 0, 'height' => 0];
405
        if ($this->image_validated) {
406
            $return_array = ['width' => $this->width, 'height' => $this->height];
407
        }
408
409
        return $return_array;
410
    }
411
412
    public function fill_image_info()
413
    {
414
        if (file_exists($this->path)) {
415
            $image_info = getimagesize($this->path);
416
            $this->width = $image_info[0];
417
            $this->height = $image_info[1];
418
            $this->type = $image_info[2];
419
        } else {
420
            $this->width = 0;
421
            $this->height = 0;
422
            $this->type = 0;
423
        }
424
    }
425
426
    public function resize($thumbw, $thumbh, $border, $specific_size = false)
427
    {
428
        if (!$this->image_validated) {
429
            return false;
430
        }
431
        if (1 == $border) {
432
            if ($specific_size) {
433
                $width = $thumbw;
434
                $height = $thumbh;
435
            } else {
436
                $scale = min($thumbw / $this->width, $thumbh / $this->height);
437
                $width = (int) ($this->width * $scale);
438
                $height = (int) ($this->height * $scale);
439
            }
440
            $deltaw = (int) (($thumbw - $width) / 2);
441
            $deltah = (int) (($thumbh - $height) / 2);
442
            $dst_img = @ImageCreateTrueColor($thumbw, $thumbh);
443
            @imagealphablending($dst_img, false);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for imagealphablending(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

443
            /** @scrutinizer ignore-unhandled */ @imagealphablending($dst_img, false);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
444
            @imagesavealpha($dst_img, true);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for imagesavealpha(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

444
            /** @scrutinizer ignore-unhandled */ @imagesavealpha($dst_img, true);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
445
446
            if (!empty($this->color)) {
447
                @imagefill($dst_img, 0, 0, $this->color);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for imagefill(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

447
                /** @scrutinizer ignore-unhandled */ @imagefill($dst_img, 0, 0, $this->color);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
Bug Best Practice introduced by
The property color does not exist on GDWrapper. Did you maybe forget to declare it?
Loading history...
448
            }
449
            $this->width = $thumbw;
450
            $this->height = $thumbh;
451
        } elseif (0 == $border) {
452
            if ($specific_size) {
453
                $width = $thumbw;
454
                $height = $thumbh;
455
            } else {
456
                $scale = ($this->width > 0 && $this->height > 0) ? min($thumbw / $this->width, $thumbh / $this->height) : 0;
457
                $width = (int) ($this->width * $scale);
458
                $height = (int) ($this->height * $scale);
459
            }
460
            $deltaw = 0;
461
            $deltah = 0;
462
            $dst_img = @ImageCreateTrueColor($width, $height);
463
            @imagealphablending($dst_img, false);
464
            @imagesavealpha($dst_img, true);
465
            $this->width = $width;
466
            $this->height = $height;
467
        }
468
        $src_img = $this->bg;
469
        @ImageCopyResampled(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for imagecopyresampled(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

469
        /** @scrutinizer ignore-unhandled */ @ImageCopyResampled(

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
470
            $dst_img,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dst_img does not seem to be defined for all execution paths leading up to this point.
Loading history...
471
            $src_img,
472
            $deltaw,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $deltaw does not seem to be defined for all execution paths leading up to this point.
Loading history...
473
            $deltah,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $deltah does not seem to be defined for all execution paths leading up to this point.
Loading history...
474
            0,
475
            0,
476
            $width,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $width does not seem to be defined for all execution paths leading up to this point.
Loading history...
477
            $height,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $height does not seem to be defined for all execution paths leading up to this point.
Loading history...
478
            ImageSX($src_img),
479
            ImageSY($src_img)
480
        );
481
        $this->bg = $dst_img;
482
        @imagedestroy($src_img);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for imagedestroy(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

482
        /** @scrutinizer ignore-unhandled */ @imagedestroy($src_img);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
483
    }
484
485
    /**
486
     * @author José Loguercio <[email protected]>
487
     *
488
     * @param int $x          coordinate of the cropped region top left corner
489
     * @param int $y          coordinate of the cropped region top left corner
490
     * @param int $width      the width of the crop
491
     * @param int $height     the height of the crop
492
     * @param int $src_width  the source width of the original image
493
     * @param int $src_height the source height of the original image
494
     */
495
    public function crop($x, $y, $width, $height, $src_width, $src_height)
496
    {
497
        if (!$this->image_validated) {
498
            return false;
499
        }
500
        $this->width = $width;
501
        $this->height = $height;
502
        $src = null;
503
        $dest = @imagecreatetruecolor($width, $height);
504
        $type = $this->type;
505
        switch ($type) {
506
            case 'jpeg':
507
            case 'jpg':
508
                $src = @imagecreatefromjpeg($this->path);
509
                @imagecopy($dest, $src, 0, 0, $x, $y, $src_width, $src_height);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for imagecopy(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

509
                /** @scrutinizer ignore-unhandled */ @imagecopy($dest, $src, 0, 0, $x, $y, $src_width, $src_height);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
510
                @imagejpeg($dest, $this->path);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for imagejpeg(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

510
                /** @scrutinizer ignore-unhandled */ @imagejpeg($dest, $this->path);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
511
                break;
512
            case 'png':
513
                $src = @imagecreatefrompng($this->path);
514
                @imagealphablending($dest, false);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for imagealphablending(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

514
                /** @scrutinizer ignore-unhandled */ @imagealphablending($dest, false);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
515
                @imagesavealpha($dest, true);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for imagesavealpha(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

515
                /** @scrutinizer ignore-unhandled */ @imagesavealpha($dest, true);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
516
                @imagecopy($dest, $src, 0, 0, $x, $y, $src_width, $src_height);
517
                @imagepng($dest, $this->path);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for imagepng(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

517
                /** @scrutinizer ignore-unhandled */ @imagepng($dest, $this->path);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
518
                break;
519
            case 'gif':
520
                $src = @imagecreatefromgif($this->path);
521
                @imagecopy($dest, $src, 0, 0, $x, $y, $src_width, $src_height);
522
                @imagegif($dest, $this->path);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for imagegif(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

522
                /** @scrutinizer ignore-unhandled */ @imagegif($dest, $this->path);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
523
                break;
524
            default:
525
                return 0;
526
        }
527
        @imagedestroy($dest);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for imagedestroy(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

527
        /** @scrutinizer ignore-unhandled */ @imagedestroy($dest);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
528
        @imagedestroy($src);
529
    }
530
531
    /**
532
     * @param string $file
533
     * @param int    $compress
534
     * @param null   $convert_file_to
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $convert_file_to is correct as it would always require null to be passed?
Loading history...
535
     *
536
     * @return bool|int
537
     */
538
    public function send_image($file = '', $compress = -1, $convert_file_to = null)
539
    {
540
        if (!$this->image_validated) {
541
            return false;
542
        }
543
        $compress = (int) $compress;
544
        $type = $this->type;
545
        if (!empty($convert_file_to) && in_array($convert_file_to, $this->allowed_extensions)) {
546
            $type = $convert_file_to;
547
        }
548
        switch ($type) {
549
            case 'jpeg':
550
            case 'jpg':
551
                if (!$file) {
552
                    header("Content-type: image/jpeg");
553
                }
554
                if (-1 == $compress) {
555
                    $compress = 100;
556
                }
557
558
                return imagejpeg($this->bg, $file, $compress);
559
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
560
            case 'png':
561
                if (!$file) {
562
                    header("Content-type: image/png");
563
                }
564
                if (-1 != $compress) {
565
                    @imagetruecolortopalette($this->bg, true, $compress);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for imagetruecolortopalette(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

565
                    /** @scrutinizer ignore-unhandled */ @imagetruecolortopalette($this->bg, true, $compress);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
566
                }
567
568
                return imagepng($this->bg, $file, $compress);
569
                break;
570
            case 'gif':
571
                if (!$file) {
572
                    header("Content-type: image/gif");
573
                }
574
                if (-1 != $compress) {
575
                    @imagetruecolortopalette($this->bg, true, $compress);
576
                }
577
578
                return imagegif($this->bg, $file, $compress);
579
                break;
580
            default:
581
                return 0;
582
        }
583
        // TODO: Occupied memory is not released, because the following fragment of code is actually dead.
584
        @imagedestroy($this->bg);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for imagedestroy(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

584
        /** @scrutinizer ignore-unhandled */ @imagedestroy($this->bg);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
Unused Code introduced by
@imagedestroy($this->bg) is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
585
    }
586
587
    /**
588
     * Convert image to black & white.
589
     */
590
    public function convert2bw()
591
    {
592
        if (!$this->image_validated) {
593
            return false;
594
        }
595
596
        $dest_img = imagecreatetruecolor(imagesx($this->bg), imagesy($this->bg));
597
        /* copy ignore the transparent color
598
         * so that we can use black (0,0,0) as transparent, which is what
599
         * the image is filled with when created.
600
         */
601
        $transparent = imagecolorallocate($dest_img, 0, 0, 0);
602
        imagealphablending($dest_img, false);
603
        imagesavealpha($dest_img, true);
604
        imagecolortransparent($dest_img, $transparent);
605
        imagecopy(
606
            $dest_img,
607
            $this->bg,
608
            0,
609
            0,
610
            0,
611
            0,
612
            imagesx($this->bg),
613
            imagesx($this->bg)
614
        );
615
        imagefilter($dest_img, IMG_FILTER_GRAYSCALE);
616
        $this->bg = $dest_img;
617
618
        return true;
619
    }
620
}
621