• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JBZoo / Image / 5690120419

pending completion
5690120419

push

github

web-flow
Release v7 (#30)

531 of 590 relevant lines covered (90.0%)

66.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.54
/src/Filter.php
1
<?php
2

3
/**
4
 * JBZoo Toolbox - Image.
5
 *
6
 * This file is part of the JBZoo Toolbox project.
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 *
10
 * @license    MIT
11
 * @copyright  Copyright (C) JBZoo.com, All rights reserved.
12
 * @see        https://github.com/JBZoo/Image
13
 */
14

15
declare(strict_types=1);
16

17
namespace JBZoo\Image;
18

19
use JBZoo\Utils\Filter as VarFilter;
20
use JBZoo\Utils\Image as Helper;
21
use JBZoo\Utils\Vars;
22

23
/**
24
 * @SuppressWarnings(PHPMD.TooManyPublicMethods)
25
 */
26
final class Filter
27
{
28
    public const BLUR_SEL  = 0;
29
    public const BLUR_GAUS = 1;
30

31
    private const DEFAULT_BACKGROUND = '#000000';
32
    private const MAX_PERCENT        = 100;
33

34
    /**
35
     * Add sepia effect (emulation).
36
     */
37
    public static function sepia(\GdImage $image): void
38
    {
39
        self::grayscale($image);
4✔
40
        \imagefilter($image, \IMG_FILTER_COLORIZE, 100, 50, 0);
4✔
41
    }
42

43
    /**
44
     * Add grayscale effect.
45
     */
46
    public static function grayscale(\GdImage $image): void
47
    {
48
        \imagefilter($image, \IMG_FILTER_GRAYSCALE);
8✔
49
    }
50

51
    /**
52
     * Pixelate effect.
53
     * @param int $blockSize Size in pixels of each resulting block
54
     */
55
    public static function pixelate(\GdImage $image, int $blockSize = 10): void
56
    {
57
        $blockSize = VarFilter::int($blockSize);
4✔
58
        \imagefilter($image, \IMG_FILTER_PIXELATE, $blockSize);
4✔
59
    }
60

61
    /**
62
     * Edge Detect.
63
     */
64
    public static function edges(\GdImage $image): void
65
    {
66
        \imagefilter($image, \IMG_FILTER_EDGEDETECT);
4✔
67
    }
68

69
    /**
70
     * Emboss.
71
     */
72
    public static function emboss(\GdImage $image): void
73
    {
74
        \imagefilter($image, \IMG_FILTER_EMBOSS);
4✔
75
    }
76

77
    /**
78
     * Negative.
79
     */
80
    public static function invert(\GdImage $image): void
81
    {
82
        \imagefilter($image, \IMG_FILTER_NEGATE);
4✔
83
    }
84

85
    /**
86
     * Blur effect.
87
     * @param int $passes Number of times to apply the filter
88
     * @param int $type   BLUR_SEL|BLUR_GAUS
89
     */
90
    public static function blur(\GdImage $image, int $passes = 1, int $type = self::BLUR_SEL): void
91
    {
92
        $passes = Helper::blur($passes);
8✔
93

94
        $filterType = \IMG_FILTER_SELECTIVE_BLUR;
8✔
95
        if ($type === self::BLUR_GAUS) {
8✔
96
            $filterType = \IMG_FILTER_GAUSSIAN_BLUR;
4✔
97
        }
98

99
        for ($i = 0; $i < $passes; $i++) {
8✔
100
            \imagefilter($image, $filterType);
8✔
101
        }
102
    }
103

104
    /**
105
     * Change brightness.
106
     * @param int $level Darkest = -255, lightest = 255
107
     */
108
    public static function brightness(\GdImage $image, int $level): void
109
    {
110
        \imagefilter($image, \IMG_FILTER_BRIGHTNESS, Helper::brightness($level));
8✔
111
    }
112

113
    /**
114
     * Change contrast.
115
     * @param int $level Min = -100, max = 100
116
     */
117
    public static function contrast(\GdImage $image, int $level): void
118
    {
119
        \imagefilter($image, \IMG_FILTER_CONTRAST, Helper::contrast($level));
4✔
120
    }
121

122
    /**
123
     * @param string $color   Hex color string, array(red, green, blue) or array(red, green, blue, alpha).
124
     *                        Where red, green, blue - integers 0-255, alpha - integer 0-127
125
     * @param float  $opacity 0-100
126
     */
127
    public static function colorize(\GdImage $image, string $color, float $opacity): void
128
    {
129
        $rgba  = Helper::normalizeColor($color);
4✔
130
        $alpha = Helper::opacity2Alpha($opacity);
4✔
131

132
        $red   = Helper::color($rgba[0]);
4✔
133
        $green = Helper::color($rgba[1]);
4✔
134
        $blue  = Helper::color($rgba[2]);
4✔
135

136
        \imagefilter($image, \IMG_FILTER_COLORIZE, $red, $green, $blue, $alpha);
4✔
137
    }
138

139
    /**
140
     * Mean Remove.
141
     */
142
    public static function meanRemove(\GdImage $image): void
143
    {
144
        \imagefilter($image, \IMG_FILTER_MEAN_REMOVAL);
4✔
145
    }
146

147
    /**
148
     * Smooth effect.
149
     * @param int $passes Number of times to apply the filter (1 - 2048)
150
     */
151
    public static function smooth(\GdImage $image, int $passes = 1): void
152
    {
153
        \imagefilter($image, \IMG_FILTER_SMOOTH, Helper::smooth($passes));
4✔
154
    }
155

156
    /**
157
     * Desaturate.
158
     * @param int $percent level of desaturization
159
     */
160
    public static function desaturate(\GdImage $image, int $percent = 100): \GdImage
161
    {
162
        // Determine percentage
163
        $percent = Helper::percent($percent);
8✔
164
        $width   = \imagesx($image);
8✔
165
        $height  = \imagesy($image);
8✔
166

167
        if ($percent === self::MAX_PERCENT) {
8✔
168
            self::grayscale($image);
4✔
169
        } else {
170
            $newImage = \imagecreatetruecolor($width, $height);
4✔
171
            if ($newImage !== false) { // Make a desaturated copy of the image
4✔
172
                \imagealphablending($newImage, false);
4✔
173
                \imagecopy($newImage, $image, 0, 0, 0, 0, $width, $height);
4✔
174
                \imagefilter($newImage, \IMG_FILTER_GRAYSCALE);
4✔
175

176
                // Merge with specified percentage
177
                Helper::imageCopyMergeAlpha(
4✔
178
                    $image,
2✔
179
                    $newImage,
2✔
180
                    [0, 0],
2✔
181
                    [0, 0],
2✔
182
                    [$width, $height],
2✔
183
                    $percent,
2✔
184
                );
2✔
185

186
                return $newImage;
4✔
187
            }
188
            throw new Exception("Can't handle image resource by 'imagecreatetruecolor'");
×
189
        }
190

191
        return $image;
4✔
192
    }
193

194
    /**
195
     * Changes the opacity level of the image.
196
     * @param float|int $opacity 0-1 or 0-100
197
     */
198
    public static function opacity(\GdImage $image, float|int $opacity): \GdImage
199
    {
200
        // Determine opacity
201
        $opacity = Helper::opacity($opacity);
16✔
202

203
        $width  = \imagesx($image);
16✔
204
        $height = \imagesy($image);
16✔
205

206
        $newImage = \imagecreatetruecolor($width, $height);
16✔
207
        if ($newImage !== false) {
16✔
208
            // Set a White & Transparent Background Color
209
            $background = \imagecolorallocatealpha($newImage, 0, 0, 0, 127);
16✔
210
            if ($background !== false) {
16✔
211
                \imagefill($newImage, 0, 0, $background);
16✔
212

213
                // Copy and merge
214
                Helper::imageCopyMergeAlpha(
16✔
215
                    $newImage,
8✔
216
                    $image,
8✔
217
                    [0, 0],
8✔
218
                    [0, 0],
8✔
219
                    [$width, $height],
8✔
220
                    $opacity,
8✔
221
                );
8✔
222

223
                \imagedestroy($image);
16✔
224

225
                return $newImage;
16✔
226
            }
227

228
            throw new Exception('Image resourced can\'t be handle by "imagecolorallocatealpha"');
×
229
        }
230

231
        throw new Exception('Image resourced can\'t be handle by "imagecreatetruecolor"');
×
232
    }
233

234
    /**
235
     * Rotate an image.
236
     * @param int          $angle   -360 < x < 360
237
     * @param array|string $bgColor Hex color string, array(red, green, blue) or array(red, green, blue,
238
     *                              alpha). Where red, green, blue - integers 0-255, alpha - integer 0-127
239
     */
240
    public static function rotate(
241
        \GdImage $image,
242
        int $angle,
243
        array|string $bgColor = self::DEFAULT_BACKGROUND,
244
    ): \GdImage {
245
        // Perform the rotation
246
        $angle = Helper::rotate($angle);
12✔
247
        $rgba  = Helper::normalizeColor($bgColor);
12✔
248

249
        $newBgColor = (int)\imagecolorallocatealpha($image, $rgba[0], $rgba[1], $rgba[2], $rgba[3]);
12✔
250
        $newImage   = \imagerotate($image, -$angle, $newBgColor);
12✔
251
        if ($newImage === false) {
12✔
252
            throw new Exception("Image can't be rotated");
×
253
        }
254

255
        Helper::addAlpha($newImage);
12✔
256

257
        return $newImage;
12✔
258
    }
259

260
    /**
261
     * Flip an image horizontally or vertically.
262
     *
263
     * @param \GdImage $image     GD resource
264
     * @param string   $direction Direction of flipping - x|y|yx|xy
265
     */
266
    public static function flip(\GdImage $image, string $direction): \GdImage
267
    {
268
        $direction = Helper::direction($direction);
16✔
269

270
        $width  = \imagesx($image);
16✔
271
        $height = \imagesy($image);
16✔
272

273
        $newImage = \imagecreatetruecolor($width, $height);
16✔
274
        if ($newImage !== false) {
16✔
275
            Helper::addAlpha($newImage);
16✔
276

277
            if ($direction === 'y') {
16✔
278
                for ($y = 0; $y < $height; $y++) {
12✔
279
                    \imagecopy($newImage, $image, 0, $y, 0, $height - $y - 1, $width, 1);
12✔
280
                }
281
            } elseif ($direction === 'x') {
12✔
282
                for ($x = 0; $x < $width; $x++) {
12✔
283
                    \imagecopy($newImage, $image, $x, 0, $width - $x - 1, 0, 1, $height);
12✔
284
                }
285
            } elseif ($direction === 'xy' || $direction === 'yx') {
8✔
286
                $newImage = self::flip($image, 'x');
8✔
287
                $newImage = self::flip($newImage, 'y');
8✔
288
            }
289

290
            return $newImage;
16✔
291
        }
292

293
        throw new Exception("Image resource can't be handle by \"imagecreatetruecolor\"");
×
294
    }
295

296
    /**
297
     * Fill image with color.
298
     *
299
     * @param \GdImage     $image GD resource
300
     * @param array|string $color Hex color string, array(red, green, blue) or array(red, green, blue,
301
     *                            alpha). Where red, green, blue - integers 0-255, alpha - integer 0-127
302
     */
303
    public static function fill(\GdImage $image, array|string $color = self::DEFAULT_BACKGROUND): void
304
    {
305
        $width  = \imagesx($image);
4✔
306
        $height = \imagesy($image);
4✔
307

308
        $rgba      = Helper::normalizeColor($color);
4✔
309
        $fillColor = (int)\imagecolorallocatealpha($image, $rgba[0], $rgba[1], $rgba[2], $rgba[3]);
4✔
310

311
        Helper::addAlpha($image, false);
4✔
312
        \imagefilledrectangle($image, 0, 0, $width, $height, $fillColor);
4✔
313
    }
314

315
    /**
316
     * Add text to an image.
317
     *
318
     * @param \GdImage $image    GD resource
319
     * @param string   $text     Some text to output on image as watermark
320
     * @param string   $fontFile TTF font file path
321
     */
322
    public static function text(\GdImage $image, string $text, string $fontFile, array $params = []): void
323
    {
324
        Text::render($image, $text, $fontFile, $params);
40✔
325
    }
326

327
    /**
328
     * Add border to an image.
329
     * @param array $params Some
330
     */
331
    public static function border(\GdImage $image, array $params = []): void
332
    {
333
        $params = \array_merge([
16✔
334
            'color' => '#333',
8✔
335
            'size'  => 1,
8✔
336
        ], $params);
8✔
337

338
        $size   = Vars::range((int)$params['size'], 1, 1000);
16✔
339
        $rgba   = Helper::normalizeColor((string)$params['color']);
16✔
340
        $width  = \imagesx($image);
16✔
341
        $height = \imagesy($image);
16✔
342

343
        $posX1 = 0;
16✔
344
        $posY1 = 0;
16✔
345
        $posX2 = $width - 1;
16✔
346
        $posY2 = $height - 1;
16✔
347

348
        $color = (int)\imagecolorallocatealpha($image, $rgba[0], $rgba[1], $rgba[2], $rgba[3]);
16✔
349

350
        for ($i = 0; $i < $size; $i++) {
16✔
351
            \imagerectangle($image, $posX1++, $posY1++, $posX2--, $posY2--, $color);
16✔
352
        }
353
    }
354
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc