예제 #1
0
 /**
  * Process image and write the result in the image cache.
  *
  * If the image already exists in cache, the cache file is immediately returned, without any processing
  * If the original (full resolution) image is required, create either a symbolic link with the
  * original image in the cache dir, or copy it in the cache dir.
  *
  * This method updates the cache_file_path and file_url attributes of the event
  *
  * @param ImageEvent $event
  * @param string $eventName
  * @param EventDispatcherInterface $dispatcher
  *
  * @throws \Thelia\Exception\ImageException
  * @throws \InvalidArgumentException
  */
 public function processImage(ImageEvent $event, $eventName, EventDispatcherInterface $dispatcher)
 {
     $subdir = $event->getCacheSubdirectory();
     $source_file = $event->getSourceFilepath();
     if (null == $subdir || null == $source_file) {
         throw new \InvalidArgumentException("Cache sub-directory and source file path cannot be null");
     }
     // Find cached file path
     $cacheFilePath = $this->getCacheFilePath($subdir, $source_file, $event->isOriginalImage(), $event->getOptionsHash());
     $originalImagePathInCache = $this->getCacheFilePath($subdir, $source_file, true);
     if (!file_exists($cacheFilePath)) {
         if (!file_exists($source_file)) {
             throw new ImageException(sprintf("Source image file %s does not exists.", $source_file));
         }
         // Create a cached version of the original image in the web space, if not exists
         if (!file_exists($originalImagePathInCache)) {
             $mode = ConfigQuery::read('original_image_delivery_mode', 'symlink');
             if ($mode == 'symlink') {
                 if (false === symlink($source_file, $originalImagePathInCache)) {
                     throw new ImageException(sprintf("Failed to create symbolic link for %s in %s image cache directory", basename($source_file), $subdir));
                 }
             } else {
                 // mode = 'copy'
                 if (false === @copy($source_file, $originalImagePathInCache)) {
                     throw new ImageException(sprintf("Failed to copy %s in %s image cache directory", basename($source_file), $subdir));
                 }
             }
         }
         // Process image only if we have some transformations to do.
         if (!$event->isOriginalImage()) {
             // We have to process the image.
             $imagine = $this->createImagineInstance();
             $image = $imagine->open($source_file);
             if ($image) {
                 // Allow image pre-processing (watermarging, or other stuff...)
                 $event->setImageObject($image);
                 $dispatcher->dispatch(TheliaEvents::IMAGE_PREPROCESSING, $event);
                 $image = $event->getImageObject();
                 $background_color = $event->getBackgroundColor();
                 $palette = new RGB();
                 if ($background_color != null) {
                     $bg_color = $palette->color($background_color);
                 } else {
                     // Define a fully transparent white background color
                     $bg_color = $palette->color('fff', 0);
                 }
                 // Apply resize
                 $image = $this->applyResize($imagine, $image, $event->getWidth(), $event->getHeight(), $event->getResizeMode(), $bg_color, $event->getAllowZoom());
                 // Rotate if required
                 $rotation = intval($event->getRotation());
                 if ($rotation != 0) {
                     $image->rotate($rotation, $bg_color);
                 }
                 // Flip
                 // Process each effects
                 foreach ($event->getEffects() as $effect) {
                     $effect = trim(strtolower($effect));
                     $params = explode(':', $effect);
                     switch ($params[0]) {
                         case 'greyscale':
                         case 'grayscale':
                             $image->effects()->grayscale();
                             break;
                         case 'negative':
                             $image->effects()->negative();
                             break;
                         case 'horizontal_flip':
                         case 'hflip':
                             $image->flipHorizontally();
                             break;
                         case 'vertical_flip':
                         case 'vflip':
                             $image->flipVertically();
                             break;
                         case 'gamma':
                             // Syntax: gamma:value. Exemple: gamma:0.7
                             if (isset($params[1])) {
                                 $gamma = floatval($params[1]);
                                 $image->effects()->gamma($gamma);
                             }
                             break;
                         case 'colorize':
                             // Syntax: colorize:couleur. Exemple: colorize:#ff00cc
                             if (isset($params[1])) {
                                 $the_color = $palette->color($params[1]);
                                 $image->effects()->colorize($the_color);
                             }
                             break;
                     }
                 }
                 $quality = $event->getQuality();
                 if (is_null($quality)) {
                     $quality = ConfigQuery::read('default_images_quality_percent', 75);
                 }
                 // Allow image post-processing (watermarging, or other stuff...)
                 $event->setImageObject($image);
                 $dispatcher->dispatch(TheliaEvents::IMAGE_POSTPROCESSING, $event);
                 $image = $event->getImageObject();
                 $image->save($cacheFilePath, array('quality' => $quality));
             } else {
                 throw new ImageException(sprintf("Source file %s cannot be opened.", basename($source_file)));
             }
         }
     }
     // Compute the image URL
     $processed_image_url = $this->getCacheFileURL($subdir, basename($cacheFilePath));
     // compute the full resolution image path in cache
     $original_image_url = $this->getCacheFileURL($subdir, basename($originalImagePathInCache));
     // Update the event with file path and file URL
     $event->setCacheFilepath($cacheFilePath);
     $event->setCacheOriginalFilepath($originalImagePathInCache);
     $event->setFileUrl(URL::getInstance()->absoluteUrl($processed_image_url, null, URL::PATH_TO_FILE));
     $event->setOriginalFileUrl(URL::getInstance()->absoluteUrl($original_image_url, null, URL::PATH_TO_FILE));
 }