brandfolder-8.x-1.x-dev/src/Plugin/ImageToolkit/Operation/brandfolder/Crop.php

src/Plugin/ImageToolkit/Operation/brandfolder/Crop.php
<?php

namespace Drupal\brandfolder\Plugin\ImageToolkit\Operation\brandfolder;

/**
 * Defines Brandfolder Crop operation.
 *
 * @ImageToolkitOperation(
 *   id = "brandfolder_crop",
 *   toolkit = "brandfolder",
 *   operation = "crop",
 *   label = @Translation("Crop"),
 *   description = @Translation("Crops an image to a rectangle specified by the given dimensions.")
 * )
 */
class Crop extends BrandfolderImageToolkitOperationBase {

  /**
   * {@inheritdoc}
   */
  protected function arguments() {
    return [
      'x' => [
        'description' => 'The starting x offset at which to start the crop, in pixels',
      ],
      'y' => [
        'description' => 'The starting y offset at which to start the crop, in pixels',
      ],
      'width' => [
        'description' => 'The width of the cropped area, in pixels',
        'required' => FALSE,
        'default' => NULL,
      ],
      'height' => [
        'description' => 'The height of the cropped area, in pixels',
        'required' => FALSE,
        'default' => NULL,
      ],
    ];
  }

  /**
   * {@inheritdoc}
   */
  protected function validateArguments(array $arguments) {
    // Assure at least one dimension.
    if (empty($arguments['width']) && empty($arguments['height'])) {
      throw new \InvalidArgumentException("At least one dimension ('width' or 'height') must be provided to the image 'crop' operation");
    }

    // If either the width or height argument is missing, try to calculate the
    // missing arg from the available arg, based on the image aspect ratio.
    $aspect = $this->getToolkit()->getHeight() / $this->getToolkit()->getWidth();
    $arguments['height'] = empty($arguments['height']) ? $arguments['width'] * $aspect : $arguments['height'];
    $arguments['width'] = empty($arguments['width']) ? $arguments['height'] / $aspect : $arguments['width'];

    // Assure integers for all arguments.
    foreach (['x', 'y', 'width', 'height'] as $key) {
      $arguments[$key] = (int) round($arguments[$key]);
    }

    // Fail when width or height are 0 or negative.
    if ($arguments['width'] <= 0) {
      throw new \InvalidArgumentException("Invalid width ('{$arguments['width']}') specified for the image 'crop' operation");
    }
    if ($arguments['height'] <= 0) {
      throw new \InvalidArgumentException("Invalid height ('{$arguments['height']}') specified for the image 'crop' operation");
    }

    return $arguments;
  }

  /**
   * {@inheritdoc}
   */
  protected function execute(array $arguments) {
    $toolkit = $this->getToolkit();
    $new_width = $crop_width = $arguments['width'];
    $new_height = $crop_height = $arguments['height'];
    $crop_x = $arguments['x'];
    $crop_y = $arguments['y'];
    // Check to see if the image was scaled prior to this crop operation.
    // If so, convert the crop values so they can be applied to the original
    // image (Brandfolder/Fastly applies crop before scale).
    $previous_operations = $toolkit->getOperationsRecord();
    $previously_scaled = FALSE;
    while ($previous_operation = array_pop($previous_operations)) {
      if ($previous_operation['operation'] == 'resize') {
        $previously_scaled = TRUE;
        break;
      }
    }
    if ($previously_scaled) {
      $original_width = $toolkit->getOriginalFileDataItem('width');
      $current_width = $toolkit->getWidth();
      $width_scale_factor = $original_width / $current_width;
      $original_height = $toolkit->getOriginalFileDataItem('height');
      $current_height = $toolkit->getheight();
      $height_scale_factor = $original_height / $current_height;
      $scale_factor = max($width_scale_factor, $height_scale_factor);
      $crop_x = round($crop_x * $scale_factor);
      $crop_y = round($crop_y * $scale_factor);
      $crop_width = round($new_width * $scale_factor);
      $crop_height = round($new_height * $scale_factor);
    }
    $params = [
      // Note: Brandfolder's Fastly Image Optimizer implementation seems to
      // always apply the "crop" param before width and height scaling, thereby
      // rendering "crop" and "precrop" identical for our purposes. Use precrop
      // in case this changes. Revisit if adding support for other
      // transformations.
      // @todo: Make the "safe" crop mode configurable globally for Drupal-BF integration?
      'precrop' => "{$crop_width},{$crop_height},x{$crop_x},y{$crop_y},safe",
      'width' => $new_width,
      'height' => $new_height,
    ];
    $toolkit->setCdnUrlParams($params);
    $toolkit->setFileDataItem('width', $new_width);
    $toolkit->setFileDataItem('height', $new_height);
    $toolkit->recordOperation("crop", $arguments);

    return TRUE;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc