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
![]() |
|||||
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
|
|||||
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
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
![]() |
|||||
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 |