Passed
Push — master ( 5319fe...eee281 )
by Derek Stephen
01:49
created

Image::output()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 15
ccs 8
cts 8
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 7
nc 4
nop 1
crap 3
1
<?php
2
3
namespace Del;
4
5
use Del\Image\Exception\NotFoundException;
6
use Del\Image\Exception\NothingLoadedException;
7
use Del\Image\Strategy\GifStrategy;
8
use Del\Image\Strategy\ImageTypeStrategyInterface;
9
use Del\Image\Strategy\JpegStrategy;
10
use Del\Image\Strategy\PngStrategy;
11
12
class Image 
13
{
14
    /** @var resource $image */
15
    private $image;
16
17
    /** @var string $fileName */
18
    private $fileName;
19
20
    /** @var ImageTypeStrategyInterface $strategy */
21
    private $strategy;
22
23
    /** @var array $strategies */
24
    private $strategies = [
25
        IMAGETYPE_JPEG => JpegStrategy::class,
26
        IMAGETYPE_GIF => GifStrategy::class,
27
        IMAGETYPE_PNG => PngStrategy::class,
28
    ];
29
30
    /**
31
     * @param string $filename
32
     */
33 24
    public function __construct($filename = null)
34
    {
35 24
        if ($filename !== null) {
36 1
            $this->fileName = $filename;
37 1
            $this->load($filename);
38
        }
39 24
    }
40
41
    /**
42
     * @param $path
43
     * @throws NotFoundException
44
     */
45 23
    private function checkFileExists($path)
46
    {
47 23
        if (!file_exists($path)) {
48 1
            throw new NotFoundException("$path does not exist");
49
        }
50 22
    }
51
52
53
    /**
54
     * @param string $filename
55
     * @throws NotFoundException
56
     */
57 23
    public function load($filename)
58
    {
59 23
        $this->checkFileExists($filename);
60 22
        $this->strategy = new $this->strategies[getimagesize($filename)[2]]();
61 22
        $this->image = $this->strategy->create($filename);
62 22
    }
63
64
65
    /**
66
     *  @param string $filename
67
     *  @param int $compression
68
     *  @param string $permissions
69
     */
70 3
    public function save($filename = null, $compression = 100, $permissions = null)
71
    {
72 3
        $filename = ($filename) ?: $this->fileName;
73 3
        $this->strategy->save($this->image, $filename, $compression);
74 3
        $this->setPermissions($filename, $permissions);
75 3
    }
76
77
    /**
78
     * @param $filename
79
     * @param $permissions
80
     */
81 3
    private function setPermissions($filename, $permissions)
82
    {
83 3
        if ($permissions !== null) {
84 1
            chmod($filename, (int) $permissions);
85
        }
86 3
    }
87
88
89
    /**
90
     * @param bool $return either output directly
91
     * @return null|string image contents
92
     */
93 17
    public function output($return = false)
94
    {
95 17
        $contents = null;
96
97 17
        if ($return) {
98 17
            ob_start();
99
        }
100
101 17
        $this->renderImage();
102
103 17
        if ($return) {
104 17
            $contents = ob_get_flush();
105
        }
106
107 17
        return $contents;
108
    }
109
110 17
    private function renderImage()
111
    {
112 17
        $this->strategy->render($this->image);
113 17
    }
114
115
    /**
116
     * @return int
117
     */
118 11
    public function getWidth()
119
    {
120 11
        return imagesx($this->image);
121
    }
122
123
    /**
124
     * @return int
125
     */
126 11
    public function getHeight()
127
    {
128 11
        return imagesy($this->image);
129
    }
130
131
    /**
132
     * @param int $height
133
     */
134 3
    public function resizeToHeight($height)
135
    {
136 3
        $ratio = $height / $this->getHeight();
137 3
        $width = $this->getWidth() * $ratio;
138 3
        $this->resize($width, $height);
139 3
    }
140
141
    /**
142
     * @param int $width
143
     */
144 4
    public function resizeToWidth($width)
145
    {
146 4
        $ratio = $width / $this->getWidth();
147 4
        $height = $this->getHeight() * $ratio;
148 4
        $this->resize($width, $height);
149 4
    }
150
151
    /**
152
     * @param int $scale %
153
     */
154 1
    public function scale($scale)
155
    {
156 1
        $width = $this->getWidth() * $scale / 100;
157 1
        $height = $this->getHeight() * $scale / 100;
158 1
        $this->resize($width, $height);
159 1
    }
160
161
    /**
162
     * @param int $width
163
     * @param int $height
164
     */
165 4
    public function resizeAndCrop($width, $height)
166
    {
167 4
        $targetRatio = $width / $height;
168 4
        $actualRatio = $this->getWidth() / $this->getHeight();
169
170 4
        if ($targetRatio == $actualRatio) {
171
            // Scale to size
172 1
            $this->resize($width, $height);
173 3
        } elseif ($targetRatio > $actualRatio) {
174
            // Resize to width, crop extra height
175 1
            $this->resizeToWidth($width);
176 1
            $this->crop($width, $height);
177
        } else {
178
            // Resize to height, crop additional width
179 2
            $this->resizeToHeight($height);
180 2
            $this->crop($width, $height);
181
        }
182 4
    }
183
184
185
    /**
186
     *  Now with added Transparency resizing feature
187
     *  @param int $width
188
     *  @param int $height
189
     */
190 9
    public function resize($width, $height)
191
    {
192 9
        $newImage = imagecreatetruecolor($width, $height);
193
194 9
        $this->strategy->handleTransparency($newImage, $this->image);
195
196
        // Now resample the image
197 9
        imagecopyresampled($newImage, $this->image, 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight());
198
199
        // And allocate to $this
200 9
        $this->image = $newImage;
201 9
    }
202
203
204
205
206
    /**
207
     * @param int $width
208
     * @param int $height
209
     * @param string $trim
210
     */
211 4
    public function crop($width, $height, $trim = 'center')
212
    {
213 4
        $offsetX = 0;
214 4
        $offsetY = 0;
215 4
        $currentWidth = $this->getWidth();
216 4
        $currentHeight = $this->getHeight();
217
218 4
        if ($trim != 'left') {
219 4
            $offsetX = $this->getOffsetX($currentWidth, $width, $trim);
220 4
            $offsetY = $this->getOffsetY($currentHeight, $height, $trim);
221
        }
222
223 4
        $newImage = imagecreatetruecolor($width, $height);
224 4
        imagecopyresampled($newImage, $this->image, 0, 0, $offsetX, $offsetY, $width, $height, $width, $height);
225 4
        $this->image = $newImage;
226 4
    }
227
228
    /**
229
     * @param $currentWidth
230
     * @param $width
231
     * @param $trim
232
     * @return float|int
233
     */
234 4
    private function getOffsetX($currentWidth, $width, $trim)
235
    {
236 4
        $offsetX = 0;
237 4
        if ($currentWidth > $width) {
238 3
            $diff = $currentWidth - $width;
239 3
            $offsetX = ($trim == 'center') ? $diff / 2 : $diff; //full diff for trim right
240
        }
241 4
        return $offsetX;
242
    }
243
244
    /**
245
     * @param $currentHeight
246
     * @param $height
247
     * @param $trim
248
     * @return float|int
249
     */
250 4
    private function getOffsetY($currentHeight, $height, $trim)
251
    {
252 4
        $offsetY = 0;
253 4
        if ($currentHeight > $height) {
254 2
            $diff = $currentHeight - $height;
255 2
            $offsetY = ($trim == 'center') ? $diff / 2 : $diff;
256
        }
257 4
        return $offsetY;
258
    }
259
260
    /**
261
     * @return mixed
262
     * @throws NothingLoadedException
263
     */
264 4
    public function getHeader()
265
    {
266 4
        if (!$this->strategy) {
267 1
            throw new NothingLoadedException();
268
        }
269 3
        return $this->strategy->getContentType();
270
    }
271
272
    /**
273
     *  Frees up memory
274
     */
275 1
    public function destroy()
276
    {
277 1
        imagedestroy($this->image);
278
    }
279
}