Elgg  Version 3.0
ImageService.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Elgg;
4 
5 use Exception;
11 
18 class ImageService {
19  use Loggable;
20 
21  const JPEG_QUALITY = 75;
22 
26  private $imagine;
27 
31  private $config;
32 
39  public function __construct(ImagineInterface $imagine, Config $config) {
40  $this->imagine = $imagine;
41  $this->config = $config;
42  }
43 
68  public function resize($source, $destination = null, array $params = []) {
69 
70  if (!isset($destination)) {
71  $destination = $source;
72  }
73 
74  try {
75  $image = $this->imagine->open($source);
76 
77  $width = $image->getSize()->getWidth();
78  $height = $image->getSize()->getHeight();
79 
80  $resize_params = $this->normalizeResizeParameters($width, $height, $params);
81 
82  $max_width = (int) elgg_extract('w', $resize_params);
83  $max_height = (int) elgg_extract('h', $resize_params);
84 
85  $x1 = (int) elgg_extract('x1', $resize_params, 0);
86  $y1 = (int) elgg_extract('y1', $resize_params, 0);
87  $x2 = (int) elgg_extract('x2', $resize_params, 0);
88  $y2 = (int) elgg_extract('y2', $resize_params, 0);
89 
90  if ($x2 > $x1 && $y2 > $y1) {
91  $crop_start = new Point($x1, $y1);
92  $crop_size = new Box($x2 - $x1, $y2 - $y1);
93  $image->crop($crop_start, $crop_size);
94  }
95 
96  $target_size = new Box($max_width, $max_height);
97  $thumbnail = $image->resize($target_size);
98 
99  $thumbnail->save($destination, [
100  'jpeg_quality' => elgg_extract('jpeg_quality', $params, self::JPEG_QUALITY),
101  'format' => $this->getFileFormat($source, $params),
102  ]);
103 
104  unset($image);
105  unset($thumbnail);
106  } catch (Exception $ex) {
107  $logger = $this->logger ? $this->logger : _elgg_services()->logger;
108  $logger->error($ex);
109  return false;
110  }
111 
112  return true;
113  }
114 
122  public function fixOrientation($filename) {
123  try {
124  $image = $this->imagine->open($filename);
125  $metadata = $image->metadata();
126  if (!isset($metadata['ifd0.Orientation'])) {
127  // no need to perform an orientation fix
128  return true;
129  }
130 
131  $autorotate = new Autorotate();
132  $autorotate->apply($image)->save($filename);
133 
134  $image->strip()->save($filename);
135 
136  return true;
137  } catch (Exception $ex) {
138  $logger = $this->logger ? $this->logger : _elgg_services()->logger;
139  $logger->notice($ex);
140  }
141  return false;
142  }
143 
159  public function normalizeResizeParameters($width, $height, array $params = []) {
160 
161  $max_width = (int) elgg_extract('w', $params, 100, false);
162  $max_height = (int) elgg_extract('h', $params, 100, false);
163  if (!$max_height || !$max_width) {
164  throw new \LogicException("Resize width and height parameters are required");
165  }
166 
167  $square = elgg_extract('square', $params, false);
168  $upscale = elgg_extract('upscale', $params, false);
169 
170  $x1 = (int) elgg_extract('x1', $params, 0);
171  $y1 = (int) elgg_extract('y1', $params, 0);
172  $x2 = (int) elgg_extract('x2', $params, 0);
173  $y2 = (int) elgg_extract('y2', $params, 0);
174 
175  $cropping_mode = $x1 || $y1 || $x2 || $y2;
176 
177  if ($cropping_mode) {
178  $crop_width = $x2 - $x1;
179  $crop_height = $y2 - $y1;
180  if ($crop_width <= 0 || $crop_height <= 0 || $crop_width > $width || $crop_height > $height) {
181  throw new \LogicException("Coordinates [$x1, $y1], [$x2, $y2] are invalid for image cropping");
182  }
183  } else {
184  // everything selected if no crop parameters
185  $crop_width = $width;
186  $crop_height = $height;
187  }
188 
189  // determine cropping offsets
190  if ($square) {
191  // asking for a square image back
192 
193  // size of the new square image
194  $max_width = $max_height = min($max_width, $max_height);
195 
196  // find largest square that fits within the selected region
197  $crop_width = $crop_height = min($crop_width, $crop_height);
198 
199  if (!$cropping_mode) {
200  // place square region in the center
201  $x1 = floor(($width - $crop_width) / 2);
202  $y1 = floor(($height - $crop_height) / 2);
203  }
204  } else {
205  // maintain aspect ratio of original image/crop
206  if ($crop_height / $max_height > $crop_width / $max_width) {
207  $max_width = floor($max_height * $crop_width / $crop_height);
208  } else {
209  $max_height = floor($max_width * $crop_height / $crop_width);
210  }
211  }
212 
213  if (!$upscale && ($crop_height < $max_height || $crop_width < $max_width)) {
214  // we cannot upscale and selected area is too small so we decrease size of returned image
215  $max_height = $crop_height;
216  $max_width = $crop_width;
217  }
218 
219  return [
220  'w' => $max_width,
221  'h' => $max_height,
222  'x1' => $x1,
223  'y1' => $y1,
224  'x2' => $x1 + $crop_width,
225  'y2' => $y1 + $crop_height,
226  'square' => $square,
227  'upscale' => $upscale,
228  ];
229  }
230 
240  protected function getFileFormat($filename, $params) {
241 
242  $accepted_formats = [
243  'image/jpeg' => 'jpeg',
244  'image/pjpeg' => 'jpeg',
245  'image/png' => 'png',
246  'image/x-png' => 'png',
247  'image/gif' => 'gif',
248  'image/vnd.wap.wbmp' => 'wbmp',
249  'image/x‑xbitmap' => 'xbm',
250  'image/x‑xbm' => 'xbm',
251  ];
252 
253  // was a valid output format supplied
254  $format = elgg_extract('format', $params);
255  if (in_array($format, $accepted_formats)) {
256  return $format;
257  }
258 
259  $mime_detector = new MimeTypeDetector();
260  $mime = $mime_detector->getType($filename);
261 
262  return elgg_extract($mime, $accepted_formats);
263  }
264 }
$format
Definition: date.php:36
$source
$params
Saves global plugin settings.
Definition: save.php:13
trait Loggable
Enables adding a logger.
Definition: Loggable.php:12
$config
Advanced site settings, debugging section.
Definition: debugging.php:6
$metadata
Outputs object metadata $vars[&#39;metadata&#39;] Metadata/menu $vars[&#39;show_entity_menu&#39;] Show the entity m...
Definition: metadata.php:10
fixOrientation($filename)
If needed the image will be rotated based on orientation information.
Configuration exception.
$image
Definition: image_block.php:25
Image manipulation service.
getFileFormat($filename, $params)
Determine the image file format, this is needed for correct resizing.
__construct(ImagineInterface $imagine, Config $config)
Constructor.
elgg_extract($key, $array, $default=null, $strict=true)
Checks for $array[$key] and returns its value if it exists, else returns $default.
Definition: elgglib.php:1131
Detect the MIME type of a file.
resize($source, $destination=null, array $params=[])
Crop and resize an image.
$filename
_elgg_services()
Get the global service provider.
Definition: elgglib.php:1292
normalizeResizeParameters($width, $height, array $params=[])
Calculate the parameters for resizing an image.