You are here

class AddWatermark in Basic Watermark 8

Defines GD2 Add Watermark operation.

Plugin annotation


@ImageToolkitOperation(
  id = "gd_add_watermark",
  toolkit = "gd",
  operation = "add_watermark",
  label = @Translation("Add Watermark"),
  description = @Translation("Adds a watermark to the image.")
)

Hierarchy

Expanded class hierarchy of AddWatermark

File

src/Plugin/ImageToolkit/Operation/gd/AddWatermark.php, line 18

Namespace

Drupal\basic_watermark\Plugin\ImageToolkit\Operation\gd
View source
class AddWatermark extends GDImageToolkitOperationBase {

  /**
   * {@inheritdoc}
   */
  protected function arguments() {
    return [
      'watermark_path' => [
        'description' => 'The path to the watermark image',
      ],
      'apply_type' => [
        'description' => 'How to apply the watermark, repeat until it covers the whole image or once',
      ],
      'position' => [
        'description' => 'Where to put the watermark, ex: top-left, center, bottom-right',
      ],
      'margins' => [
        'description' => 'Empty area to keep around the watermark in pixels',
      ],
    ];
  }

  /**
   * {@inheritdoc}
   */
  protected function validateArguments(array $arguments) {
    $path = DRUPAL_ROOT . $arguments['watermark_path'];
    if (!file_exists($path) || !getimagesize($path)) {
      throw new \InvalidArgumentException("Invalid image ('{$arguments['watermark_path']}')");
    }
    return $arguments;
  }

  /**
   * {@inheritdoc}
   */
  protected function execute(array $arguments) {
    $image_resource = $this
      ->getToolkit()
      ->getResource();
    $watermark_filepath = DRUPAL_ROOT . $arguments['watermark_path'];
    $watermark_image = imagecreatefrompng($watermark_filepath);
    $image['width'] = imagesx($image_resource);
    $image['height'] = imagesy($image_resource);
    $watermark = $this
      ->scaleWatermark($watermark_image, $image, $arguments['margins']);
    $margins = $this
      ->getMargins($image, $watermark, $arguments['position'], $arguments['margins']);
    $temp_resource = $this
      ->getToolkit()
      ->getResource();
    switch ($arguments['apply_type']) {
      case 'repeat':

        // Repeat always starts from top left.
        $start_x = $arguments['margins']['left'];
        for ($i = 0; $i < $image['width'] / $watermark['width'] + 1; $i++) {
          $start_y = $arguments['margins']['top'];
          for ($j = 0; $j < $image['height'] / $watermark['height'] + 1; $j++) {
            $resource = imagecopy($temp_resource, $watermark['image'], $start_x, $start_y, 0, 0, min($watermark['width'], $image['width'] - $start_x), min($watermark['height'], $image['height'] - $start_y));

            // If at any point the image copy fails fail the operation.
            if (!$resource) {
              $this
                ->getToolkit()
                ->setResource($image_resource);
              return FALSE;
            }
            $start_y += $arguments['margins']['top'] + $watermark['height'];
          }
          $start_x += $arguments['margins']['left'] + $watermark['width'];
        }
        break;
      case 'once':
        $resource = imagecopy($temp_resource, $watermark['image'], $margins['x'], $margins['y'], 0, 0, $watermark['width'], $watermark['height']);
        if (!$resource) {
          $this
            ->getToolkit()
            ->setResource($image_resource);
          return FALSE;
        }
        break;
      default:
        return FALSE;
    }
    $this
      ->getToolkit()
      ->setResource(TRUE);
    imagedestroy($image_resource);
    return TRUE;
  }

  /**
   * Scales the watermark to fit in the image.
   *
   * The watermark will only be scaled down if its too big, taking into
   * consideration the provided margins.
   *
   * @param resource $watermark_image
   *   The watermark gd resource.
   * @param array $image
   *   An array with the width and height of the image to apply the watermark.
   * @param array $margins
   *   The margins to keep around the watermark.
   *
   * @return array
   *   An array of the scaled watermark as well as its width and height.
   */
  private function scaleWatermark($watermark_image, array $image, array &$margins) {
    $watermark['width'] = imagesx($watermark_image);
    $watermark['height'] = imagesy($watermark_image);

    // If the width of the margins exceed the image height remove the margins.
    if ($margins['left'] + $margins['right'] >= $image['width']) {
      $margins['left'] = 0;
      $margins['right'] = 0;
    }

    // If the height of the margins exceed the image height remove the margins.
    if ($margins['top'] + $margins['bottom'] >= $image['height']) {
      $margins['top'] = 0;
      $margins['bottom'] = 0;
    }

    // Scale Watermark to fit on image horizontaly.
    if ($watermark['width'] + $margins['left'] + $margins['right'] > $image['width']) {
      $watermark['width'] = $image['width'] - $margins['left'] - $margins['right'];
      $watermark_image = imagescale($watermark_image, $watermark['width']);
      $watermark['height'] = imagesy($watermark_image);
    }

    // Scale Watermark to fit on image vertically.
    if ($watermark['height'] + $margins['top'] + $margins['bottom'] > $image['height']) {
      $watermark['height'] = $image['height'] - $margins['top'] - $margins['bottom'];

      // New width = new height * (original width / original height)
      $watermark['width'] = $watermark['height'] * (imagesx($watermark_image) / imagesy($watermark_image));
      $watermark_image = imagescale($watermark_image, $watermark['width'], $watermark['height']);
    }
    return [
      'image' => $watermark_image,
      'width' => $watermark['width'],
      'height' => $watermark['height'],
    ];
  }

  /**
   * Gets the offset of where to put the watermark dependend of its position.
   *
   * Depending on the position selected we calculate the x and y offset taking
   * into consideration the margins provided.
   *
   * @param array $image
   *   The image width and height.
   * @param array $watermark
   *   The watermark gd resource, width and height.
   * @param string $position
   *   The position the watermark is going to be placed.
   * @param array $margins
   *   The margins to keep around the watermark.
   *
   * @return array
   *   The x and y offset.
   */
  private function getMargins(array $image, array $watermark, string $position, array $margins) {
    switch ($position) {
      case 'left-top':
        return [
          'x' => $margins['left'],
          'y' => $margins['top'],
        ];
      case 'center-top':
        return [
          'x' => $image['width'] / 2 - $watermark['width'] / 2,
          'y' => $margins['top'],
        ];
      case 'right-top':
        return [
          'x' => $image['width'] - $watermark['width'] - $margins['left'],
          'y' => $margins['top'],
        ];
      case 'left-center':
        return [
          'x' => $margins['left'],
          'y' => $image['height'] / 2 - $watermark['height'] / 2,
        ];
      case 'center-center':
        return [
          'x' => $image['width'] / 2 - $watermark['width'] / 2,
          'y' => $image['height'] / 2 - $watermark['height'] / 2,
        ];
      case 'right-center':
        return [
          'x' => $image['width'] - $watermark['width'] - $margins['left'],
          'y' => $image['height'] / 2 - $watermark['height'] / 2,
        ];
      case 'left-bottom':
        return [
          'x' => $margins['left'],
          'y' => $image['height'] - $watermark['height'] - $margins['top'],
        ];
      case 'center-bottom':
        return [
          'x' => $image['width'] / 2 - $watermark['width'] / 2,
          'y' => $image['height'] - $watermark['height'] - $margins['top'],
        ];
      case 'right-bottom':
        return [
          'x' => $image['width'] - $watermark['width'] - $margins['left'],
          'y' => $image['height'] - $watermark['height'] - $margins['top'],
        ];
      default:
        return [
          'x' => $margins['left'],
          'y' => $margins['top'],
        ];
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
AddWatermark::arguments protected function Returns the definition of the operation arguments. Overrides ImageToolkitOperationBase::arguments
AddWatermark::execute protected function Performs the actual manipulation on the image. Overrides ImageToolkitOperationBase::execute
AddWatermark::getMargins private function Gets the offset of where to put the watermark dependend of its position.
AddWatermark::scaleWatermark private function Scales the watermark to fit in the image.
AddWatermark::validateArguments protected function Validates the arguments. Overrides ImageToolkitOperationBase::validateArguments
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
GDImageToolkitOperationBase::getToolkit protected function The correctly typed image toolkit for GD operations. Overrides ImageToolkitOperationBase::getToolkit
ImageToolkitOperationBase::$logger protected property A logger instance.
ImageToolkitOperationBase::$toolkit protected property The image toolkit.
ImageToolkitOperationBase::apply final public function Applies a toolkit specific operation to an image. Overrides ImageToolkitOperationInterface::apply
ImageToolkitOperationBase::prepareArguments protected function Checks if required arguments are passed in and adds defaults for non passed in optional arguments.
ImageToolkitOperationBase::__construct public function Constructs an image toolkit operation plugin. Overrides PluginBase::__construct
MessengerTrait::$messenger protected property The messenger. 29
MessengerTrait::messenger public function Gets the messenger. 29
MessengerTrait::setMessenger public function Sets the messenger.
PluginBase::$configuration protected property Configuration information passed into the plugin. 1
PluginBase::$pluginDefinition protected property The plugin implementation definition. 1
PluginBase::$pluginId protected property The plugin_id.
PluginBase::DERIVATIVE_SEPARATOR constant A string which is used to separate base plugin IDs from the derivative ID.
PluginBase::getBaseId public function Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface::getBaseId
PluginBase::getDerivativeId public function Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface::getDerivativeId
PluginBase::getPluginDefinition public function Gets the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition 3
PluginBase::getPluginId public function Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
PluginBase::isConfigurable public function Determines if the plugin is configurable.
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.