1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* This file is part of the IrishDan\ResponsiveImageBundle package. |
4
|
|
|
* |
5
|
|
|
* (c) Daniel Byrne <[email protected]> |
6
|
|
|
* |
7
|
|
|
* For the full copyright and license information, please view the LICENSE file that was distributed with this source |
8
|
|
|
* code. |
9
|
|
|
*/ |
10
|
|
|
|
11
|
|
|
namespace IrishDan\ResponsiveImageBundle\ImageProcessing; |
12
|
|
|
|
13
|
|
|
use Intervention\Image\ImageManager as Intervention; |
14
|
|
|
|
15
|
|
|
/** |
16
|
|
|
* Class ImageStyler |
17
|
|
|
* |
18
|
|
|
* @package ResponsiveImageBundle |
19
|
|
|
*/ |
20
|
|
|
class ImageStyler |
21
|
|
|
{ |
22
|
|
|
/** |
23
|
|
|
* @var |
24
|
|
|
*/ |
25
|
|
|
private $compression = 90; |
26
|
|
|
/** |
27
|
|
|
* @var |
28
|
|
|
*/ |
29
|
|
|
private $cropCoordinates = []; |
30
|
|
|
/** |
31
|
|
|
* @var |
32
|
|
|
*/ |
33
|
|
|
private $driver = 'gd'; |
34
|
|
|
/** |
35
|
|
|
* @var |
36
|
|
|
*/ |
37
|
|
|
private $focusCoordinates = []; |
38
|
|
|
/** |
39
|
|
|
* @var \Intervention\Image\Image |
40
|
|
|
*/ |
41
|
|
|
private $image; |
42
|
|
|
/** |
43
|
|
|
* @var |
44
|
|
|
*/ |
45
|
|
|
private $manager; |
46
|
|
|
/** |
47
|
|
|
* @var array |
48
|
|
|
*/ |
49
|
|
|
private $styleData = []; |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* ImageStyler constructor. |
53
|
|
|
* |
54
|
|
|
* @param array $responsiveImageConfig |
55
|
|
|
*/ |
56
|
|
|
public function __construct($responsiveImageConfig = []) |
57
|
|
|
{ |
58
|
|
|
if (!empty($responsiveImageConfig['image_driver'])) { |
59
|
|
|
$this->driver = $responsiveImageConfig['image_driver']; |
60
|
|
|
} |
61
|
|
|
if (!empty($responsiveImageConfig['image_compression'])) { |
62
|
|
|
$this->compression = $responsiveImageConfig['image_compression']; |
63
|
|
|
} |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* Separates the crop and focus coordinates from the image object and stores them. |
68
|
|
|
* |
69
|
|
|
* @param $cropFocusCoords |
70
|
|
|
*/ |
71
|
|
|
public function setCoordinateGroups($cropFocusCoords) |
72
|
|
|
{ |
73
|
|
|
// x1, y1, x2, y2:x3, y3, x4, y4 |
74
|
|
|
$coordsSets = explode(':', $cropFocusCoords); |
75
|
|
|
$this->cropCoordinates = explode(', ', $coordsSets[0]); |
76
|
|
|
$this->focusCoordinates = explode(', ', $coordsSets[1]); |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* Returns the style information of a defined style. |
81
|
|
|
* |
82
|
|
|
* @param array $style |
83
|
|
|
*/ |
84
|
|
|
public function setStyleData($style = []) |
85
|
|
|
{ |
86
|
|
|
$this->styleData['effect'] = empty($style['effect']) ? null : $style['effect']; |
87
|
|
|
$this->styleData['width'] = empty($style['width']) ? null : $style['width']; |
88
|
|
|
$this->styleData['height'] = empty($style['height']) ? null : $style['height']; |
89
|
|
|
$this->styleData['greyscale'] = empty($style['greyscale']) ? null : $style['greyscale']; |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* @param $width |
94
|
|
|
* @param $height |
95
|
|
|
*/ |
96
|
|
|
protected function scaleImage($width, $height) |
97
|
|
|
{ |
98
|
|
|
$this->image->resize( |
99
|
|
|
$width, |
100
|
|
|
$height, |
101
|
|
|
function ($constraint) { |
102
|
|
|
$constraint->aspectRatio(); |
103
|
|
|
} |
104
|
|
|
); |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* @param $source |
109
|
|
|
* @param string $driver |
110
|
|
|
*/ |
111
|
|
|
protected function setImage($source, $driver = 'gd') |
112
|
|
|
{ |
113
|
|
|
if (empty($this->manager)) { |
114
|
|
|
$this->manager = new Intervention(['driver' => $driver]); |
115
|
|
|
} |
116
|
|
|
$this->image = $this->manager->make($source); |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* Performs the image manipulation using current style information |
121
|
|
|
* and user defined crop and focus rectangles. |
122
|
|
|
* |
123
|
|
|
* @param $source |
124
|
|
|
* @param $destination |
125
|
|
|
* @param array $style |
126
|
|
|
* @param null $cropFocusCoords |
127
|
|
|
* |
128
|
|
|
* @return string |
129
|
|
|
*/ |
130
|
|
|
public function createImage($source, $destination, array $style = [], $cropFocusCoords = null) |
131
|
|
|
{ |
132
|
|
|
$this->setImage($source, $this->driver); |
133
|
|
|
|
134
|
|
|
if (!empty($style)) { |
135
|
|
|
$this->setStyleData($style); |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
if (!empty($cropFocusCoords)) { |
139
|
|
|
$this->setCoordinateGroups($cropFocusCoords); |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
if (!empty($this->styleData)) { |
143
|
|
|
switch ($this->styleData['effect']) { |
144
|
|
|
case 'scale': |
145
|
|
|
// Do the crop rectangle first |
146
|
|
|
// then scale the image |
147
|
|
|
$this->doCropRectangle(); |
148
|
|
|
$this->scaleImage($this->styleData['width'], $this->styleData['height']); |
149
|
|
|
break; |
150
|
|
|
|
151
|
|
|
case 'crop': |
152
|
|
|
// If there's no focus rectangle, |
153
|
|
|
// just cut out the crop rectangle. |
154
|
|
|
if (empty($this->getCoordinates('focus'))) { |
155
|
|
|
$this->doCropRectangle(); |
156
|
|
|
} |
157
|
|
|
else { |
158
|
|
|
|
159
|
|
|
$focusOffsetFinder = new FocusCropDataCalculator( |
160
|
|
|
$this->getCoordinates('crop'), |
161
|
|
|
$this->getCoordinates('focus'), |
162
|
|
|
$this->styleData['width'], |
163
|
|
|
$this->styleData['height'] |
164
|
|
|
); |
165
|
|
|
|
166
|
|
|
$focusCropData = $focusOffsetFinder->getFocusCropData(); |
167
|
|
|
if (!empty($focusCropData)) { |
168
|
|
|
$this->cropImage( |
169
|
|
|
$focusCropData['width'], |
170
|
|
|
$focusCropData['height'], |
171
|
|
|
$focusCropData['x'], |
172
|
|
|
$focusCropData['y'] |
173
|
|
|
); |
174
|
|
|
} |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
$this->image->fit( |
178
|
|
|
$this->styleData['width'], |
179
|
|
|
$this->styleData['height'], |
180
|
|
|
function ($constraint) { |
181
|
|
|
$constraint->upsize(); |
182
|
|
|
} |
183
|
|
|
); |
184
|
|
|
|
185
|
|
|
break; |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
// Do greyscale. |
189
|
|
|
if (!empty($this->styleData['greyscale'])) { |
190
|
|
|
$this->image->greyscale(); |
191
|
|
|
} |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
return $this->saveImage($destination); |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
/** |
198
|
|
|
* @param $width |
199
|
|
|
* @param $height |
200
|
|
|
* @param $xOffset |
201
|
|
|
* @param $yOffset |
202
|
|
|
*/ |
203
|
|
|
protected function cropImage($width, $height, $xOffset, $yOffset) |
204
|
|
|
{ |
205
|
|
|
try { |
206
|
|
|
$this->image->crop( |
207
|
|
|
round($width), |
208
|
|
|
round($height), |
209
|
|
|
round($xOffset), |
210
|
|
|
round($yOffset) |
211
|
|
|
); |
212
|
|
|
} catch (Exception $exception) { |
|
|
|
|
213
|
|
|
throw new ImageProcessingException($e->getMessage); |
214
|
|
|
} |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
/** |
218
|
|
|
* Crops out defined crop area. |
219
|
|
|
*/ |
220
|
|
|
protected function doCropRectangle() |
221
|
|
|
{ |
222
|
|
|
// Get the offset. |
223
|
|
|
$cropCoords = $this->getCoordinates('crop'); |
224
|
|
|
if (!empty($cropCoords)) { |
225
|
|
|
$geometry = new CoordinateGeometry($cropCoords[0], $cropCoords[1], $cropCoords[2], $cropCoords[3]); |
226
|
|
|
|
227
|
|
|
// Get the lengths. |
228
|
|
|
$newWidth = $geometry->axisLength('x'); |
229
|
|
|
$newHeight = $geometry->axisLength('y'); |
230
|
|
|
|
231
|
|
|
// Do the initial crop. |
232
|
|
|
$this->cropImage($newWidth, $newHeight, $cropCoords[0], $cropCoords[1]); |
233
|
|
|
} |
234
|
|
|
} |
235
|
|
|
|
236
|
|
|
/** |
237
|
|
|
* @param string $type |
238
|
|
|
* |
239
|
|
|
* @return bool |
240
|
|
|
*/ |
241
|
|
|
protected function getCoordinates($type = 'crop') |
242
|
|
|
{ |
243
|
|
|
$coords = $this->{$type . 'Coordinates'}; |
244
|
|
|
$valid = 0; |
245
|
|
|
foreach ($coords as $id => $coord) { |
246
|
|
|
if ($coord > 0) { |
247
|
|
|
$valid++; |
248
|
|
|
} |
249
|
|
|
$coords[$id] = round($coord); |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
if ($valid == 0) { |
253
|
|
|
return false; |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
return $coords; |
257
|
|
|
} |
258
|
|
|
|
259
|
|
|
/** |
260
|
|
|
* @param $destination |
261
|
|
|
* |
262
|
|
|
* @return mixed |
263
|
|
|
*/ |
264
|
|
|
protected function saveImage($destination) |
265
|
|
|
{ |
266
|
|
|
$this->image->save($destination, $this->compression); |
267
|
|
|
|
268
|
|
|
return $destination; |
269
|
|
|
} |
270
|
|
|
} |
Scrutinizer analyzes your
composer.json
/composer.lock
file if available to determine the classes, and functions that are defined by your dependencies.It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.