‪TYPO3CMS  ‪main
LocalCropScaleMaskHelper.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
24 
29 {
49  public function ‪process(‪TaskInterface $task)
50  {
51  return $this->‪processWithLocalFile($task, $task->‪getSourceFile()->‪getForLocalProcessing(false));
52  }
53 
58  public function ‪processWithLocalFile(‪TaskInterface $task, string $originalFileName): ?array
59  {
60  $result = null;
61  $targetFile = $task->‪getTargetFile();
62 
63  $gifBuilder = GeneralUtility::makeInstance(GifBuilder::class);
64 
65  $configuration = $targetFile->getProcessingConfiguration();
66  $configuration['additionalParameters'] = $this->‪modifyImageMagickStripProfileParameters((string)($configuration['additionalParameters'] ?? ''), $configuration);
67 
68  if (empty($configuration['fileExtension'])) {
69  $configuration['fileExtension'] = $task->‪getTargetFileExtension();
70  }
71 
72  $options = $this->‪getConfigurationForImageCropScaleMask($targetFile, $gifBuilder);
73 
74  $croppedImage = null;
75  if (!empty($configuration['crop'])) {
76  // check if it is a json object
77  $cropData = json_decode($configuration['crop']);
78  if ($cropData) {
79  $offsetLeft = (int)($cropData->x ?? 0);
80  $offsetTop = (int)($cropData->y ?? 0);
81  $newWidth = (int)($cropData->width ?? 0);
82  $newHeight = (int)($cropData->height ?? 0);
83  } else {
84  [$offsetLeft, $offsetTop, $newWidth, $newHeight] = explode(',', $configuration['crop'], 4);
85  }
86 
87  $backupPrefix = $gifBuilder->filenamePrefix;
88  $gifBuilder->filenamePrefix = 'crop_';
89 
90  $jpegQuality = ‪MathUtility::forceIntegerInRange(‪$GLOBALS['TYPO3_CONF_VARS']['GFX']['jpg_quality'], 10, 100, 85);
91 
92  // the result info is an array with 0=width,1=height,2=extension,3=filename
93  $result = $gifBuilder->imageMagickConvert(
94  $originalFileName,
95  $configuration['fileExtension'],
96  '',
97  '',
98  sprintf('-crop %dx%d+%d+%d +repage -quality %d', $newWidth, $newHeight, $offsetLeft, $offsetTop, $jpegQuality),
99  '',
100  ['noScale' => true],
101  true
102  );
103  $gifBuilder->filenamePrefix = $backupPrefix;
104 
105  if ($result !== null) {
106  $originalFileName = $croppedImage = $result[3];
107  }
108  }
109 
110  // Normal situation (no masking)
111  if (!(is_array($configuration['maskImages'] ?? null) && ‪$GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_enabled'])) {
112  // the result info is an array with 0=width,1=height,2=extension,3=filename
113  $result = $gifBuilder->imageMagickConvert(
114  $originalFileName,
115  $configuration['fileExtension'],
116  $configuration['width'] ?? '',
117  $configuration['height'] ?? '',
118  $configuration['additionalParameters'],
119  $configuration['frame'] ?? '',
120  $options,
121  // in case file is in `/typo3temp/`, it must create a result
122  $this->‪isTemporaryFile($originalFileName)
123  );
124  } else {
125  $targetFileName = $this->‪getFilenameForImageCropScaleMask($task);
126  $temporaryFileName = ‪Environment::getPublicPath() . '/typo3temp/' . $targetFileName;
127  $maskImage = $configuration['maskImages']['maskImage'] ?? null;
128  $maskBackgroundImage = $configuration['maskImages']['backgroundImage'];
129  if ($maskImage instanceof ‪FileInterface && $maskBackgroundImage instanceof ‪FileInterface) {
130  $temporaryExtension = 'png';
131  if (!‪$GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_allowTemporaryMasksAsPng']) {
132  // If ImageMagick version 5+
133  $temporaryExtension = $gifBuilder->gifExtension;
134  }
135  $tempFileInfo = $gifBuilder->imageMagickConvert(
136  $originalFileName,
137  $temporaryExtension,
138  $configuration['width'] ?? '',
139  $configuration['height'] ?? '',
140  $configuration['additionalParameters'],
141  $configuration['frame'] ?? '',
142  $options
143  );
144  if (is_array($tempFileInfo)) {
145  $maskBottomImage = $configuration['maskImages']['maskBottomImage'];
146  if ($maskBottomImage instanceof ‪FileInterface) {
147  $maskBottomImageMask = $configuration['maskImages']['maskBottomImageMask'];
148  } else {
149  $maskBottomImageMask = null;
150  }
151 
152  // Scaling: ****
153  $tempScale = [];
154  $command = '-geometry ' . $tempFileInfo[0] . 'x' . $tempFileInfo[1] . '!';
155  $command = $this->‪modifyImageMagickStripProfileParameters($command, $configuration);
156  $tmpStr = $gifBuilder->randomName();
157  // m_mask
158  $tempScale['m_mask'] = $tmpStr . '_mask.' . $temporaryExtension;
159  $gifBuilder->imageMagickExec($maskImage->getForLocalProcessing(true), $tempScale['m_mask'], $command);
160  // m_bgImg
161  $tempScale['m_bgImg'] = $tmpStr . '_bgImg.miff';
162  $gifBuilder->imageMagickExec($maskBackgroundImage->getForLocalProcessing(), $tempScale['m_bgImg'], $command);
163  // m_bottomImg / m_bottomImg_mask
164  if ($maskBottomImage instanceof ‪FileInterface && $maskBottomImageMask instanceof ‪FileInterface) {
165  $tempScale['m_bottomImg'] = $tmpStr . '_bottomImg.' . $temporaryExtension;
166  $gifBuilder->imageMagickExec($maskBottomImage->getForLocalProcessing(), $tempScale['m_bottomImg'], $command);
167  $tempScale['m_bottomImg_mask'] = ($tmpStr . '_bottomImg_mask.') . $temporaryExtension;
168  $gifBuilder->imageMagickExec($maskBottomImageMask->getForLocalProcessing(), $tempScale['m_bottomImg_mask'], $command);
169  // BEGIN combining:
170  // The image onto the background
171  $gifBuilder->combineExec($tempScale['m_bgImg'], $tempScale['m_bottomImg'], $tempScale['m_bottomImg_mask'], $tempScale['m_bgImg']);
172  }
173  // The image onto the background
174  $gifBuilder->combineExec($tempScale['m_bgImg'], $tempFileInfo[3], $tempScale['m_mask'], $temporaryFileName);
175  $tempFileInfo[3] = $temporaryFileName;
176  // Unlink the temp-images...
177  foreach ($tempScale as $tempFile) {
178  if (@is_file($tempFile)) {
179  unlink($tempFile);
180  }
181  }
182  }
183  $result = $tempFileInfo;
184  }
185  }
186 
187  // check if the processing really generated a new file (scaled and/or cropped)
188  if ($result !== null) {
189  if ($result[3] !== $originalFileName || $originalFileName === $croppedImage) {
190  $result = [
191  'width' => $result[0],
192  'height' => $result[1],
193  'filePath' => $result[3],
194  ];
195  } else {
196  // No file was generated
197  $result = null;
198  }
199  }
200 
201  // Cleanup temp file if it isn't used as result
202  if ($croppedImage && ($result === null || $croppedImage !== $result['filePath'])) {
203  GeneralUtility::unlink_tempfile($croppedImage);
204  }
205 
206  return $result;
207  }
208 
212  protected function ‪getConfigurationForImageCropScaleMask(‪ProcessedFile $processedFile, ‪GifBuilder $gifBuilder)
213  {
214  $configuration = $processedFile->‪getProcessingConfiguration();
215 
216  if ($configuration['useSample'] ?? false) {
217  $gifBuilder->scalecmd = '-sample';
218  }
219  $options = [];
220  if ($configuration['maxWidth'] ?? false) {
221  $options['maxW'] = $configuration['maxWidth'];
222  }
223  if ($configuration['maxHeight'] ?? false) {
224  $options['maxH'] = $configuration['maxHeight'];
225  }
226  if ($configuration['minWidth'] ?? false) {
227  $options['minW'] = $configuration['minWidth'];
228  }
229  if ($configuration['minHeight'] ?? false) {
230  $options['minH'] = $configuration['minHeight'];
231  }
232 
233  $options['noScale'] = $configuration['noScale'] ?? null;
234 
235  return $options;
236  }
237 
244  {
245  $configuration = $task->‪getTargetFile()->‪getProcessingConfiguration();
246  $targetFileExtension = $task->‪getSourceFile()->‪getExtension();
247  $processedFileExtension = ‪$GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png'] ? 'png' : 'gif';
248  if (is_array($configuration['maskImages']) && ‪$GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_enabled'] && $task->‪getSourceFile()->‪getExtension() != $processedFileExtension) {
249  $targetFileExtension = 'jpg';
250  } elseif ($configuration['fileExtension']) {
251  $targetFileExtension = $configuration['fileExtension'];
252  }
253 
254  return $task->‪getTargetFile()->‪generateProcessedFileNameWithoutExtension() . '.' . ltrim(trim($targetFileExtension), '.');
255  }
256 
264  protected function ‪modifyImageMagickStripProfileParameters(string $parameters, array $configuration)
265  {
266  // Strips profile information of image to save some space:
267  if (isset($configuration['stripProfile'])) {
268  if (
269  $configuration['stripProfile']
270  && ‪$GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_stripColorProfileCommand'] !== ''
271  ) {
272  $parameters = ‪$GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_stripColorProfileCommand'] . $parameters;
273  } else {
274  $parameters .= '###SkipStripProfile###';
275  }
276  }
277  return $parameters;
278  }
279 
280  protected function ‪isTemporaryFile(string $filePath): bool
281  {
282  return str_starts_with($filePath, ‪Environment::getPublicPath() . '/typo3temp/');
283  }
284 }
‪TYPO3\CMS\Core\Resource\Processing\LocalCropScaleMaskHelper\processWithLocalFile
‪processWithLocalFile(TaskInterface $task, string $originalFileName)
Definition: LocalCropScaleMaskHelper.php:58
‪TYPO3\CMS\Core\Resource\Processing\LocalCropScaleMaskHelper\modifyImageMagickStripProfileParameters
‪string modifyImageMagickStripProfileParameters(string $parameters, array $configuration)
Definition: LocalCropScaleMaskHelper.php:264
‪TYPO3\CMS\Core\Resource\FileInterface
Definition: FileInterface.php:22
‪TYPO3\CMS\Core\Resource\AbstractFile\getForLocalProcessing
‪string getForLocalProcessing($writable=true)
Definition: AbstractFile.php:580
‪TYPO3\CMS\Core\Resource\Processing\LocalCropScaleMaskHelper\isTemporaryFile
‪isTemporaryFile(string $filePath)
Definition: LocalCropScaleMaskHelper.php:280
‪TYPO3\CMS\Core\Resource\Processing\TaskInterface
Definition: TaskInterface.php:33
‪TYPO3\CMS\Core\Core\Environment\getPublicPath
‪static getPublicPath()
Definition: Environment.php:187
‪TYPO3\CMS\Core\Resource\Processing\LocalCropScaleMaskHelper\getFilenameForImageCropScaleMask
‪string getFilenameForImageCropScaleMask(TaskInterface $task)
Definition: LocalCropScaleMaskHelper.php:243
‪TYPO3\CMS\Core\Resource\Processing\TaskInterface\getSourceFile
‪Resource File getSourceFile()
‪TYPO3\CMS\Core\Resource\Processing\LocalCropScaleMaskHelper\getConfigurationForImageCropScaleMask
‪array getConfigurationForImageCropScaleMask(ProcessedFile $processedFile, GifBuilder $gifBuilder)
Definition: LocalCropScaleMaskHelper.php:212
‪TYPO3\CMS\Core\Resource\Processing\LocalCropScaleMaskHelper
Definition: LocalCropScaleMaskHelper.php:29
‪TYPO3\CMS\Core\Resource\Processing
Definition: AbstractGraphicalTask.php:16
‪TYPO3\CMS\Core\Resource\ProcessedFile\getProcessingConfiguration
‪array getProcessingConfiguration()
Definition: ProcessedFile.php:536
‪TYPO3\CMS\Core\Resource\ProcessedFile\generateProcessedFileNameWithoutExtension
‪string generateProcessedFileNameWithoutExtension()
Definition: ProcessedFile.php:570
‪TYPO3\CMS\Core\Resource\Processing\TaskInterface\getTargetFile
‪Resource ProcessedFile getTargetFile()
‪TYPO3\CMS\Frontend\Imaging\GifBuilder
Definition: GifBuilder.php:56
‪TYPO3\CMS\Core\Resource\ProcessedFile
Definition: ProcessedFile.php:45
‪TYPO3\CMS\Core\Resource\AbstractFile\getExtension
‪string getExtension()
Definition: AbstractFile.php:255
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:41
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:24
‪TYPO3\CMS\Core\Resource\Processing\LocalCropScaleMaskHelper\process
‪array null process(TaskInterface $task)
Definition: LocalCropScaleMaskHelper.php:49
‪TYPO3\CMS\Core\Utility\MathUtility\forceIntegerInRange
‪static int forceIntegerInRange(mixed $theInt, int $min, int $max=2000000000, int $defaultValue=0)
Definition: MathUtility.php:34
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:51
‪TYPO3\CMS\Core\Resource\Processing\TaskInterface\getTargetFileExtension
‪string getTargetFileExtension()