Image::grayscaleFilter()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 1
c 1
b 0
f 1
dl 0
loc 3
rs 10
ccs 0
cts 2
cp 0
cc 1
nc 1
nop 0
crap 2
1
<?php
2
3
namespace Nip\Filesystem;
4
5
/**
6
 * Nip Framework
7
 *
8
 * @category   Nip
9
 * @copyright  2009 Nip Framework
10
 * @license    http://www.opensource.org/licenses/mit-license.php The MIT License
11
 * @version    SVN: $Id: Image.php 193 2009-06-23 23:11:53Z victorstanciu $
12
 */
13
class Image extends File
14
{
15
    public $extensions = ["jpg", "jpeg", "gif", "png"];
16
    public $quality = 90;
17
    public $type = 'jpg';
18
    public $max_width = false;
19
    public $errors = [];
20
    protected $_resource;
21
    protected $_file;
22
    protected $_upload;
23
    protected $_width;
24
    protected $_height;
25
26
    /**
27
     * @param array $upload
28
     */
29
    public function setResourceFromUpload($upload)
30
    {
31
        $this->_upload = $upload;
32
        $this->setResourceFromFile($upload['tmp_name']);
33
    }
34
35
    /**
36
     * @param string $path
37
     * @return bool
38
     */
39
    public function setResourceFromFile($path)
40
    {
41
        $this->_file = $path;
42
        if (file_exists($path)) {
43
            $details = getimagesize($path);
44
            switch ($details['mime']) {
45
                case 'image/gif':
46
                    $this->type = 'gif';
47
                    if (imagetypes() & IMG_GIF) {
48
                        $this->_resource = imagecreatefromgif($path);
49
                    }
50
                    break;
51
                case 'image/jpeg':
52
                    $this->type = 'jpg';
53
                    if (imagetypes() & IMG_JPG) {
54
                        $this->_resource = imagecreatefromjpeg($path);
55
                    }
56
                    break;
57
                case 'image/png':
58
                    $this->type = 'png';
59
                    if (imagetypes() & IMG_PNG) {
60
                        $this->_resource = imagecreatefrompng($path);
61
                    }
62
                    break;
63
            }
64
            $this->getWidth();
65
            $this->getHeight();
66
67
            return true;
68
        } else {
69
            trigger_error("Cannot find file $path", E_USER_ERROR);
70
        }
71
72
        return false;
73
    }
74
75
    /**
76
     * @return int
77
     */
78
    public function getWidth()
79
    {
80
        if (!$this->_width && $this->_resource) {
81
            $this->setWidth(imagesx($this->_resource));
82
        }
83
84
        return $this->_width;
85
    }
86
87
    /**
88
     * @param int $width
89
     */
90
    public function setWidth($width)
91
    {
92
        $this->_width = $width;
93
    }
94
95
    /**
96
     * @return int
97
     */
98
    public function getHeight()
99
    {
100
        if (!$this->_height && $this->_resource) {
101
            $this->setHeight(imagesy($this->_resource));
102
        }
103
104
        return $this->_height;
105
    }
106
107
    /**
108
     * @param int $height
109
     */
110
    public function setHeight($height)
111
    {
112
        $this->_height = $height;
113
    }
114
115
    /**
116
     * @param string $name
117
     */
118
    public function setBaseName($name)
119
    {
120
        $name = $name . '.' . $this->type;
121
        $this->setName($name);
122
    }
123
124
    /**
125
     * @param string $name
126
     */
127
    public function setName($name)
128
    {
129
        $this->name = $name;
130
        $this->url = dirname($this->url) . '/' . $this->name;
131
        $this->path = dirname($this->path) . '/' . $this->name;
132
    }
133
134
    /**
135
     * @return bool
136
     */
137
    public function save()
138
    {
139
        if (Nip_File_System::instance()->createDirectory(dirname($this->path))) {
0 ignored issues
show
Bug introduced by
The type Nip\Filesystem\Nip_File_System was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
140
            switch ($this->type) {
141
                case 'png':
142
                    if ($this->quality > 9) {
143
                        if ($this->quality < 100) {
144
                            $this->quality = $this->quality / 10;
145
                        } else {
146
                            $this->quality = 9;
147
                        }
148
                    }
149
                    $this->quality = abs($this->quality - 9);
150
                    $this->quality = 0;
151
                    $newImg = imagecreatetruecolor($this->_width, $this->_height);
152
                    imagealphablending($newImg, false);
153
                    imagesavealpha($newImg, true);
154
                    imagecopyresampled($newImg, $this->_resource, 0, 0, 0, 0, $this->_width, $this->_height,
155
                        $this->_width, $this->_height);
156
                    $return = imagepng($newImg, $this->path, $this->quality);
157
                    break;
158
                case 'jpg':
159
                default:
160
                    $return = imagejpeg($this->_resource, $this->path, $this->quality);
161
                    break;
162
            }
163
            if ($return) {
164
                chmod($this->path, 0777);
165
                return true;
166
            }
167
            $this->errors[] = 'Error saving file';
168
        } else {
169
            $this->errors[] = 'Error creating directory';
170
        }
171
        return false;
172
    }
173
174
    public function grayscaleFade()
175
    {
176
        $this->grayscaleFilter();
177
        imagefilter($this->_resource, IMG_FILTER_BRIGHTNESS, 50);
178
    }
179
180
    public function grayscaleFilter()
181
    {
182
        imagefilter($this->_resource, IMG_FILTER_GRAYSCALE);
183
    }
184
185
    public function resize($max_width = false, $max_height = false)
186
    {
187
        if (!$max_width) {
188
            if ($this->max_width) {
189
                $max_width = $this->max_width;
190
            } else {
191
                $max_width = $this->getWidth();
192
            }
193
        }
194
        if (!$max_height) {
195
            if ($this->max_height) {
0 ignored issues
show
Bug introduced by
The property max_height does not exist on Nip\Filesystem\Image. Did you mean _height?
Loading history...
196
                $max_height = $this->max_height;
197
            } else {
198
                $max_height = $this->getHeight();
199
            }
200
        }
201
        $ratio = $this->getRatio();
202
        $target_ratio = $max_width / $max_height;
203
        if ($ratio > $target_ratio) {
204
            $new_width = $max_width;
205
            $new_height = round($max_width / $ratio);
206
        } else {
207
            $new_height = $max_height;
208
            $new_width = round($max_height * $ratio);
209
        }
210
        $image = imagecreatetruecolor($new_width, $new_height);
211
        imagealphablending($image, false);
212
        imagesavealpha($image, true);
213
        imagecopyresampled($image, $this->_resource, 0, 0, 0, 0, $new_width, $new_height, $this->getWidth(),
214
            $this->getHeight());
215
        $this->_width = $new_width;
216
        $this->_height = $new_height;
217
        $this->_resource = $image;
218
219
        return $this;
220
    }
221
222
    public function getRatio()
223
    {
224
        return $this->getWidth() / $this->getHeight();
225
    }
226
227
    public function cropToCenter($cWidth, $cHeight)
228
    {
229
        $this->resizeToLarge($cWidth, $cHeight);
230
        $width = $this->getWidth();
231
        $height = $this->getHeight();
232
        $x0 = round(abs(($width - $cWidth) / 2), 0);
233
        $y0 = round(abs(($height - $cHeight) / 2), 0);
234
        $this->crop($x0, $y0, $cWidth, $cHeight, $cWidth, $cHeight);
235
    }
236
237
    /**
238
     * @param bool|int $max_width
239
     * @param bool|int $max_height
240
     * @return $this
241
     */
242
    public function resizeToLarge($max_width = false, $max_height = false)
243
    {
244
        if (!$max_width) {
245
            $max_width = $this->getWidth();
246
        }
247
        if (!$max_height) {
248
            $max_height = $this->getHeight();
249
        }
250
        $sourceRatio = $this->getRatio();
251
        $target_ratio = $max_width / $max_height;
252
        if ($sourceRatio > $target_ratio) {
253
            $new_height = $max_height;
254
            $new_width = (int)($max_height * $sourceRatio);
255
        } else {
256
            $new_width = $max_width;
257
            $new_height = (int)($max_width / $sourceRatio);
258
        }
259
        $image = imagecreatetruecolor($new_width, $new_height);
0 ignored issues
show
Bug introduced by
It seems like $new_height can also be of type boolean; however, parameter $height of imagecreatetruecolor() does only seem to accept integer, 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

259
        $image = imagecreatetruecolor($new_width, /** @scrutinizer ignore-type */ $new_height);
Loading history...
Bug introduced by
It seems like $new_width can also be of type boolean; however, parameter $width of imagecreatetruecolor() does only seem to accept integer, 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

259
        $image = imagecreatetruecolor(/** @scrutinizer ignore-type */ $new_width, $new_height);
Loading history...
260
        imagealphablending($image, false);
261
        imagesavealpha($image, true);
262
        imagecopyresampled($image, $this->_resource, 0, 0, 0, 0, $new_width, $new_height, $this->getWidth(),
0 ignored issues
show
Bug introduced by
It seems like $new_height can also be of type boolean; however, parameter $dst_h of imagecopyresampled() does only seem to accept integer, 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

262
        imagecopyresampled($image, $this->_resource, 0, 0, 0, 0, $new_width, /** @scrutinizer ignore-type */ $new_height, $this->getWidth(),
Loading history...
Bug introduced by
It seems like $new_width can also be of type boolean; however, parameter $dst_w of imagecopyresampled() does only seem to accept integer, 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

262
        imagecopyresampled($image, $this->_resource, 0, 0, 0, 0, /** @scrutinizer ignore-type */ $new_width, $new_height, $this->getWidth(),
Loading history...
263
            $this->getHeight());
264
        $this->_width = $new_width;
265
        $this->_height = $new_height;
266
        $this->_resource = $image;
267
268
        return $this;
269
    }
270
271
    /**
272
     * @param double $x
273
     * @param double $y
274
     * @param $dwidth
275
     * @param $dheight
276
     * @param $swidth
277
     * @param $sheight
278
     */
279
    public function crop($x, $y, $dwidth, $dheight, $swidth, $sheight)
280
    {
281
        $image = imagecreatetruecolor($dwidth, $dheight);
282
        imagealphablending($image, false);
283
        imagesavealpha($image, true);
284
        imagecopyresampled($image, $this->_resource,
285
            0, 0,
286
            $x, $y,
0 ignored issues
show
Bug introduced by
$x of type double is incompatible with the type integer expected by parameter $src_x of imagecopyresampled(). ( Ignorable by Annotation )

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

286
            /** @scrutinizer ignore-type */ $x, $y,
Loading history...
Bug introduced by
$y of type double is incompatible with the type integer expected by parameter $src_y of imagecopyresampled(). ( Ignorable by Annotation )

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

286
            $x, /** @scrutinizer ignore-type */ $y,
Loading history...
287
            $dwidth, $dheight,
288
            $swidth, $sheight);
289
        $this->_width = $dwidth;
290
        $this->_height = $dheight;
291
        $this->_resource = $image;
292
    }
293
294
    /**
295
     * @param int $amount
296
     * @param float $radius
297
     * @param int $threshold
298
     * @return $this
299
     */
300
    public function unsharpMask($amount = 80, $radius = 0.5, $threshold = 3)
301
    {
302
        $img = &$this->_resource;
303
        if ($amount > 500) {
304
            $amount = 500;
305
        }
306
        $amount = $amount * 0.016;
307
        if ($radius > 50) {
308
            $radius = 50;
309
        }
310
        $radius = $radius * 2;
311
        if ($threshold > 255) {
312
            $threshold = 255;
313
        }
314
        $radius = abs(round($radius));
315
        if ($radius == 0) {
316
            return;
317
        }
318
        $w = $this->_width;
319
        $h = $this->_height;
320
        $imgCanvas = imagecreatetruecolor($w, $h);
321
        $imgBlur = imagecreatetruecolor($w, $h);
322
        if (function_exists('imageconvolution')) {
323
            $matrix = [[1, 2, 1], [2, 4, 2], [1, 2, 1]];
324
            imagecopy($imgBlur, $img, 0, 0, 0, 0, $w, $h);
325
            imageconvolution($imgBlur, $matrix, 16, 0);
326
        } else {
327
            for ($i = 0; $i < $radius; $i++) {
328
                imagecopy($imgBlur, $img, 0, 0, 1, 0, $w - 1, $h);
329
                imagecopymerge($imgBlur, $img, 1, 0, 0, 0, $w, $h, 50);
330
                imagecopymerge($imgBlur, $img, 0, 0, 0, 0, $w, $h, 50);
331
                imagecopy($imgCanvas, $imgBlur, 0, 0, 0, 0, $w, $h);
332
                imagecopymerge($imgBlur, $imgCanvas, 0, 0, 0, 1, $w, $h - 1, 33.33333);
0 ignored issues
show
Bug introduced by
33.33333 of type double is incompatible with the type integer expected by parameter $pct of imagecopymerge(). ( Ignorable by Annotation )

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

332
                imagecopymerge($imgBlur, $imgCanvas, 0, 0, 0, 1, $w, $h - 1, /** @scrutinizer ignore-type */ 33.33333);
Loading history...
333
                imagecopymerge($imgBlur, $imgCanvas, 0, 1, 0, 0, $w, $h, 25);
334
            }
335
        }
336
        if ($threshold > 0) {
337
            for ($x = 0; $x < $w - 1; $x++) {
338
                for ($y = 0; $y < $h; $y++) {
339
                    $rgbOrig = ImageColorAt($img, $x, $y);
340
                    $rOrig = (($rgbOrig >> 16) & 0xFF);
341
                    $gOrig = (($rgbOrig >> 8) & 0xFF);
342
                    $bOrig = ($rgbOrig & 0xFF);
343
                    $rgbBlur = ImageColorAt($imgBlur, $x, $y);
344
                    $rBlur = (($rgbBlur >> 16) & 0xFF);
345
                    $gBlur = (($rgbBlur >> 8) & 0xFF);
346
                    $bBlur = ($rgbBlur & 0xFF);
347
                    $rNew = (abs($rOrig - $rBlur) >= $threshold) ? max(0,
348
                        min(255, ($amount * ($rOrig - $rBlur)) + $rOrig)) : $rOrig;
349
                    $gNew = (abs($gOrig - $gBlur) >= $threshold) ? max(0,
350
                        min(255, ($amount * ($gOrig - $gBlur)) + $gOrig)) : $gOrig;
351
                    $bNew = (abs($bOrig - $bBlur) >= $threshold) ? max(0,
352
                        min(255, ($amount * ($bOrig - $bBlur)) + $bOrig)) : $bOrig;
353
                    if (($rOrig != $rNew) || ($gOrig != $gNew) || ($bOrig != $bNew)) {
354
                        $pixCol = ImageColorAllocate($img, $rNew, $gNew, $bNew);
355
                        ImageSetPixel($img, $x, $y, $pixCol);
356
                    }
357
                }
358
            }
359
        } else {
360
            for ($x = 0; $x < $w; $x++) {
361
                for ($y = 0; $y < $h; $y++) {
362
                    $rgbOrig = ImageColorAt($img, $x, $y);
363
                    $rOrig = (($rgbOrig >> 16) & 0xFF);
364
                    $gOrig = (($rgbOrig >> 8) & 0xFF);
365
                    $bOrig = ($rgbOrig & 0xFF);
366
                    $rgbBlur = ImageColorAt($imgBlur, $x, $y);
367
                    $rBlur = (($rgbBlur >> 16) & 0xFF);
368
                    $gBlur = (($rgbBlur >> 8) & 0xFF);
369
                    $bBlur = ($rgbBlur & 0xFF);
370
                    $rNew = ($amount * ($rOrig - $rBlur)) + $rOrig;
371
                    if ($rNew > 255) {
372
                        $rNew = 255;
373
                    } elseif ($rNew < 0) {
374
                        $rNew = 0;
375
                    }
376
                    $gNew = ($amount * ($gOrig - $gBlur)) + $gOrig;
377
                    if ($gNew > 255) {
378
                        $gNew = 255;
379
                    } elseif ($gNew < 0) {
380
                        $gNew = 0;
381
                    }
382
                    $bNew = ($amount * ($bOrig - $bBlur)) + $bOrig;
383
                    if ($bNew > 255) {
384
                        $bNew = 255;
385
                    } elseif ($bNew < 0) {
386
                        $bNew = 0;
387
                    }
388
                    $rgbNew = ($rNew << 16) + ($gNew << 8) + $bNew;
389
                    ImageSetPixel($img, $x, $y, $rgbNew);
0 ignored issues
show
Bug introduced by
$rgbNew of type double is incompatible with the type integer expected by parameter $color of imagesetpixel(). ( Ignorable by Annotation )

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

389
                    ImageSetPixel($img, $x, $y, /** @scrutinizer ignore-type */ $rgbNew);
Loading history...
390
                }
391
            }
392
        }
393
        imagedestroy($imgCanvas);
394
        imagedestroy($imgBlur);
395
396
        return $this;
397
    }
398
399
    /**
400
     * @param Image $image
401
     * @return $this
402
     */
403
    public function copyResource($image)
404
    {
405
        $this->_width = $image->getWidth();
406
        $this->_height = $image->getHeight();
407
        $this->_resource = $image->getResource();
408
409
        return $this;
410
    }
411
412
    public function getResource()
413
    {
414
        return $this->_resource;
415
    }
416
417
    public function setResource($gdImage)
418
    {
419
        $this->_resource = $gdImage;
420
    }
421
422
    /**
423
     * @return string
424
     */
425
    public function getFile()
426
    {
427
        return $this->_file;
428
    }
429
430
    /**
431
     * @return string
432
     */
433
    public function getExtension()
434
    {
435
        return Nip_File_System::instance()->getExtension($this->path);
436
    }
437
}
438