Completed
Push — master ( 3e458d...115c32 )
by Derek Stephen
02:19
created

Image::getHeight()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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