TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
PreviewProcessing.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Core\Resource\OnlineMedia\Processing;
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
29 
34 {
38  protected $processor;
39 
44  protected function needsReprocessing($processedFile)
45  {
46  return $processedFile->isNew()
47  || (!$processedFile->usesOriginalFile() && !$processedFile->exists())
48  || $processedFile->isOutdated();
49  }
50 
62  public function processFile(FileProcessingService $fileProcessingService, AbstractDriver $driver, ProcessedFile $processedFile, File $file, $taskType, array $configuration)
63  {
64  if ($taskType !== 'Image.Preview' && $taskType !== 'Image.CropScaleMask') {
65  return;
66  }
67  // Check if processing is needed
68  if (!$this->needsReprocessing($processedFile)) {
69  return;
70  }
71  // Check if there is a OnlineMediaHelper registered for this file type
72  $helper = OnlineMediaHelperRegistry::getInstance()->getOnlineMediaHelper($file);
73  if ($helper === false) {
74  return;
75  }
76  // Check if helper provides a preview image
77  $temporaryFileName = $helper->getPreviewImage($file);
78  if (empty($temporaryFileName) || !file_exists($temporaryFileName)) {
79  return;
80  }
81  $temporaryFileNameForResizedThumb = uniqid(PATH_site . 'typo3temp/var/transient/online_media_' . $file->getHashedIdentifier()) . '.jpg';
82  switch ($taskType) {
83  case 'Image.Preview':
84  // Merge custom configuration with default configuration
85  $configuration = array_merge(['width' => 64, 'height' => 64], $configuration);
86  $configuration['width'] = MathUtility::forceIntegerInRange($configuration['width'], 1, 1000);
87  $configuration['height'] = MathUtility::forceIntegerInRange($configuration['height'], 1, 1000);
88  $this->resizeImage($temporaryFileName, $temporaryFileNameForResizedThumb, $configuration);
89  break;
90 
91  case 'Image.CropScaleMask':
92  $this->cropScaleImage($temporaryFileName, $temporaryFileNameForResizedThumb, $configuration);
93  break;
94  }
95  GeneralUtility::unlink_tempfile($temporaryFileName);
96  if (is_file($temporaryFileNameForResizedThumb)) {
97  $processedFile->setName($this->getTargetFileName($processedFile));
98  list($width, $height) = getimagesize($temporaryFileNameForResizedThumb);
99  $processedFile->updateProperties(
100  [
101  'width' => $width,
102  'height' => $height,
103  'size' => filesize($temporaryFileNameForResizedThumb),
104  'checksum' => $processedFile->getTask()->getConfigurationChecksum()
105  ]
106  );
107  $processedFile->updateWithLocalFile($temporaryFileNameForResizedThumb);
108  GeneralUtility::unlink_tempfile($temporaryFileNameForResizedThumb);
109 
111  $processedFileRepository = GeneralUtility::makeInstance(ProcessedFileRepository::class);
112  $processedFileRepository->add($processedFile);
113  }
114  }
115 
121  protected function getTargetFileName(ProcessedFile $processedFile, $prefix = 'preview_')
122  {
123  return $prefix . $processedFile->getTask()->getConfigurationChecksum() . '_' . $processedFile->getOriginalFile()->getNameWithoutExtension() . '.jpg';
124  }
125 
131  protected function resizeImage($originalFileName, $temporaryFileName, $configuration)
132  {
133  // Create the temporary file
134  if (empty($GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_enabled'])) {
135  return;
136  }
137 
138  if (file_exists($originalFileName)) {
140  'width' => $configuration['width'],
141  'height' => $configuration['height'],
142  'originalFileName' => $originalFileName,
143  'temporaryFileName' => $temporaryFileName,
144  ]);
145  $parameters = '-sample ' . $arguments['width'] . 'x' . $arguments['height'] . ' '
146  . $arguments['originalFileName'] . '[0] ' . $arguments['temporaryFileName'];
147 
148  $cmd = CommandUtility::imageMagickCommand('convert', $parameters) . ' 2>&1';
149  CommandUtility::exec($cmd);
150  }
151 
152  if (!file_exists($temporaryFileName)) {
153  // Create a error image
154  $graphicalFunctions = $this->getGraphicalFunctionsObject();
155  $graphicalFunctions->getTemporaryImageWithText($temporaryFileName, 'No thumb', 'generated!', basename($originalFileName));
156  }
157  }
158 
166  protected function cropScaleImage($originalFileName, $temporaryFileName, $configuration)
167  {
168  if (file_exists($originalFileName)) {
170  $gifBuilder = GeneralUtility::makeInstance(GifBuilder::class);
171  $gifBuilder->init();
172 
173  $options = $this->getConfigurationForImageCropScaleMask($configuration, $gifBuilder);
174  $info = $gifBuilder->getImageDimensions($originalFileName);
175  $data = $gifBuilder->getImageScale($info, $configuration['width'], $configuration['height'], $options);
176 
177  $info[0] = $data[0];
178  $info[1] = $data[1];
179  $frame = '';
180  $params = $gifBuilder->cmds['jpg'];
181 
182  // Cropscaling:
183  if ($data['crs']) {
184  if (!$data['origW']) {
185  $data['origW'] = $data[0];
186  }
187  if (!$data['origH']) {
188  $data['origH'] = $data[1];
189  }
190  $offsetX = (int)(($data[0] - $data['origW']) * ($data['cropH'] + 100) / 200);
191  $offsetY = (int)(($data[1] - $data['origH']) * ($data['cropV'] + 100) / 200);
192  $params .= ' -crop ' . $data['origW'] . 'x' . $data['origH'] . '+' . $offsetX . '+' . $offsetY . '! ';
193  }
194  $command = $gifBuilder->scalecmd . ' ' . $info[0] . 'x' . $info[1] . '! ' . $params . ' ';
195  $gifBuilder->imageMagickExec($originalFileName, $temporaryFileName, $command, $frame);
196  }
197  if (!file_exists($temporaryFileName)) {
198  // Create a error image
199  $graphicalFunctions = $this->getGraphicalFunctionsObject();
200  $graphicalFunctions->getTemporaryImageWithText($temporaryFileName, 'No thumb', 'generated!', basename($originalFileName));
201  }
202  }
203 
211  protected function getConfigurationForImageCropScaleMask(array $configuration, GifBuilder $gifBuilder)
212  {
213  if (!empty($configuration['useSample'])) {
214  $gifBuilder->scalecmd = '-sample';
215  }
216  $options = [];
217  if (!empty($configuration['maxWidth'])) {
218  $options['maxW'] = $configuration['maxWidth'];
219  }
220  if (!empty($configuration['maxHeight'])) {
221  $options['maxH'] = $configuration['maxHeight'];
222  }
223  if (!empty($configuration['minWidth'])) {
224  $options['minW'] = $configuration['minWidth'];
225  }
226  if (!empty($configuration['minHeight'])) {
227  $options['minH'] = $configuration['minHeight'];
228  }
229 
230  $options['noScale'] = $configuration['noScale'];
231 
232  return $options;
233  }
234 
238  protected function getProcessor()
239  {
240  if (!$this->processor) {
241  $this->processor = GeneralUtility::makeInstance(LocalImageProcessor::class);
242  }
243  return $this->processor;
244  }
245 
249  protected function getGraphicalFunctionsObject()
250  {
251  static $graphicalFunctionsObject = null;
252  if ($graphicalFunctionsObject === null) {
253  $graphicalFunctionsObject = GeneralUtility::makeInstance(GraphicalFunctions::class);
254  }
255  return $graphicalFunctionsObject;
256  }
257 }
resizeImage($originalFileName, $temporaryFileName, $configuration)
getConfigurationForImageCropScaleMask(array $configuration, GifBuilder $gifBuilder)
getTargetFileName(ProcessedFile $processedFile, $prefix= 'preview_')
static imageMagickCommand($command, $parameters, $path= '')
static unlink_tempfile($uploadedTempFileName)
static exec($command, &$output=null, &$returnValue=0)
if(TYPO3_MODE=== 'BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
static makeInstance($className,...$constructorArguments)
static forceIntegerInRange($theInt, $min, $max=2000000000, $defaultValue=0)
Definition: MathUtility.php:31