ImageTrimmer   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 144
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 15
eloc 68
c 2
b 0
f 0
dl 0
loc 144
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A detectTrimColor() 0 12 2
A __construct() 0 7 1
B trim() 0 80 10
A trim_new() 0 20 2
1
<?php
2
/**
3
 * @package Application Utils
4
 * @subpackage ImageHelper
5
 * @see \AppUtils\ImageHelper\ImageTrimmer
6
 */
7
8
declare(strict_types=1);
9
10
namespace AppUtils\ImageHelper;
11
12
use AppUtils\ImageHelper;
13
use AppUtils\ImageHelper_Exception;
14
use AppUtils\RGBAColor;
15
use AppUtils\RGBAColor\ColorFactory;
16
use GdImage;
17
18
/**
19
 * Specialized class used for trimming images.
20
 *
21
 * @package Application Utils
22
 * @subpackage ImageHelper
23
 * @author Sebastian Mordziol <[email protected]>
24
 */
25
class ImageTrimmer
26
{
27
    /**
28
     * @var resource|GdImage
29
     */
30
    private $sourceImage;
31
    private RGBAColor $trimColor;
32
    private ImageHelper $helper;
33
34
    /**
35
     * @param ImageHelper $helper
36
     * @param resource|GdImage $sourceImage
37
     * @param RGBAColor|null $trimColor
38
     * @throws ImageHelper_Exception
39
     */
40
    public function __construct(ImageHelper $helper, $sourceImage, ?RGBAColor $trimColor=null)
41
    {
42
        ImageHelper::requireResource($sourceImage);
43
44
        $this->helper = $helper;
45
        $this->sourceImage = $sourceImage;
46
        $this->trimColor = $this->detectTrimColor($trimColor);
47
    }
48
49
    private function detectTrimColor(?RGBAColor $trimColor) : RGBAColor
50
    {
51
        $targetColor = ColorFactory::createAuto($trimColor);
52
53
        if($targetColor !== null)
54
        {
55
            return $targetColor;
56
        }
57
58
        return $this->helper->getIndexedColors(
59
            $this->sourceImage,
0 ignored issues
show
Bug introduced by
It seems like $this->sourceImage can also be of type GdImage; however, parameter $img of AppUtils\ImageHelper::getIndexedColors() 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

59
            /** @scrutinizer ignore-type */ $this->sourceImage,
Loading history...
60
            (int)imagecolorat($this->sourceImage, 0, 0)
61
        );
62
    }
63
64
    /**
65
     * @return resource|GdImage|null
66
     */
67
    public function trim_new()
68
    {
69
        $img = imagecropauto(
70
            $this->sourceImage,
71
            IMG_CROP_THRESHOLD,
72
            0.1, // Does not work at all with 0.0
73
            imagecolorclosestalpha(
74
                $this->sourceImage,
75
                $this->trimColor->getRed()->get8Bit(),
76
                $this->trimColor->getGreen()->get8Bit(),
77
                $this->trimColor->getBlue()->get8Bit(),
78
                $this->trimColor->getAlpha()->get7Bit()
79
            )
80
        );
81
82
        if($img !== false) {
83
            return $img;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $img also could return the type true which is incompatible with the documented return type GdImage|null|resource.
Loading history...
84
        }
85
86
        return null;
87
    }
88
89
    public function trim()
90
    {
91
        // Get the image width and height.
92
        $imw = imagesx($this->sourceImage);
93
        $imh = imagesy($this->sourceImage);
94
95
        // Set the X variables.
96
        $xmin = $imw;
97
        $xmax = 0;
98
        $ymin = null;
99
        $ymax = null;
100
101
        // Start scanning for the edges.
102
        for ($iy=0; $iy<$imh; $iy++)
103
        {
104
            $first = true;
105
106
            for ($ix=0; $ix<$imw; $ix++)
107
            {
108
                $ndx = imagecolorat($this->sourceImage, $ix, $iy);
109
                $colors = $this->helper->getIndexedColors($this->sourceImage, $ndx);
0 ignored issues
show
Bug introduced by
It seems like $this->sourceImage can also be of type GdImage; however, parameter $img of AppUtils\ImageHelper::getIndexedColors() 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

109
                $colors = $this->helper->getIndexedColors(/** @scrutinizer ignore-type */ $this->sourceImage, $ndx);
Loading history...
110
111
                if(!$colors->matchesAlpha($this->trimColor))
112
                {
113
                    if ($xmin > $ix) { $xmin = $ix; }
114
                    if ($xmax < $ix) { $xmax = $ix; }
115
                    if (!isset($ymin)) { $ymin = $iy; }
116
117
                    $ymax = $iy;
118
119
                    if($first)
120
                    {
121
                        $ix = $xmax;
122
                        $first = false;
123
                    }
124
                }
125
            }
126
        }
127
128
        // no trimming border found
129
        if($ymax === null) {
130
            return $this->sourceImage;
131
        }
132
133
        // The new width and height of the image.
134
        $imw = 1+$xmax-$xmin; // Image width in pixels
135
        $imh = 1+$ymax-$ymin; // Image height in pixels
136
137
        // Make another image to place the trimmed version in.
138
        $im2 = $this->helper->createNewImage($imw, $imh);
139
140
        if($this->trimColor->hasTransparency())
141
        {
142
            $bg2 = imagecolorallocatealpha(
143
                $im2,
144
                $this->trimColor->getRed()->get8Bit(),
145
                $this->trimColor->getGreen()->get8Bit(),
146
                $this->trimColor->getBlue()->get8Bit(),
147
                $this->trimColor->getAlpha()->get7Bit()
148
            );
149
150
            imagecolortransparent($im2, $bg2);
151
        }
152
        else
153
        {
154
            $bg2 = imagecolorallocate(
155
                $im2,
156
                $this->trimColor->getRed()->get8Bit(),
157
                $this->trimColor->getGreen()->get8Bit(),
158
                $this->trimColor->getBlue()->get8Bit()
159
            );
160
        }
161
162
        // Make the background of the new image the same as the background of the old one.
163
        imagefill($im2, 0, 0, $bg2);
164
165
        // Copy it over to the new image.
166
        imagecopy($im2, $this->sourceImage, 0, 0, $xmin, $ymin, $imw, $imh);
167
168
        return $im2;
169
    }
170
}
171