abstract class FocalPointEffectBase in Focal Point 8
Provides a base class for image effects.
Hierarchy
- class \Drupal\Component\Plugin\PluginBase implements DerivativeInspectionInterface, PluginInspectionInterface
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
- class \Drupal\image\ImageEffectBase implements ContainerFactoryPluginInterface, ImageEffectInterface
- class \Drupal\image\ConfigurableImageEffectBase implements ConfigurableImageEffectInterface
- class \Drupal\image\Plugin\ImageEffect\ResizeImageEffect
- class \Drupal\focal_point\FocalPointEffectBase implements ContainerFactoryPluginInterface
- class \Drupal\image\Plugin\ImageEffect\ResizeImageEffect
- class \Drupal\image\ConfigurableImageEffectBase implements ConfigurableImageEffectInterface
- class \Drupal\image\ImageEffectBase implements ContainerFactoryPluginInterface, ImageEffectInterface
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
Expanded class hierarchy of FocalPointEffectBase
3 files declare their use of FocalPointEffectBase
- FocalPointCropImageEffect.php in src/
Plugin/ ImageEffect/ FocalPointCropImageEffect.php - FocalPointEffectsTest.php in tests/
src/ Unit/ Effects/ FocalPointEffectsTest.php - FocalPointScaleAndCropImageEffect.php in src/
Plugin/ ImageEffect/ FocalPointScaleAndCropImageEffect.php
File
- src/
FocalPointEffectBase.php, line 19
Namespace
Drupal\focal_pointView source
abstract class FocalPointEffectBase extends ResizeImageEffect implements ContainerFactoryPluginInterface {
/**
* Crop storage.
*
* @var \Drupal\crop\CropStorageInterface
*/
protected $cropStorage;
/**
* Focal point configuration object.
*
* @var \Drupal\Core\Config\ImmutableConfig
*/
protected $focalPointConfig;
/**
* The original image dimensions before any effects are applied.
*
* @var array
*/
protected $originalImageSize;
/**
* Focal point manager object.
*
* @var \Drupal\focal_point\FocalPointManager
*/
protected $focalPointManager;
/**
* The current request object.
*
* @var \Symfony\Component\HttpFoundation\Request
*/
public $request;
/**
* Constructs a \Drupal\focal_point\FocalPointEffectBase object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Psr\Log\LoggerInterface $logger
* Image logger.
* @param \Drupal\focal_point\FocalPointManager $focal_point_manager
* Focal point manager.
* @param \Drupal\crop\CropStorageInterface $crop_storage
* Crop storage.
* @param \Drupal\Core\Config\ImmutableConfig $focal_point_config
* Focal point configuration object.
* @param \Symfony\Component\HttpFoundation\Request $request
* Current request object.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, LoggerInterface $logger, FocalPointManager $focal_point_manager, CropStorageInterface $crop_storage, ImmutableConfig $focal_point_config, Request $request) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $logger);
$this->focalPointManager = $focal_point_manager;
$this->cropStorage = $crop_storage;
$this->focalPointConfig = $focal_point_config;
$this->request = $request;
}
/**
* {@inheritdoc}
*
* @codeCoverageIgnore
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('logger.factory')
->get('image'), $container
->get('focal_point.manager'), $container
->get('entity_type.manager')
->getStorage('crop'), $container
->get('config.factory')
->get('focal_point.settings'), $container
->get('request_stack')
->getCurrentRequest());
}
/**
* {@inheritdoc}
*/
public function applyEffect(ImageInterface $image) {
// @todo: Get the original image in case there are multiple scale/crop effects?
$this
->setOriginalImageSize($image
->getWidth(), $image
->getHeight());
return TRUE;
}
/**
* Calculate the resize dimensions of an image.
*
* The calculated dimensions are based on the longest crop dimension (length
* or width) so that the aspect ratio is preserved in all cases and that there
* is always enough image available to the crop.
*
* @param int $image_width
* Image width.
* @param int $image_height
* Image height.
* @param int $crop_width
* Crop width.
* @param int $crop_height
* Crop height.
*
* @return array
* Resize data.
*/
public static function calculateResizeData($image_width, $image_height, $crop_width, $crop_height) {
$resize_data = [];
if ($crop_width > $crop_height) {
$resize_data['width'] = (int) $crop_width;
$resize_data['height'] = (int) ceil($crop_width * $image_height / $image_width);
// Ensure there is enough area to crop.
if ($resize_data['height'] < $crop_height) {
$resize_data['width'] = (int) ceil($crop_height * $resize_data['width'] / $resize_data['height']);
$resize_data['height'] = (int) $crop_height;
}
}
else {
$resize_data['width'] = (int) ceil($crop_height * $image_width / $image_height);
$resize_data['height'] = (int) $crop_height;
// Ensure there is enough area to crop.
if ($resize_data['width'] < $crop_width) {
$resize_data['height'] = (int) ceil($crop_width * $resize_data['height'] / $resize_data['width']);
$resize_data['width'] = (int) $crop_width;
}
}
return $resize_data;
}
/**
* Applies the crop effect to an image.
*
* @param \Drupal\Core\Image\ImageInterface $image
* The image resource to crop.
* @param \Drupal\crop\CropInterface $crop
* A crop object containing the relevant crop information.
*
* @return bool
* TRUE if the image is successfully cropped, otherwise FALSE.
*/
public function applyCrop(ImageInterface $image, CropInterface $crop) {
// Get the top-left anchor position of the crop area.
$anchor = $this
->getAnchor($image, $crop);
if (!$image
->crop($anchor['x'], $anchor['y'], $this->configuration['width'], $this->configuration['height'])) {
$this->logger
->error('Focal point scale and crop failed while scaling and cropping using the %toolkit toolkit on %path (%mimetype, %dimensions, anchor: %anchor)', [
'%toolkit' => $image
->getToolkitId(),
'%path' => $image
->getSource(),
'%mimetype' => $image
->getMimeType(),
'%dimensions' => $image
->getWidth() . 'x' . $image
->getHeight(),
'%anchor' => $anchor,
]);
return FALSE;
}
return TRUE;
}
/**
* Get the cropped image.
*
* @param \Drupal\Core\Image\ImageInterface $image
* The image resource whose crop is being requested.
*
* @return \Drupal\crop\CropInterface
* The crop.
*/
public function getCrop(ImageInterface $image) {
$crop_type = $this->focalPointConfig
->get('crop_type');
/** @var \Drupal\crop\CropInterface $crop */
if ($crop = Crop::findCrop($image
->getSource(), $crop_type)) {
// An existing crop has been found; set the size.
$crop
->setSize($this->configuration['width'], $this->configuration['height']);
}
else {
// No existing crop could be found; create a new one using the size.
$crop = $this->cropStorage
->create([
'type' => $crop_type,
'x' => (int) round($this->originalImageSize['width'] / 2),
'y' => (int) round($this->originalImageSize['height'] / 2),
'width' => $this->configuration['width'],
'height' => $this->configuration['height'],
]);
}
return $crop;
}
/**
* Returns the focal point config.
*
* @return \Drupal\Core\Config\ImmutableConfig
* The focal point config.
*/
public function getFocalPointConfig() {
return $this->focalPointConfig;
}
/**
* Returns the crop storage.
*
* @return \Drupal\crop\CropStorageInterface
* The crop storage.
*/
public function getCropStorage() {
return $this->cropStorage;
}
/**
* Get the top-left anchor position of the crop area.
*
* @param \Drupal\Core\Image\ImageInterface $image
* Image object representing original image.
* @param \Drupal\crop\CropInterface $crop
* Crop entity.
*
* @return array
* Array with two keys (x, y) and anchor coordinates as values.
*
* @codeCoverageIgnore
*/
public function getAnchor(ImageInterface $image, CropInterface $crop) {
$original_focal_point = $this
->getOriginalFocalPoint($crop, $this->focalPointManager);
$focal_point = $this
->transformFocalPoint($image, $original_focal_point);
return $this
->calculateAnchor($focal_point, $image, $crop);
}
/**
* Set original image size.
*
* @param int $width
* The original image width.
* @param int $height
* The original image height.
*/
public function setOriginalImageSize($width, $height) {
$this->originalImageSize = [
'width' => $width,
'height' => $height,
];
}
/**
* Return the original image dimensions.
*
* @return array
* An array with keys 'width' and 'height'.
*/
public function getOriginalImageSize() {
// @todo: check if originalImageSize exists and if not throw an exception.
return $this->originalImageSize;
}
/**
* Calculate the top left coordinates of crop rectangle.
*
* This is based on Crop's anchor function with additional logic to ensure
* that crop area doesn't fall outside of the original image. Note that the
* image modules crop effect expects the top left coordinate of the crop
* rectangle.
*
* @param array $focal_point
* The focal point value.
* @param \Drupal\Core\Image\ImageInterface $image
* The original image to be cropped.
* @param \Drupal\crop\CropInterface $crop
* The crop object used to define the crop.
*
* @return array
* An array with the keys 'x' and 'y'.
*/
protected function calculateAnchor(array $focal_point, ImageInterface $image, CropInterface $crop) {
$crop_size = $crop
->size();
// The anchor must be the top-left coordinate of the crop area but the focal
// point is expressed as the center coordinates of the crop area.
$anchor = [
'x' => (int) ($focal_point['x'] - $crop_size['width'] / 2),
'y' => (int) ($focal_point['y'] - $crop_size['height'] / 2),
];
$anchor = $this
->constrainCropArea($anchor, $image, $crop);
return $anchor;
}
/**
* Calculate the anchor such that the crop will not exceed the image boundary.
*
* Given the top-left anchor (in pixels), the crop size and the image size,
* reposition the anchor to ensure the crop area does not exceed the bounds of
* the image.
*
* @param array $anchor
* An array with the keys 'x' and 'y'. Values are in pixels representing the
* top left corner of the of the crop area relative to the image.
* @param \Drupal\Core\Image\ImageInterface $image
* The image to which the crop area must be constrained.
* @param \Drupal\crop\CropInterface $crop
* The crop object used to define the crop.
*
* @return array
* An array with the keys 'x' and 'y'.
*/
protected function constrainCropArea(array $anchor, ImageInterface $image, CropInterface $crop) {
$image_size = [
'width' => $image
->getWidth(),
'height' => $image
->getHeight(),
];
$crop_size = $crop
->size();
// Ensure that the crop area doesn't fall off the bottom right of the image.
$anchor = [
'x' => $anchor['x'] + $crop_size['width'] <= $image_size['width'] ? $anchor['x'] : $image_size['width'] - $crop_size['width'],
'y' => $anchor['y'] = $anchor['y'] + $crop_size['height'] <= $image_size['height'] ? $anchor['y'] : $image_size['height'] - $crop_size['height'],
];
// Ensure that the crop area doesn't fall off the top left of the image.
$anchor = [
'x' => max(0, $anchor['x']),
'y' => max(0, $anchor['y']),
];
return $anchor;
}
/**
* Returns the focal point value (in pixels) relative to the original image.
*
* @param \Drupal\crop\CropInterface $crop
* The crop object used to define the crop.
* @param \Drupal\focal_point\FocalPointManager $focal_point_manager
* The focal point manager.
*
* @return array
* An array with the keys 'x' and 'y'. Values are in pixels.
*/
protected function getOriginalFocalPoint(CropInterface $crop, FocalPointManager $focal_point_manager) {
$focal_point = $crop
->position();
// Check if we are generating a preview image. If so get the focal point
// from the query parameter, otherwise use the crop position.
$preview_value = $this
->getPreviewValue();
if (!is_null($preview_value)) {
// @todo: should we check that preview_value is valid here? If it's invalid it gets converted to 0,0.
$original_image_size = $this
->getOriginalImageSize();
list($x, $y) = explode('x', $preview_value);
$focal_point = $focal_point_manager
->relativeToAbsolute($x, $y, $original_image_size['width'], $original_image_size['height']);
}
return $focal_point;
}
/**
* Returns the focal point value (in pixels) relative to the provided image.
*
* @param \Drupal\Core\Image\ImageInterface $image
* Image object that the focal point must be applied to.
* @param array $original_focal_point
* An array with keys 'x' and 'y' which represent the focal point in pixels
* relative to the original image.
*
* @return array
* An array with the keys 'x' and 'y'. Values are in pixels.
*/
protected function transformFocalPoint(ImageInterface $image, array $original_focal_point) {
$image_size = [
'width' => $image
->getWidth(),
'height' => $image
->getHeight(),
];
$original_image_size = $this
->getOriginalImageSize();
$relative_focal_point = [
'x' => (int) round($original_focal_point['x'] / $original_image_size['width'] * $image_size['width']),
'y' => (int) round($original_focal_point['y'] / $original_image_size['height'] * $image_size['height']),
];
return $relative_focal_point;
}
/**
* Get the 'focal_point_preview_value' query string value.
*
* @return string|null
* Safely return the value of the focal_point_preview_value query string if
* it exists.
*
* @codeCoverageIgnore
*/
protected function getPreviewValue() {
return $this->request->query
->get('focal_point_preview_value');
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
ConfigurableImageEffectBase:: |
public | function |
Form validation handler. Overrides PluginFormInterface:: |
2 |
DependencySerializationTrait:: |
protected | property | An array of entity type IDs keyed by the property name of their storages. | |
DependencySerializationTrait:: |
protected | property | An array of service IDs keyed by property name used for serialization. | |
DependencySerializationTrait:: |
public | function | 1 | |
DependencySerializationTrait:: |
public | function | 2 | |
FocalPointEffectBase:: |
protected | property | Crop storage. | |
FocalPointEffectBase:: |
protected | property | Focal point configuration object. | |
FocalPointEffectBase:: |
protected | property | Focal point manager object. | |
FocalPointEffectBase:: |
protected | property | The original image dimensions before any effects are applied. | |
FocalPointEffectBase:: |
public | property | The current request object. | |
FocalPointEffectBase:: |
public | function | Applies the crop effect to an image. | |
FocalPointEffectBase:: |
public | function |
Applies an image effect to the image object. Overrides ResizeImageEffect:: |
2 |
FocalPointEffectBase:: |
protected | function | Calculate the top left coordinates of crop rectangle. | |
FocalPointEffectBase:: |
public static | function | Calculate the resize dimensions of an image. | |
FocalPointEffectBase:: |
protected | function | Calculate the anchor such that the crop will not exceed the image boundary. | |
FocalPointEffectBase:: |
public static | function |
@codeCoverageIgnore Overrides ImageEffectBase:: |
|
FocalPointEffectBase:: |
public | function | Get the top-left anchor position of the crop area. | |
FocalPointEffectBase:: |
public | function | Get the cropped image. | |
FocalPointEffectBase:: |
public | function | Returns the crop storage. | |
FocalPointEffectBase:: |
public | function | Returns the focal point config. | |
FocalPointEffectBase:: |
protected | function | Returns the focal point value (in pixels) relative to the original image. | |
FocalPointEffectBase:: |
public | function | Return the original image dimensions. | |
FocalPointEffectBase:: |
protected | function | Get the 'focal_point_preview_value' query string value. | 1 |
FocalPointEffectBase:: |
public | function | Set original image size. | |
FocalPointEffectBase:: |
protected | function | Returns the focal point value (in pixels) relative to the provided image. | |
FocalPointEffectBase:: |
public | function |
Constructs a \Drupal\focal_point\FocalPointEffectBase object. Overrides ImageEffectBase:: |
|
ImageEffectBase:: |
protected | property | A logger instance. | |
ImageEffectBase:: |
protected | property | The image effect ID. | |
ImageEffectBase:: |
protected | property | The weight of the image effect. | |
ImageEffectBase:: |
public | function |
Calculates dependencies for the configured plugin. Overrides DependentPluginInterface:: |
|
ImageEffectBase:: |
public | function |
Gets this plugin's configuration. Overrides ConfigurableInterface:: |
|
ImageEffectBase:: |
public | function |
Returns the extension of the derivative after applying this image effect. Overrides ImageEffectInterface:: |
1 |
ImageEffectBase:: |
public | function |
Returns the unique ID representing the image effect. Overrides ImageEffectInterface:: |
|
ImageEffectBase:: |
public | function |
Returns the weight of the image effect. Overrides ImageEffectInterface:: |
|
ImageEffectBase:: |
public | function |
Returns the image effect label. Overrides ImageEffectInterface:: |
|
ImageEffectBase:: |
public | function |
Sets the configuration for this plugin instance. Overrides ConfigurableInterface:: |
|
ImageEffectBase:: |
public | function |
Sets the weight for this image effect. Overrides ImageEffectInterface:: |
|
MessengerTrait:: |
protected | property | The messenger. | 29 |
MessengerTrait:: |
public | function | Gets the messenger. | 29 |
MessengerTrait:: |
public | function | Sets the messenger. | |
PluginBase:: |
protected | property | Configuration information passed into the plugin. | 1 |
PluginBase:: |
protected | property | The plugin implementation definition. | 1 |
PluginBase:: |
protected | property | The plugin_id. | |
PluginBase:: |
constant | A string which is used to separate base plugin IDs from the derivative ID. | ||
PluginBase:: |
public | function |
Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the definition of the plugin implementation. Overrides PluginInspectionInterface:: |
3 |
PluginBase:: |
public | function |
Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface:: |
|
PluginBase:: |
public | function | Determines if the plugin is configurable. | |
ResizeImageEffect:: |
public | function |
Form constructor. Overrides PluginFormInterface:: |
2 |
ResizeImageEffect:: |
public | function |
Gets default configuration for this plugin. Overrides ImageEffectBase:: |
2 |
ResizeImageEffect:: |
public | function |
Returns a render array summarizing the configuration of the image effect. Overrides ImageEffectBase:: |
2 |
ResizeImageEffect:: |
public | function |
Form submission handler. Overrides ConfigurableImageEffectBase:: |
2 |
ResizeImageEffect:: |
public | function |
Determines the dimensions of the styled image. Overrides ImageEffectBase:: |
1 |
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. |