Completed
Push — develop ( dce625...7bbca0 )
by Mathieu
01:58
created

Image   B

Complexity

Total Complexity 47

Size/Duplication

Total Lines 280
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
eloc 152
dl 0
loc 280
ccs 0
cts 167
cp 0
rs 8.64
c 0
b 0
f 0
wmc 47

17 Methods

Rating   Name   Duplication   Size   Complexity  
A writeText() 0 17 4
B getCoordinatesFromString() 0 44 10
A mirror() 0 2 1
A getHeight() 0 3 1
A isLandscape() 0 3 1
A crop() 0 15 1
A load() 0 17 4
A resize() 0 26 4
A rotate() 0 2 1
A merge() 0 36 5
A line() 0 11 2
A resizeCanvas() 0 18 2
A flip() 0 2 1
A getWidth() 0 3 1
B save() 0 24 7
A isPortrait() 0 3 1
A chain() 0 7 1

How to fix   Complexity   

Complex Class

Complex classes like Image often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Image, and based on these observations, apply Extract Interface, too.

1
<?php
2
namespace Suricate;
3
4
class Image
5
{
6
    use Traits\ImageFilter;
7
8
    public $source;
9
    private $destination;
10
11
    private $width;
12
    private $height;
13
    
14
15
    public function load($filename)
16
    {
17
        if (is_file($filename) && $imgString = file_get_contents($filename)) {
18
            $imgString = imagecreatefromstring($imgString);
19
            if ($imgString !== false) {
20
                $this->source = $imgString;
21
                $this->destination = $this->source;
22
                $this->width = imagesx($this->source);
23
                $this->height = imagesy($this->source);
24
25
                return $this;
26
            }
27
28
            throw new \InvalidArgumentException('Cannot load ' . $filename . ', not an image');
29
        }
30
        
31
        throw new \InvalidArgumentException('Cannot load ' . $filename . ', file unreadable');
32
    }
33
34
    public function getWidth()
35
    {
36
        return $this->width;
37
    }
38
39
    public function getHeight()
40
    {
41
        return $this->height;
42
    }
43
44
    public function isPortrait()
45
    {
46
        return $this->width < $this->height;
47
    }
48
49
    public function isLandscape()
50
    {
51
        return $this->height < $this->width;
52
    }
53
54
    public function chain()
55
    {
56
        $this->source   = $this->destination;
57
        $this->width    = imagesx($this->source);
58
        $this->height   = imagesy($this->source);
59
60
        return $this;
61
    }
62
63
    public function resize($width = null, $height = null)
64
    {
65
        if ($this->source) {
66
            if ($width == null) {
67
                $width = round(($height / $this->height) * $this->width);
68
            } elseif ($height == null) {
69
                $height = round(($width / $this->width) * $this->height);
70
            }
71
72
            $this->destination = imagecreatetruecolor($width, $height);
73
            imagecopyresampled(
74
                $this->destination,
75
                $this->source,
76
                0,
77
                0,
78
                0,
79
                0,
80
                $width,
81
                $height,
82
                $this->width,
83
                $this->height
84
            );
85
86
            return $this->chain();
87
        }
88
        return $this;
89
    }
90
91
    public function crop($width, $height)
92
    {
93
        $centerX = round($this->width / 2);
94
        $centerY = round($this->height / 2);
95
96
        $cropWidthHalf  = round($width / 2);
97
        $cropHeightHalf = round($height / 2);
98
99
        $x1 = max(0, $centerX - $cropWidthHalf);
100
        $y1 = max(0, $centerY - $cropHeightHalf);
101
        
102
        $this->destination = imagecreatetruecolor($width, $height);
103
        imagecopy($this->destination, $this->source, 0, 0, $x1, $y1, $width, $height);
104
105
        return $this->chain();
106
    }
107
108
    public function resizeCanvas($width, $height, $position = null, $color = [0, 0, 0])
109
    {
110
        $this->destination = imagecreatetruecolor($width, $height);
111
        $colorRes = imagecolorallocate($this->destination, $color[0], $color[1], $color[2]);
112
        $imageObj = new Image();
113
        $imageObj->width = $width;
114
        $imageObj->height = $height;
115
        imagefill($this->destination, 0, 0, $colorRes);
116
117
        if ($position !== null) {
118
            list($x, $y) = $imageObj->getCoordinatesFromString($position, $this->width, $this->height);
119
        } else {
120
            $x = 0;
121
            $y = 0;
122
        }
123
        imagecopy($this->destination, $this->source, $x, $y, 0, 0, $this->width, $this->height);
0 ignored issues
show
Bug introduced by
It seems like $y can also be of type double; however, parameter $dst_y of imagecopy() 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

123
        imagecopy($this->destination, $this->source, $x, /** @scrutinizer ignore-type */ $y, 0, 0, $this->width, $this->height);
Loading history...
Bug introduced by
It seems like $x can also be of type double; however, parameter $dst_x of imagecopy() 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

123
        imagecopy($this->destination, $this->source, /** @scrutinizer ignore-type */ $x, $y, 0, 0, $this->width, $this->height);
Loading history...
124
125
        return $this->chain();
126
    }
127
128
    
129
130
    public function rotate()
131
    {
132
    }
133
134
    public function mirror()
135
    {
136
    }
137
138
    public function flip()
139
    {
140
    }
141
142
    public function merge($source, $position = null, $x = null, $y = null, $percent = 100)
143
    {
144
        if ($source instanceof \Suricate\Image) {
145
        } else {
146
            $source = with(new Image())->load($source);
147
        }
148
149
        if ($position !== null) {
150
            list($x, $y) = $this->getCoordinatesFromString($position, $source->width, $source->height);
151
        }
152
        $x = $x !== null ? $x : 0;
153
        $y = $y !== null ? $y : 0;
154
155
        // Handle transparent image
156
        // creating a cut resource
157
        $cut = imagecreatetruecolor($source->getWidth(), $source->getHeight());
158
159
        // copying relevant section from background to the cut resource
160
        imagecopy($cut, $this->destination, 0, 0, $x, $y, $source->getWidth(), $source->getHeight());
161
        
162
        // copying relevant section from watermark to the cut resource
163
        imagecopy($cut, $source->source, 0, 0, 0, 0, $source->getWidth(), $source->getHeight());
164
165
        imagecopymerge(
166
            $this->destination,
167
            $cut,
168
            $x,
169
            $y,
170
            0,
171
            0,
172
            $source->getWidth(),
173
            $source->getHeight(),
174
            $percent
175
        );
176
177
        return $this->chain();
178
    }
179
180
    public function writeText($text, $x = 0, $y = 0, \Closure $callback = null)
181
    {
182
        if ($x < 0) {
183
            $x = $this->width + $x;
184
        }
185
        if ($y < 0) {
186
            $y = $this->height + $y;
187
        }
188
        $imageFont = new ImageFont($text);
189
190
        if ($callback != null) {
191
            $callback($imageFont);
192
        }
193
194
        $imageFont->apply($this->source, $x, $y);
195
        
196
        return $this;
197
    }
198
199
    public function line($x1, $y1, $x2, $y2, \Closure $callback = null)
200
    {
201
        $imageShape = new ImageShape();
202
        $imageShape->setImage($this->source);
203
        if ($callback != null) {
204
            $callback($imageShape);
205
        }
206
207
        $imageShape->drawLine($x1, $y1, $x2, $y2);
208
209
        return $this;
210
    }
211
212
    
213
214
    public function save($filename, $outputType = null, $quality = 70)
215
    {
216
        $result = false;
217
        if ($outputType === null) {
218
            $extension = pathinfo($filename, PATHINFO_EXTENSION);
219
        } else {
220
            $extension = $outputType;
221
        }
222
        if ($extension !== false) {
223
            switch (strtolower($extension)) {
224
                case 'jpg':
225
                case 'jpeg':
226
                    $result = imagejpeg($this->source, $filename, $quality);
227
                    break;
228
                case 'png':
229
                    $result = imagepng($this->source, $filename);
230
                    break;
231
                case 'gif':
232
                    $result = imagegif($this->source, $filename);
233
                    break;
234
            }
235
        }
236
237
        return $result;
238
    }
239
240
    private function getCoordinatesFromString($position, $offsetWidth = 0, $offsetHeight = 0)
241
    {
242
        switch ($position) {
243
            case 'top':
244
                $x = floor(($this->width / 2) - ($offsetWidth / 2));
245
                $y = 0;
246
                break;
247
            case 'top-right':
248
                $x = $this->width - $offsetWidth;
249
                $y = 0;
250
                break;
251
            case 'left':
252
                $x = 0;
253
                $y = floor(($this->height / 2) - ($offsetHeight / 2));
254
                break;
255
            case 'center':
256
                $x = floor(($this->width / 2) - ($offsetWidth / 2));
257
                $y = floor(($this->height / 2) - ($offsetHeight / 2));
258
                break;
259
            case 'right':
260
                $x = $x = $this->width - $offsetWidth;
0 ignored issues
show
Unused Code introduced by
The assignment to $x is dead and can be removed.
Loading history...
261
                $y = floor(($this->height / 2) - ($offsetHeight / 2));
262
                break;
263
            case 'bottom-left':
264
                $x = 0;
265
                $y = $this->height - $offsetHeight;
266
                break;
267
            case 'bottom':
268
                $x = floor(($this->width / 2) - ($offsetWidth / 2));
269
                $y = $this->height - $offsetHeight;
270
                break;
271
            case 'bottom-right':
272
                $x = $x = $this->width - $offsetWidth;
273
                $y = $this->height - $offsetHeight;
274
                break;
275
            
276
            case 'top-left':
277
            default:
278
                $x = 0;
279
                $y = 0;
280
                break;
281
        }
282
283
        return [$x, $y];
284
    }
285
}
286