‪TYPO3CMS  ‪main
ImageDimension.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
24 
29 class ImageDimension
30 {
35  public function __construct(
36  private readonly int $width,
37  private readonly int $height
38  ) {}
39 
43  public function getWidth(): int
44  {
45  return $this->width;
46  }
47 
51  public function getHeight(): int
52  {
53  return $this->height;
54  }
55 
56  public static function fromProcessingTask(TaskInterface $task): self
57  {
58  $config = self::getConfigurationForImageCropScaleMask($task);
59  $processedFile = $task->getTargetFile();
60  $isCropped = false;
61  if (($config['crop'] ?? null) instanceof Area) {
62  $isCropped = true;
63  $imageWidth = (int)round($config['crop']->getWidth());
64  $imageHeight = (int)round($config['crop']->getHeight());
65  } else {
66  $imageWidth = (int)$processedFile->getOriginalFile()->getProperty('width');
67  $imageHeight = (int)$processedFile->getOriginalFile()->getProperty('height');
68  }
69  if ($imageWidth <= 0 || $imageHeight <= 0) {
70  throw new ZeroImageDimensionException('Width and height of the image must be greater than zero.', 1597310560);
71  }
73  $imageWidth,
74  $imageHeight,
75  $config['width'] ?? '',
76  $config['height'] ?? '',
77  $config
78  );
79  $imageWidth = $geometryWidth = $result->width;
80  $imageHeight = $geometryHeight = $result->height;
81 
82  if ($result->useCropScaling) {
83  $cropWidth = $result->originalWidth;
84  $cropHeight = $result->originalHeight;
85  // If the image is crop-scaled, use the dimension of the crop
86  // unless crop area exceeds the dimension of the scaled image
87  if ($cropWidth <= $geometryWidth && $cropHeight <= $geometryHeight) {
88  $imageWidth = $cropWidth;
89  $imageHeight = $cropHeight;
90  }
91  if (!$isCropped && $task->getTargetFileExtension() === 'svg') {
92  // Keep aspect ratio of SVG files, when crop-scaling is requested
93  // but no crop is applied
94  if ($geometryWidth > $geometryHeight) {
95  $imageHeight = (int)round($imageWidth * $geometryHeight / $geometryWidth);
96  } else {
97  $imageWidth = (int)round($imageHeight * $geometryWidth / $geometryHeight);
98  }
99  }
100  }
101 
102  return new self($imageWidth, $imageHeight);
103  }
104 
119  private static function getConfigurationForImageCropScaleMask(TaskInterface $task): array
120  {
121  $configuration = $task->getConfiguration();
122 
123  if ($task->getTargetFile()->getTaskIdentifier() === ‪ProcessedFile::CONTEXT_IMAGEPREVIEW) {
124  $task->sanitizeConfiguration();
125  // @todo: this transformation needs to happen in the PreviewTask, but if we do this,
126  // all preview images would be re-created, so we should be careful when to do this.
127  $configuration = $task->getConfiguration();
128  $configuration['maxWidth'] = $configuration['width'];
129  unset($configuration['width']);
130  $configuration['maxHeight'] = $configuration['height'];
131  unset($configuration['height']);
132  }
133 
134  $options = $configuration;
135  if ($configuration['maxWidth'] ?? null) {
136  $options['maxW'] = $configuration['maxWidth'];
137  }
138  if ($configuration['maxHeight'] ?? null) {
139  $options['maxH'] = $configuration['maxHeight'];
140  }
141  if ($configuration['minWidth'] ?? null) {
142  $options['minW'] = $configuration['minWidth'];
143  }
144  if ($configuration['minHeight'] ?? null) {
145  $options['minH'] = $configuration['minHeight'];
146  }
147  if ($configuration['crop'] ?? null) {
148  $options['crop'] = $configuration['crop'];
149  if (is_string($configuration['crop'])) {
150  // check if it is a json object
151  $cropData = json_decode($configuration['crop']);
152  if ($cropData) {
153  $options['crop'] = new Area((float)$cropData->x, (float)$cropData->y, (float)$cropData->width, (float)$cropData->height);
154  } else {
155  [$offsetLeft, $offsetTop, $newWidth, $newHeight] = explode(',', $configuration['crop'], 4);
156  $options['crop'] = new Area((float)$offsetLeft, (float)$offsetTop, (float)$newWidth, (float)$newHeight);
157  }
158  if ($options['crop']->isEmpty()) {
159  unset($options['crop']);
160  }
161  }
162  }
163  if ($configuration['noScale'] ?? null) {
164  $options['noScale'] = $configuration['noScale'];
165  }
166 
167  return $options;
168  }
169 }
‪TYPO3\CMS\Core\Resource\ProcessedFile\CONTEXT_IMAGEPREVIEW
‪const CONTEXT_IMAGEPREVIEW
Definition: ProcessedFile.php:55
‪TYPO3\CMS\Core\Imaging
Definition: Dimension.php:16
‪TYPO3\CMS\Core\Imaging\Exception\ZeroImageDimensionException
Definition: ZeroImageDimensionException.php:26
‪TYPO3\CMS\Core\Resource\Processing\TaskInterface
Definition: TaskInterface.php:34
‪TYPO3\CMS\Core\Imaging\ImageManipulation\Area
Definition: Area.php:23
‪TYPO3\CMS\Core\Imaging\ImageProcessingInstructions\fromCropScaleValues
‪static fromCropScaleValues(int $incomingWidth, int $incomingHeight, int|string $width, int|string $height, array $options)
Definition: ImageProcessingInstructions.php:94
‪TYPO3\CMS\Core\Resource\ProcessedFile
Definition: ProcessedFile.php:47