|
11 | 11 | * source code. |
12 | 12 | */ |
13 | 13 |
|
| 14 | +use Contao\ImagineSvg\Imagine as SvgImagine; |
14 | 15 | use Imagine\Image\ImageInterface; |
15 | 16 | use Imagine\Image\ImagineInterface; |
16 | 17 | use Imagine\Image\Palette\CMYK; |
|
21 | 22 | use Neos\Flow\ResourceManagement\ResourceManager; |
22 | 23 | use Neos\Flow\Utility\Algorithms; |
23 | 24 | use Neos\Flow\Utility\Environment; |
| 25 | +use Neos\Media\Domain\Model\Adjustment\CropImageAdjustment; |
24 | 26 | use Neos\Media\Domain\Model\Adjustment\QualityImageAdjustment; |
| 27 | +use Neos\Media\Domain\Model\Adjustment\ResizeImageAdjustment; |
25 | 28 | use Neos\Media\Domain\Repository\AssetRepository; |
26 | 29 | use Neos\Media\Imagine\Box; |
27 | 30 | use Neos\Flow\Annotations as Flow; |
@@ -103,17 +106,8 @@ public function processImage(PersistentResource $originalResource, array $adjust |
103 | 106 | $additionalOptions = []; |
104 | 107 | $adjustmentsApplied = false; |
105 | 108 |
|
106 | | - // TODO: Special handling for SVG should be refactored at a later point. |
107 | 109 | if ($originalResource->getMediaType() === 'image/svg+xml') { |
108 | | - $originalResourceStream = $originalResource->getStream(); |
109 | | - $resource = $this->resourceManager->importResource($originalResourceStream, $originalResource->getCollectionName()); |
110 | | - fclose($originalResourceStream); |
111 | | - $resource->setFilename($originalResource->getFilename()); |
112 | | - return [ |
113 | | - 'width' => null, |
114 | | - 'height' => null, |
115 | | - 'resource' => $resource |
116 | | - ]; |
| 110 | + return $this->processSvgImage($originalResource, $adjustments); |
117 | 111 | } |
118 | 112 |
|
119 | 113 | $resourceUri = $originalResource->createTemporaryLocalCopy(); |
@@ -214,6 +208,77 @@ public function processImage(PersistentResource $originalResource, array $adjust |
214 | 208 | return $result; |
215 | 209 | } |
216 | 210 |
|
| 211 | + /** |
| 212 | + * Process SVG images with adjustments |
| 213 | + * |
| 214 | + * @param PersistentResource $originalResource |
| 215 | + * @param array<ImageAdjustmentInterface> $adjustments |
| 216 | + * @return array{width: int|null, height: int|null, resource: PersistentResource} |
| 217 | + * @throws Exception |
| 218 | + */ |
| 219 | + protected function processSvgImage(PersistentResource $originalResource, array $adjustments): array |
| 220 | + { |
| 221 | + $originalResourceStream = $originalResource->getStream(); |
| 222 | + |
| 223 | + $nonAdjustedResult = [ |
| 224 | + 'width' => null, |
| 225 | + 'height' => null, |
| 226 | + 'resource' => $originalResource |
| 227 | + ]; |
| 228 | + |
| 229 | + if (is_bool($originalResourceStream)) { |
| 230 | + return $nonAdjustedResult; |
| 231 | + } |
| 232 | + |
| 233 | + try { |
| 234 | + $svgImage = (new SvgImagine())->read($originalResourceStream); |
| 235 | + } catch (\Exception) { |
| 236 | + return $nonAdjustedResult; |
| 237 | + } |
| 238 | + |
| 239 | + $svgImage = $this->applySvgAdjustments($svgImage, $adjustments); |
| 240 | + $size = $svgImage->getSize(); |
| 241 | + |
| 242 | + $transformedImageTemporaryPathAndFilename = $this->environment->getPathToTemporaryDirectory() |
| 243 | + . 'ProcessedImage-' . Algorithms::generateRandomString(13) . '.svg'; |
| 244 | + |
| 245 | + $svgImage->save($transformedImageTemporaryPathAndFilename); |
| 246 | + $resource = $this->resourceManager->importResource( |
| 247 | + $transformedImageTemporaryPathAndFilename, |
| 248 | + $originalResource->getCollectionName() |
| 249 | + ); |
| 250 | + $resource->setFilename($originalResource->getFilename()); |
| 251 | + unlink($transformedImageTemporaryPathAndFilename); |
| 252 | + |
| 253 | + return [ |
| 254 | + 'width' => $size->getWidth(), |
| 255 | + 'height' => $size->getHeight(), |
| 256 | + 'resource' => $resource, |
| 257 | + ]; |
| 258 | + } |
| 259 | + |
| 260 | + /** |
| 261 | + * Apply supported adjustments to SVG image |
| 262 | + * |
| 263 | + * @param ImageInterface $svgImage |
| 264 | + * @param array<ImageAdjustmentInterface> $adjustments |
| 265 | + * @return ImageInterface |
| 266 | + */ |
| 267 | + protected function applySvgAdjustments(ImageInterface $svgImage, array $adjustments): ImageInterface |
| 268 | + { |
| 269 | + foreach ($adjustments as $adjustment) { |
| 270 | + if ($adjustment instanceof CropImageAdjustment) { |
| 271 | + $svgAdjustment = CropImageAdjustment::createFromCropImageAdjustment($adjustment); |
| 272 | + $svgImage = $svgAdjustment->applyToImage($svgImage); |
| 273 | + } elseif ($adjustment instanceof ResizeImageAdjustment) { |
| 274 | + $svgAdjustment = ResizeImageAdjustment::createFromResizeImageAdjustment($adjustment); |
| 275 | + $svgImage = $svgAdjustment->applyToImage($svgImage); |
| 276 | + } |
| 277 | + } |
| 278 | + |
| 279 | + return $svgImage; |
| 280 | + } |
| 281 | + |
217 | 282 | /** |
218 | 283 | * @param array $additionalOptions |
219 | 284 | * @return array |
@@ -260,9 +325,8 @@ public function getImageSize(PersistentResource $resource) |
260 | 325 | return $imageSize; |
261 | 326 | } |
262 | 327 |
|
263 | | - // TODO: Special handling for SVG should be refactored at a later point. |
264 | 328 | if ($resource->getMediaType() === 'image/svg+xml') { |
265 | | - $imageSize = ['width' => null, 'height' => null]; |
| 329 | + return $this->getSvgImageSize($resource); |
266 | 330 | } else { |
267 | 331 | try { |
268 | 332 | $imagineImage = $this->imagineService->read($resource->getStream()); |
@@ -303,6 +367,28 @@ protected function applyAdjustments(ImageInterface $image, array $adjustments, & |
303 | 367 | return $image; |
304 | 368 | } |
305 | 369 |
|
| 370 | + /** |
| 371 | + * Get the size of an SVG image |
| 372 | + * |
| 373 | + * @param PersistentResource $resource |
| 374 | + * @return array{width: int|null, height: int|null} |
| 375 | + */ |
| 376 | + protected function getSvgImageSize(PersistentResource $resource): array |
| 377 | + { |
| 378 | + try { |
| 379 | + $resourceStream = $resource->getStream(); |
| 380 | + if (is_bool($resourceStream)) { |
| 381 | + throw new \Exception('the stream of the given resource is not available'); |
| 382 | + } |
| 383 | + |
| 384 | + $svgImage = (new SvgImagine())->read($resourceStream); |
| 385 | + $size = $svgImage->getSize(); |
| 386 | + return ['width' => $size->getWidth(), 'height' => $size->getHeight()]; |
| 387 | + } catch (\Exception) { |
| 388 | + return ['width' => null, 'height' => null]; |
| 389 | + } |
| 390 | + } |
| 391 | + |
306 | 392 | /** |
307 | 393 | * Detects whether the given GIF image data contains more than one frame |
308 | 394 | * |
|
0 commit comments