Passed
Push — master ( 36008f...05efeb )
by Derek Stephen
02:07
created

Image::crop()   B

Complexity

Conditions 6
Paths 10

Size

Total Lines 21
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 6

Importance

Changes 0
Metric Value
cc 6
eloc 14
nc 10
nop 3
dl 0
loc 21
ccs 15
cts 15
cp 1
crap 6
rs 8.7624
c 0
b 0
f 0
1
<?php
2
3
namespace Del;
4
5
use Del\Image\Exception\NotFoundException;
6
use Del\Image\Exception\NothingLoadedException;
7
8
class Image 
9
{
10
    /** @var resource $image */
11
    private $image;
12
13
    /** @var int $imageType */
14
    private $imageType;
15
16
    /** @var string $fileName */
17
    private $fileName;
18
19
    private $contentType = [
20
        IMAGETYPE_JPEG => 'image/jpeg',
21
        IMAGETYPE_GIF => 'image/gif',
22
        IMAGETYPE_PNG =>'image/png',
23
    ];
24
25
    /**
26
     * @param null $filename
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $filename is correct as it would always require null to be passed?
Loading history...
27
     */
28 21
    public function __construct($filename = null)
29
    {
30 21
        if ($filename) {
31 1
            $this->fileName = $filename;
32 1
            $this->load($filename);
33
        }
34 21
    }
35
36 20
    private function checkFileExists($path)
37
    {
38 20
        if (!file_exists($path)) {
39 1
            throw new NotFoundException("$path does not exist");
40
        }
41 19
    }
42
43
44
    /**
45
     * @param string $filename
46
     * @throws NotFoundException
47
     */
48 20
    public function load($filename)
49
    {
50 20
        $this->checkFileExists($filename);
51 19
        $imageInfo = getimagesize($filename);
52 19
        $this->imageType = $imageInfo[2];
53
54 19
        if( $this->imageType == IMAGETYPE_JPEG ) {
55 4
            $this->image = imagecreatefromjpeg($filename);
56 15
        }  elseif( $this->imageType == IMAGETYPE_GIF ) {
57 3
            $this->image = imagecreatefromgif($filename);
58 12
        } elseif( $this->imageType == IMAGETYPE_PNG ) {
59 12
            $this->image = imagecreatefrompng($filename);
60
        }
61 19
    }
62
63
64
    /**
65
     *  @param string $filename
66
     *  @param int $compression
67
     *  @param string $permissions
68
     */
69 3
    public function save($filename = null, $compression = 100, $permissions = null)
70
    {
71 3
        $filename = ($filename) ?: $this->fileName;
72
73 3
        switch ($this->getImageType()) {
74 3
            case IMAGETYPE_JPEG:
75 1
                imagejpeg($this->image, $filename, $compression);
76 1
                break;
77 2
            case IMAGETYPE_GIF:
78 1
                imagegif($this->image, $filename);
79 1
                break;
80 1
            case IMAGETYPE_PNG:
81 1
                imagepng($this->image, $filename);
82 1
                break;
83
        }
84
85 3
        if( $permissions !== null) {
86 1
            chmod($filename, (int) $permissions);
87
        }
88 3
    }
89
90
91
    /**
92
     * @param bool $return either output directly
93
     * @return null|string image contents
94
     */
95 14
    public function output($return = false)
96
    {
97 14
        $contents = null;
98 14
        if ($return) {
99 14
            ob_start();
100
        }
101 14
        switch ($this->getImageType()) {
102 14
            case IMAGETYPE_JPEG:
103 3
                imagejpeg($this->image);
104 3
                break;
105 11
            case IMAGETYPE_GIF:
106 2
                imagegif($this->image);
107 2
                break;
108 9
            case IMAGETYPE_PNG:
109 9
                imagealphablending($this->image,true);
110 9
                imagesavealpha($this->image,true);
111 9
                imagepng($this->image);
112 9
                break;
113
        }
114 14
        if ($return) {
115 14
            $contents = ob_get_flush();
116
        }
117 14
        return $contents;
118
    }
119
120
    /**
121
     * @return int
122
     */
123 8
    public function getWidth()
124
    {
125 8
        return imagesx($this->image);
126
    }
127
128
    /**
129
     * @return int
130
     */
131 8
    public function getHeight()
132
    {
133 8
        return imagesy($this->image);
134
    }
135
136
    /**
137
     * @param int $height
138
     */
139 2
    public function resizeToHeight($height)
140
    {
141 2
        $ratio = $height / $this->getHeight();
142 2
        $width = $this->getWidth() * $ratio;
143 2
        $this->resize($width,$height);
144 2
    }
145
146
    /**
147
     * @param int $width
148
     */
149 2
    public function resizeToWidth($width)
150
    {
151 2
        $ratio = $width / $this->getWidth();
152 2
        $height = $this->getHeight() * $ratio;
153 2
        $this->resize($width,$height);
154 2
    }
155
156
    /**
157
     * @param int $scale %
158
     */
159 1
    public function scale($scale)
160
    {
161 1
        $width = $this->getWidth() * $scale / 100;
162 1
        $height = $this->getHeight() * $scale / 100;
163 1
        $this->resize($width,$height);
164 1
    }
165
166
    /**
167
     * @param int $width
168
     * @param int $height
169
     */
170 3
    public function resizeAndCrop($width,$height)
171
    {
172 3
        $targetRatio = $width / $height;
173 3
        $actualRatio = $this->getWidth() / $this->getHeight();
174
175 3
        if ($targetRatio == $actualRatio) {
176
            // Scale to size
177 1
            $this->resize($width,$height);
178 2
        } elseif ($targetRatio > $actualRatio) {
179
            // Resize to width, crop extra height
180 1
            $this->resizeToWidth($width);
181 1
            $this->crop($width,$height);
182
        } else {
183
            // Resize to height, crop additional width
184 1
            $this->resizeToHeight($height);
185 1
            $this->crop($width,$height);
186
        }
187 3
    }
188
189
190
    /**
191
     *  Now with added Transparency resizing feature
192
     *  @param int $width
193
     *  @param int $height
194
     */
195 6
    public function resize($width,$height)
196
    {
197 6
        $newImage = imagecreatetruecolor($width, $height);
198
199 6
        if ( ($this->getImageType() == IMAGETYPE_GIF) || ($this->getImageType()  == IMAGETYPE_PNG) ) {
200
201
            // Get transparency color's index number
202 6
            $transparency = imagecolortransparent($this->image);
203
204
            // Is a strange index other than -1 set?
205 6
            if ($transparency >= 0) {
206
207
                // deal with alpha channels
208
                $this->prepWithExistingIndex($newImage, $transparency);
209
210 6
            }  elseif ($this->getImageType() == IMAGETYPE_PNG) {
211
212
                // deal with alpha channels
213 6
                $this->prepTransparentPng($newImage);
214
            }
215
        }
216
217
        // Now resample the image
218 6
        imagecopyresampled($newImage, $this->image, 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight());
219
220
        // And allocate to $this
221 6
        $this->image = $newImage;
222 6
    }
223
224
    /**
225
     * @param $resource
226
     * @param $index
227
     */
228
    private function prepWithExistingIndex($resource, $index)
229
    {
230
        // Get the array of RGB vals for the transparency index
231
        $transparentColor = imagecolorsforindex($this->image, $index);
232
233
        // Now allocate the color
234
        $transparency = imagecolorallocate($resource, $transparentColor['red'], $transparentColor['green'], $transparentColor['blue']);
235
236
        // Fill the background with the color
237
        imagefill($resource, 0, 0, $transparency);
238
239
        // And set that color as the transparent one
240
        imagecolortransparent($resource, $transparency);
241
    }
242
243
    /**
244
     * @param $resource
245
     */
246 6
    private function prepTransparentPng($resource)
247
    {
248
        // Set blending mode as false
249 6
        imagealphablending($resource, false);
250
251
        // Tell it we want to save alpha channel info
252 6
        imagesavealpha($resource, true);
253
254
        // Set the transparent color
255 6
        $color = imagecolorallocatealpha($resource, 0, 0, 0, 127);
256
257
        // Fill the image with nothingness
258 6
        imagefill($resource, 0, 0, $color);
259 6
    }
260
261
262
    /**
263
     * @param int $width
264
     * @param int $height
265
     * @param string $trim
266
     */
267 3
    public function crop($width,$height, $trim = 'center')
268
    {
269 3
        $offsetX = 0;
270 3
        $offsetY = 0;
271 3
        $currentWidth = $this->getWidth();
272 3
        $currentHeight = $this->getHeight();
273
274 3
        if ($trim != 'left') {
275 3
            if ($currentWidth > $width) {
276 2
                $diff = $currentWidth - $width;
277 2
                $offsetX = ($trim == 'center') ? $diff / 2 : $diff; //full diff for trim right
278
            }
279 3
            if ($currentHeight > $height) {
280 2
                $diff = $currentHeight - $height;
281 2
                $offsetY = ($trim == 'center') ? $diff / 2 : $diff;
282
            }
283
        }
284
285 3
        $newImage = imagecreatetruecolor($width,$height);
286 3
        imagecopyresampled($newImage, $this->image, 0, 0, $offsetX, $offsetY, $width, $height, $width, $height);
287 3
        $this->image = $newImage;
288 3
    }
289
290
    /**
291
     * @return mixed
292
     */
293 14
    public function getImageType()
294
    {
295 14
        return $this->imageType;
296
    }
297
298
    /**
299
     * @return mixed
300
     * @throws NothingLoadedException
301
     */
302 4
    public function getHeader()
303
    {
304 4
        if (!$this->imageType) {
305 1
            throw new NothingLoadedException();
306
        }
307 3
        return $this->contentType[$this->imageType];
308
    }
309
310
    /**
311
     *  Frees up memory
312
     */
313
    public function destroy()
314
    {
315
        imagedestroy($this->image);
316
    }
317
}
318