/**
  * Processing the focus point crop (fallback to LocalCropScaleMaskHelper)
  *
  * @param TaskInterface $task
  *
  * @return array|NULL
  */
 public function process(TaskInterface $task)
 {
     $configuration = $task->getConfiguration();
     $crop = $configuration['crop'] ? json_decode($configuration['crop']) : null;
     if ($crop instanceof \stdClass && isset($crop->x)) {
         // if crop is enable release the process
         return parent::process($task);
     }
     $sourceFile = $task->getSourceFile();
     try {
         if (self::$deepCheck === false) {
             self::$deepCheck = true;
             $ratio = $this->getCurrentRatioConfiguration();
             $this->dimensionService->getRatio($ratio);
             $newFile = $this->focusCropService->getCroppedImageSrcByFile($sourceFile, $ratio);
             $file = ResourceFactory::getInstance()->retrieveFileOrFolderObject($newFile);
             $targetFile = $task->getTargetFile();
             ObjectAccess::setProperty($targetFile, 'originalFile', $file, true);
             ObjectAccess::setProperty($targetFile, 'originalFileSha1', $file->getSha1(), true);
             ObjectAccess::setProperty($targetFile, 'storage', $file->getStorage(), true);
             ObjectAccess::setProperty($task, 'sourceFile', $file, true);
             ObjectAccess::setProperty($task, 'targetFile', $targetFile, true);
         }
     } catch (\Exception $ex) {
     }
     self::$deepCheck = false;
     return parent::process($task);
 }
 /**
  * This method actually does the processing of files locally
  *
  * takes the original file (on remote storages this will be fetched from the remote server)
  * does the IM magic on the local server by creating a temporary typo3temp/ file
  * copies the typo3temp/ file to the processing folder of the target storage
  * removes the typo3temp/ file
  *
  * @param TaskInterface $task
  * @return array
  */
 public function process(TaskInterface $task)
 {
     $targetFile = $task->getTargetFile();
     // Merge custom configuration with default configuration
     $configuration = array_merge(array('width' => 64, 'height' => 64), $task->getConfiguration());
     $configuration['width'] = Utility\MathUtility::forceIntegerInRange($configuration['width'], 1, 1000);
     $configuration['height'] = Utility\MathUtility::forceIntegerInRange($configuration['height'], 1, 1000);
     $originalFileName = $targetFile->getOriginalFile()->getForLocalProcessing(FALSE);
     // Create a temporary file in typo3temp/
     if ($targetFile->getOriginalFile()->getExtension() === 'jpg') {
         $targetFileExtension = '.jpg';
     } else {
         $targetFileExtension = '.png';
     }
     // Create the thumb filename in typo3temp/preview_....jpg
     $temporaryFileName = Utility\GeneralUtility::tempnam('preview_') . $targetFileExtension;
     // Check file extension
     if ($targetFile->getOriginalFile()->getType() != Resource\File::FILETYPE_IMAGE && !Utility\GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $targetFile->getOriginalFile()->getExtension())) {
         // Create a default image
         $this->processor->getTemporaryImageWithText($temporaryFileName, 'Not imagefile!', 'No ext!', $targetFile->getOriginalFile()->getName());
     } else {
         // Create the temporary file
         if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['im']) {
             $parameters = '-sample ' . $configuration['width'] . 'x' . $configuration['height'] . ' ' . $this->processor->wrapFileName($originalFileName) . '[0] ' . $this->processor->wrapFileName($temporaryFileName);
             $cmd = Utility\GeneralUtility::imageMagickCommand('convert', $parameters) . ' 2>&1';
             Utility\CommandUtility::exec($cmd);
             if (!file_exists($temporaryFileName)) {
                 // Create a error gif
                 $this->processor->getTemporaryImageWithText($temporaryFileName, 'No thumb', 'generated!', $targetFile->getOriginalFile()->getName());
             }
         }
     }
     return array('filePath' => $temporaryFileName);
 }
 /**
  * @param TaskInterface $task
  * @return array|null
  */
 protected function process(TaskInterface $task)
 {
     $result = NULL;
     $sourceFile = $task->getOriginalProcessedFile() ?: $task->getSourceFile();
     $sourceFilePath = realpath($sourceFile->getForLocalProcessing(FALSE));
     $targetFilePath = realpath(GeneralUtility::tempnam('_processed_/nlx-tempfile-', '.' . $sourceFile->getExtension()));
     switch ($sourceFile->getExtension()) {
         case 'jpg':
         case 'jpeg':
             if ($this->settings['jpg.']['enabled'] === FALSE) {
                 return $result;
             }
             $library = 'jpegtran';
             $arguments = sprintf('-copy none -optimize %s -outfile %s %s', $this->settings['jpg.']['progressive'] === TRUE ? '-progressive' : '', escapeshellarg($targetFilePath), escapeshellarg($sourceFilePath));
             break;
         case 'png':
             if ($this->settings['png.']['enabled'] === FALSE) {
                 return $result;
             }
             $library = 'optipng';
             $arguments = sprintf('-o%u -strip all -fix -clobber -force -out %s %s', $this->settings['png.']['optimizationLevel'], escapeshellarg($targetFilePath), escapeshellarg($sourceFilePath));
             break;
         case 'gif':
             if ($this->settings['gif.']['enabled'] === FALSE) {
                 return $result;
             }
             $library = 'gifsicle';
             $arguments = sprintf('--batch -O%u -o %s %s', $this->settings['gif.']['optimizationLevel'], escapeshellarg($targetFilePath), escapeshellarg($sourceFilePath));
             break;
         case 'svg':
             if ($this->settings['svg.']['enabled'] === FALSE) {
                 return $result;
             }
             $library = 'svgo';
             $arguments = sprintf('%s %s', escapeshellarg($sourceFilePath), escapeshellarg($targetFilePath));
             break;
         default:
             return $result;
     }
     $cmd = escapeshellcmd($library) . ' ' . $arguments;
     $output = [];
     exec($cmd, $output, $return);
     if ($return === 0) {
         $result = array('filePath' => $targetFilePath);
     }
     return $result;
 }
 /**
  * Processing the focus point crop (fallback to LocalCropScaleMaskHelper)
  *
  * @param TaskInterface $task
  *
  * @return array|NULL
  */
 public function process(TaskInterface $task)
 {
     $sourceFile = $task->getSourceFile();
     try {
         $ratio = $this->getCurrentRatioConfiguration();
         $this->dimensionService->getRatio($ratio);
         $newFile = $this->focusCropService->getCroppedImageSrcByFile($sourceFile, $ratio);
         $file = ResourceFactory::getInstance()->retrieveFileOrFolderObject($newFile);
         $targetFile = $task->getTargetFile();
         ObjectAccess::setProperty($targetFile, 'originalFile', $file, TRUE);
         ObjectAccess::setProperty($targetFile, 'originalFileSha1', $file->getSha1(), TRUE);
         ObjectAccess::setProperty($targetFile, 'storage', $file->getStorage(), TRUE);
         ObjectAccess::setProperty($task, 'sourceFile', $file, TRUE);
         ObjectAccess::setProperty($task, 'targetFile', $targetFile, TRUE);
     } catch (\Exception $ex) {
     }
     return parent::process($task);
 }
 /**
  * Returns TRUE if this processor can process the given task.
  *
  * @param TaskInterface $task
  * @return boolean
  */
 public function canProcessTask(TaskInterface $task)
 {
     $canProcessTask = $task->getType() === 'Image';
     $canProcessTask = $canProcessTask & in_array($task->getName(), array('Preview', 'CropScaleMask'));
     return $canProcessTask;
 }
 /**
  * Returns the filename for a cropped/scaled/masked file.
  *
  * @param TaskInterface $task
  * @return string
  */
 protected function getFilenameForImageCropScaleMask(TaskInterface $task)
 {
     $configuration = $task->getTargetFile()->getProcessingConfiguration();
     $targetFileExtension = $task->getSourceFile()->getExtension();
     $processedFileExtension = $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png'] ? 'png' : 'gif';
     if (is_array($configuration['maskImages']) && $GLOBALS['TYPO3_CONF_VARS']['GFX']['im'] && $task->getSourceFile()->getExtension() != $processedFileExtension) {
         $targetFileExtension = 'jpg';
     } elseif ($configuration['fileExtension']) {
         $targetFileExtension = $configuration['fileExtension'];
     }
     return $task->getTargetFile()->generateProcessedFileNameWithoutExtension() . '.' . ltrim(trim($targetFileExtension), '.');
 }
 /**
  * Check if the to be processed target file already exists
  * if exist take info from that file and mark task as done
  *
  * @param TaskInterface $task
  * @return bool
  */
 protected function checkForExistingTargetFile(TaskInterface $task)
 {
     $processingFolder = $task->getTargetFile()->getStorage()->getProcessingFolder();
     $storage = $task->getTargetFile()->getStorage();
     // @todo: make proper use of the FAL API, see https://forge.typo3.org/issues/67126
     if ($processingFolder->hasFile($task->getTargetFileName()) && $storage->getDriverType() === 'Local') {
         $processedFileIdentifier = rtrim($processingFolder->getIdentifier(), '/') . '/' . $task->getTargetFileName();
         $configuration = $storage->getConfiguration();
         if ($configuration['pathType'] === 'relative') {
             $absoluteBasePath = PATH_site . $configuration['basePath'];
         } else {
             $absoluteBasePath = $configuration['basePath'];
         }
         $targetFile = $absoluteBasePath . ltrim($processedFileIdentifier, '/');
         $task->setExecuted(true);
         $imageDimensions = $this->getGraphicalFunctionsObject()->getImageDimensions($targetFile);
         $task->getTargetFile()->setName($task->getTargetFileName());
         $properties = array('width' => $imageDimensions[0], 'height' => $imageDimensions[1], 'size' => filesize($targetFile), 'checksum' => $task->getConfigurationChecksum());
         $task->getTargetFile()->updateProperties($properties);
         return true;
     } else {
         return false;
     }
 }
 /**
  * Returns the path to a temporary file for processing
  *
  * @param TaskInterface $task
  * @return string
  */
 protected function getTemporaryFilePath(TaskInterface $task)
 {
     return GeneralUtility::tempnam('preview_', '.' . $task->getTargetFileExtension());
 }
 /**
  * Check if the to be processed target file already exists
  * if exist take info from that file and mark task as done
  *
  * @param TaskInterface $task
  * @return bool
  */
 protected function checkForExistingTargetFile(TaskInterface $task)
 {
     // the storage of the processed file, not of the original file!
     $storage = $task->getTargetFile()->getStorage();
     $processingFolder = $storage->getProcessingFolder();
     // explicitly check for the raw filename here, as we check for files that existed before we even started
     // processing, i.e. that were processed earlier
     if ($processingFolder->hasFile($task->getTargetFileName())) {
         // When the processed file already exists set it as processed file
         $task->getTargetFile()->setName($task->getTargetFileName());
         // If the processed file is stored on a remote server, we must fetch a local copy of the file, as we
         // have no API for fetching file metadata from a remote file.
         $localProcessedFile = $storage->getFileForLocalProcessing($task->getTargetFile(), false);
         $task->setExecuted(true);
         $imageDimensions = $this->getGraphicalFunctionsObject()->getImageDimensions($localProcessedFile);
         $properties = array('width' => $imageDimensions[0], 'height' => $imageDimensions[1], 'size' => filesize($localProcessedFile), 'checksum' => $task->getConfigurationChecksum());
         $task->getTargetFile()->updateProperties($properties);
         return true;
     } else {
         return false;
     }
 }
 /**
  * This method actually does the processing of files locally
  *
  * Takes the original file (for remote storages this will be fetched from the remote server),
  * does the IM magic on the local server by creating a temporary typo3temp/ file,
  * copies the typo3temp/ file to the processing folder of the target storage and
  * removes the typo3temp/ file.
  *
  * @param TaskInterface $task
  * @return array
  */
 public function process(TaskInterface $task)
 {
     $result = NULL;
     $targetFile = $task->getTargetFile();
     $originalFileName = $targetFile->getOriginalFile()->getForLocalProcessing(FALSE);
     /** @var $gifBuilder \TYPO3\CMS\Frontend\Imaging\GifBuilder */
     $gifBuilder = Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Imaging\\GifBuilder');
     $gifBuilder->init();
     $configuration = $targetFile->getProcessingConfiguration();
     $configuration['additionalParameters'] = $this->modifyImageMagickStripProfileParameters($configuration['additionalParameters'], $configuration);
     $options = $this->getConfigurationForImageCropScaleMask($targetFile, $gifBuilder);
     // Normal situation (no masking)
     if (!(is_array($configuration['maskImages']) && $GLOBALS['TYPO3_CONF_VARS']['GFX']['im'])) {
         // the result info is an array with 0=width,1=height,2=extension,3=filename
         $result = $gifBuilder->imageMagickConvert($originalFileName, $configuration['fileExtension'], $configuration['width'], $configuration['height'], $configuration['additionalParameters'], $configuration['frame'], $options);
     } else {
         $targetFileName = $this->getFilenameForImageCropScaleMask($targetFile);
         $temporaryFileName = $gifBuilder->tempPath . $targetFileName;
         $maskImage = $configuration['maskImages']['maskImage'];
         $maskBackgroundImage = $configuration['maskImages']['backgroundImage'];
         if ($maskImage instanceof Resource\FileInterface && $maskBackgroundImage instanceof Resource\FileInterface) {
             $negate = $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_negate_mask'] ? ' -negate' : '';
             $temporaryExtension = 'png';
             if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_mask_temp_ext_gif']) {
                 // If ImageMagick version 5+
                 $temporaryExtension = $gifBuilder->gifExtension;
             }
             $tempFileInfo = $gifBuilder->imageMagickConvert($originalFileName, $temporaryExtension, $configuration['width'], $configuration['height'], $configuration['additionalParameters'], $configuration['frame'], $options);
             if (is_array($tempFileInfo)) {
                 $maskBottomImage = $configuration['maskImages']['maskBottomImage'];
                 if ($maskBottomImage instanceof $maskBottomImage) {
                     $maskBottomImageMask = $configuration['maskImages']['maskBottomImageMask'];
                 } else {
                     $maskBottomImageMask = NULL;
                 }
                 //	Scaling:	****
                 $tempScale = array();
                 $command = '-geometry ' . $tempFileInfo[0] . 'x' . $tempFileInfo[1] . '!';
                 $command = $this->modifyImageMagickStripProfileParameters($command, $configuration);
                 $tmpStr = $gifBuilder->randomName();
                 //	m_mask
                 $tempScale['m_mask'] = $tmpStr . '_mask.' . $temporaryExtension;
                 $gifBuilder->imageMagickExec($maskImage->getForLocalProcessing(TRUE), $tempScale['m_mask'], $command . $negate);
                 //	m_bgImg
                 $tempScale['m_bgImg'] = $tmpStr . '_bgImg.' . trim($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_mask_temp_ext_noloss']);
                 $gifBuilder->imageMagickExec($maskBackgroundImage->getForLocalProcessing(), $tempScale['m_bgImg'], $command);
                 //	m_bottomImg / m_bottomImg_mask
                 if ($maskBottomImage instanceof Resource\FileInterface && $maskBottomImageMask instanceof Resource\FileInterface) {
                     $tempScale['m_bottomImg'] = $tmpStr . '_bottomImg.' . $temporaryExtension;
                     $gifBuilder->imageMagickExec($maskBottomImage->getForLocalProcessing(), $tempScale['m_bottomImg'], $command);
                     $tempScale['m_bottomImg_mask'] = $tmpStr . '_bottomImg_mask.' . $temporaryExtension;
                     $gifBuilder->imageMagickExec($maskBottomImageMask->getForLocalProcessing(), $tempScale['m_bottomImg_mask'], $command . $negate);
                     // BEGIN combining:
                     // The image onto the background
                     $gifBuilder->combineExec($tempScale['m_bgImg'], $tempScale['m_bottomImg'], $tempScale['m_bottomImg_mask'], $tempScale['m_bgImg']);
                 }
                 // The image onto the background
                 $gifBuilder->combineExec($tempScale['m_bgImg'], $tempFileInfo[3], $tempScale['m_mask'], $temporaryFileName);
                 // Unlink the temp-images...
                 foreach ($tempScale as $tempFile) {
                     if (@is_file($tempFile)) {
                         unlink($tempFile);
                     }
                 }
             }
             $result = $tempFileInfo;
         }
     }
     // check if the processing really generated a new file
     if ($result !== NULL) {
         if ($result[3] !== $originalFileName) {
             $result = array('width' => $result[0], 'height' => $result[1], 'filePath' => $result[3]);
         } else {
             // No file was generated
             $result = NULL;
         }
     }
     return $result;
 }