Completed
Push — master ( 4181f5...2f550b )
by Stéphane
04:08
created

src/Image.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * An image to run through imagecache
5
 */
6
namespace Onigoetz\Imagecache;
7
8
use Intervention\Image\ImageManagerStatic as InterventionImage;
9
10
/**
11
 * An image to run through imagecache
12
 */
13
class Image
14
{
15
    /**
16
     * File source
17
     * @var string
18
     */
19
    public $source;
20
21
    /**
22
     * Informations about the image
23
     * @var array
24
     */
25
    protected $info;
26
27
    /**
28
     * Image resource
29
     * @var \Intervention\Image\Image
30
     */
31
    protected $image;
32
33
    /**
34
     * Create an image and get informations about it
35
     *
36
     * @param string $source
37
     *
38
     * @throws \Exception if cannot find or load the file
39
     */
40
    public function __construct($source)
41
    {
42
        $this->source = $source;
43
44 105
        if (!is_file($this->source) && !is_uploaded_file($this->source)) {
45
            throw new Exceptions\NotFoundException('file not found');
46 105
        }
47
48 105
        $this->image = InterventionImage::make($source);
49 3
    }
50
51
    /**
52 102
     * @return \Intervention\Image\Image
53 102
     */
54 96
    public function getImage()
55
    {
56
        return $this->image;
57
    }
58
59 18
    /**
60
     * @param \Intervention\Image\Image $image
61 18
     * used mainly for unit tests, we cannot typehint as we get a mockery object
62
     */
63
    public function setImage($image)
64
    {
65
        $this->image = $image;
66
    }
67
68 18
    /**
69
     * File's width
70 18
     *
71 18
     * @return int
72
     */
73
    public function getWidth()
74
    {
75
        return $this->image->getWidth();
76
    }
77
78
    /**
79
     * File's height
80
     *
81
     * @return int
82
     */
83
    public function getHeight()
84
    {
85
        return $this->image->getHeight();
86
    }
87
88
    /**
89
     * File's size
90
     *
91
     * @return int
92
     */
93
    public function getFileSize()
94
    {
95
        return filesize($this->source);
96
    }
97
98
    /**
99 51
     * Get details about an image.
100
     *
101 51
     * @return bool|array false, if the file could not be found or is not an image. Otherwise, a keyed array containing information about the image:
102
     *   - "width": Width, in pixels.
103
     *   - "height": Height, in pixels.
104
     *   - "file_size": File size in bytes.
105
     */
106
    public function getInfo()
107
    {
108
        $this->info = [
109 48
            'width' => $this->getWidth(),
110
            'height' => $this->getHeight(),
111 48
            'file_size' => $this->getFileSize(),
112
        ];
113
114
        return $this->info;
115
    }
116
117
    /**
118
     * Scales an image to the exact width and height given.
119 6
     *
120
     * This function achieves the target aspect ratio by cropping the original image
121 6
     * equally on both sides, or equally on the top and bottom. This function is
122
     * useful to create uniform sized avatars from larger images.
123
     *
124
     * The resulting image always has the exact target dimensions.
125
     *
126
     * @param int $width The target width, in pixels.
127
     * @param int $height The target height, in pixels.
128
     *
129
     * @throws \LogicException if the parameters are wrong
130
     *
131
     * @see resize()
132 3
     * @see crop()
133
     */
134 3
    public function scale_and_crop($width, $height)
135
    {
136 3
        if ($width === null) {
137 3
            throw new \LogicException('"width" must not be null for "scale_and_crop"');
138 3
        }
139 3
140
        if ($height === null) {
141
            throw new \LogicException('"height" must not be null for "scale_and_crop"');
142 3
        }
143
144
        $scale = max($width / $this->getWidth(), $height / $this->getHeight());
145
        $w = ceil($this->getWidth() * $scale);
146
        $h = ceil($this->getHeight() * $scale);
147
        $x = ($w - $width) / 2;
148
        $y = ($h - $height) / 2;
149
150
        $this->resize($w, $h);
151
        $this->crop($x, $y, $width, $height);
152
    }
153
154
    /**
155
     * Scales an image to the given width and height while maintaining aspect ratio.
156
     *
157
     * The resulting image can be smaller for one or both target dimensions.
158
     *
159
     * @param int $width
160
     *   The target width, in pixels. This value is omitted then the scaling will
161
     *   based only on the height value.
162
     * @param int $height
163
     *   The target height, in pixels. This value is omitted then the scaling will
164 33
     *   based only on the width value.
165
     */
166 33
    public function scale($width = null, $height = null)
167 3
    {
168
        if ($width === null && $height === null) {
169
            throw new \LogicException('one of "width" or "height" must be set for "scale"');
170 30
        }
171 3
172
        if ($width !== null && $height !== null) {
173
            $this->resize($width, $height);
174 27
            return;
175 27
        }
176 27
177 27
        if ($width !== null) {
178 27
            $this->image->widen($width);
179
            return;
180 27
        }
181 27
182
        $this->image->heighten($height);
183 27
    }
184
185
    /**
186
     * Resize an image to the given dimensions (ignoring aspect ratio).
187
     *
188
     * @param int $width The target width, in pixels.
189
     * @param int $height The target height, in pixels.
190
     */
191
    public function resize($width, $height)
192
    {
193
        $this->image->resize($width, $height);
194
    }
195
196
    /**
197
     * Rotate an image by the given number of degrees.
198 15
     *
199
     * @param  int $degrees The number of (clockwise) degrees to rotate the image.
200 15
     * @param  string|null $background hexadecimal background color
201 3
     * @param  bool $random
202
     */
203
    public function rotate($degrees, $background = null, $random = false)
204 12
    {
205 3
        if ($background) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $background of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
206 2
            $background = trim($background);
207
        } else {
208 12
            $background = "ffffff";
209 12
        }
210
211 12
        if ($random) {
212 12
            $deg = abs((float) $degrees);
213
            $degrees = rand(-1 * $deg, $deg);
214
        }
215
216
        $this->image->rotate($degrees, $background);
217
    }
218
219
    /**
220
     * Crop an image to the rectangle specified by the given rectangle.
221
     *
222 36
     * @param int $xoffset
223
     *   The top left coordinate, in pixels, of the crop area (x axis value).
224 36
     * @param int $yoffset
225 36
     *   The top left coordinate, in pixels, of the crop area (y axis value).
226
     * @param int $width
227
     *   The target width, in pixels.
228
     * @param int $height
229
     *   The target height, in pixels.
230
     *
231
     * @throws \LogicException if the parameters are wrong
232
     */
233
    public function crop($xoffset, $yoffset, $width, $height)
234
    {
235 9
        if ($xoffset === null) {
236
            throw new \LogicException('"xoffset" must not be null for "crop"');
237 9
        }
238
239
        if ($yoffset === null) {
240 9
            throw new \LogicException('"yoffset" must not be null for "crop"');
241 9
        }
242 3
243 2
        if ($width === null) {
244
            throw new \LogicException('"width" must not be null for "crop"');
245 9
        }
246 3
247 3
        if ($height === null) {
248 2
            throw new \LogicException('"height" must not be null for "crop"');
249
        }
250 9
251 9
        $this->image->crop($width, $height, $xoffset, $yoffset);
252
    }
253
254
    /**
255
     * Convert an image to grayscale.
256
     */
257
    public function desaturate()
258
    {
259
        $this->image->greyscale();
260
    }
261
262
    /**
263
     * Close the image and save the changes to a file.
264
     *
265
     * @param  string|null $destination Destination path where the image should be saved. If it is empty the original image file will be overwritten.
266
     * @throws \RuntimeException
267
     * @return Image  image or false, based on success.
268 48
     */
269
    public function save($destination = null)
270 48
    {
271 3
        if (empty($destination)) {
272
            $destination = $this->source;
273
        }
274 45
275 3
        $this->image->save($destination);
276
277
        // Clear the cached file size and refresh the image information.
278 42
        clearstatcache();
279 3
280
        chmod($destination, 0644);
281
282 39
        return new self($destination);
283 3
    }
284
}
285