class ImagickToolkit in Imagick 8
Defines the Imagick toolkit for image manipulation within Drupal.
Plugin annotation
@ImageToolkit(
id = "imagick",
title = @Translation("Imagick image manipulation toolkit")
)
Hierarchy
- class \Drupal\Component\Plugin\PluginBase implements DerivativeInspectionInterface, PluginInspectionInterface
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
- class \Drupal\Core\ImageToolkit\ImageToolkitBase implements ImageToolkitInterface
- class \Drupal\imagick\Plugin\ImageToolkit\ImagickToolkit
- class \Drupal\Core\ImageToolkit\ImageToolkitBase implements ImageToolkitInterface
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
Expanded class hierarchy of ImagickToolkit
2 files declare their use of ImagickToolkit
- ConvertImageEffect.php in src/
Plugin/ ImageEffect/ ConvertImageEffect.php - Resize.php in src/
Plugin/ ImageToolkit/ Operation/ imagick/ Resize.php
File
- src/
Plugin/ ImageToolkit/ ImagickToolkit.php, line 29
Namespace
Drupal\imagick\Plugin\ImageToolkitView source
class ImagickToolkit extends ImageToolkitBase {
const TEMP_DIR = 'temporary://';
const TEMP_PREFIX = 'imagick_';
const CONFIG = 'imagick.config';
const CONFIG_JPEG_QUALITY = 'jpeg_quality';
const CONFIG_OPTIMIZE = 'optimize';
const CONFIG_RESIZE_FILTER = 'resize_filter';
const CONFIG_STRIP_METADATA = 'strip_metadata';
/**
* @var resource|null
*/
protected $resource = NULL;
/**
* @var \Drupal\Core\File\FileSystem
*/
private $fileSystem;
/**
* @var \Drupal\Core\StreamWrapper\StreamWrapperManager
*/
private $streamWrapperManager;
/**
* Destructs a Imagick object.
*/
public function __destruct() {
if (is_object($this
->getResource())) {
$this
->getResource()
->clear();
}
}
/**
* ImagickToolkit constructor.
*
* @param array $configuration
* @param $plugin_id
* @param array $plugin_definition
* @param \Drupal\Core\ImageToolkit\ImageToolkitOperationManagerInterface $operation_manager
* @param \Drupal\imagick\Plugin\ImageToolkit\LoggerInterface $logger
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* @param \Drupal\Core\File\FileSystem $fileSystem
* @param \Drupal\Core\StreamWrapper\StreamWrapperManager $streamWrapperManager
*/
public function __construct(array $configuration, $plugin_id, array $plugin_definition, ImageToolkitOperationManagerInterface $operation_manager, LoggerInterface $logger, ConfigFactoryInterface $config_factory, FileSystem $fileSystem, StreamWrapperManager $streamWrapperManager) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $operation_manager, $logger, $config_factory);
$this->fileSystem = $fileSystem;
$this->streamWrapperManager = $streamWrapperManager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('image.toolkit.operation.manager'), $container
->get('logger.channel.image'), $container
->get('config.factory'), $container
->get('file_system'), $container
->get('stream_wrapper_manager'));
}
/**
* Sets the Imagick image resource.
*
* @param Imagick $resource
* The Imagick image resource.
*
* @return $this
*/
public function setResource($resource) {
$this->resource = $resource;
return $this;
}
/** Retrieves the Imagick image resource.
*
* @return Imagick|resource|null
* The Imagick image resource, or NULL if not available.
*/
public function getResource() {
return $this->resource;
}
/**
* {@inheritdoc}
*/
public function isValid() {
return (bool) $this
->getPath();
}
/**
* {@inheritdoc}
*/
public function save($destination) {
$resource = $this
->getResource();
if (is_null($resource)) {
return FALSE;
}
if ($this
->isValidUri($destination)) {
// If destination is not local, save image to temporary local file.
if ($this
->isRemoteUri($destination)) {
$permanent_destination = $destination;
$destination = $this->fileSystem
->tempnam(self::TEMP_DIR, self::TEMP_PREFIX);
}
// Convert stream wrapper URI to normal path.
$destination = $this->fileSystem
->realpath($destination);
}
// If preferred format is set, use it as prefix for writeImage
// If not this will throw a ImagickException exception
try {
$image_format = $resource
->getImageFormat();
$destination = implode(':', [
$image_format,
$destination,
]);
} catch (ImagickException $e) {
}
// Only compress JPEG files because other filetypes will increase in filesize
if (isset($image_format) && in_array($image_format, [
'JPEG',
'JPG',
'JPE',
])) {
// Get image quality from effect or global setting
$quality = $resource
->getImageProperty('quality') ?: $this->configFactory
->get(self::CONFIG)
->get(self::CONFIG_JPEG_QUALITY);
// Set image compression quality
$resource
->setImageCompressionQuality($quality);
// Optimize images
if ($this->configFactory
->get(self::CONFIG)
->get(self::CONFIG_OPTIMIZE)) {
// Using recommendations from Google's Page Speed docs: https://developers.google.com/speed/docs/insights/OptimizeImages
$resource
->setSamplingFactors([
'2x2',
'1x1',
'1x1',
]);
$resource
->setColorspace(Imagick::COLORSPACE_RGB);
$resource
->setInterlaceScheme(Imagick::INTERLACE_JPEG);
}
}
// Strip metadata
if ($this->configFactory
->get(self::CONFIG)
->get(self::CONFIG_STRIP_METADATA)) {
$resource
->stripImage();
}
// Write image to destination
if (isset($image_format) && in_array($image_format, [
'GIF',
])) {
if (!$resource
->writeImages($destination, TRUE)) {
return FALSE;
}
}
else {
if (!$resource
->writeImage($destination)) {
return FALSE;
}
}
// Move temporary local file to remote destination.
if (isset($permanent_destination)) {
return (bool) $this->fileSystem
->move($destination, $permanent_destination, FileSystemInterface::EXISTS_REPLACE);
}
return TRUE;
}
/**
* {@inheritdoc}
*/
public function getWidth() {
if (!$this
->getResource()) {
return NULL;
}
return $this
->getResource()
->getImageGeometry()['width'];
}
/**
* {@inheritdoc}
*/
public function getHeight() {
if (!$this
->getResource()) {
return NULL;
}
return $this
->getResource()
->getImageGeometry()['height'];
}
/**
* {@inheritdoc}
*/
public function getMimeType() {
if (!$this
->getResource()) {
return NULL;
}
return $this
->getResource()
->getImageMimeType();
}
/**
* ensure that we have a local filepath since Imagick does not support remote stream wrappers
*
* @return string
*/
protected function getPath() {
$source = $this
->getSource();
return $this
->isRemoteUri($source) ? $this
->copyRemoteFileToLocalTemp($source) : $this->fileSystem
->realpath($source);
}
/**
* {@inheritdoc}
*/
public function parseFile() {
$success = FALSE;
try {
$resource = new Imagick();
$resource
->setBackgroundColor(new ImagickPixel('transparent'));
$resource
->readImage($this
->getPath());
$this
->setResource($resource);
$success = TRUE;
} catch (ImagickException $e) {
}
// cleanup local file if the original was remote
if ($this
->isRemoteUri($this
->getPath())) {
$this->fileSystem
->delete($this
->getPath());
}
return $success;
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form['jpeg'] = [
'#type' => 'fieldset',
'#title' => $this
->t('JPEG specific settings'),
'#description' => $this
->t('<strong>Tip: </strong>Generated images can be converted to the JPEG format using the Convert effect.'),
];
$form['jpeg'][self::CONFIG_JPEG_QUALITY] = [
'#type' => 'number',
'#title' => $this
->t('Quality'),
'#description' => $this
->t('Higher values mean better image quality but bigger files. Quality level below 80% is not advisable when using ImageMagick.'),
'#min' => 0,
'#max' => 100,
'#default_value' => $this->configFactory
->get(self::CONFIG)
->get(self::CONFIG_JPEG_QUALITY),
'#field_suffix' => $this
->t('%'),
];
$form['jpeg'][self::CONFIG_OPTIMIZE] = [
'#type' => 'checkbox',
'#title' => t('Use Google Pagespeed Insights image optimization.'),
'#description' => t('See the <a href=":url" target="_blank">guidelines</a> for further information.', [
':url' => 'https://developers.google.com/speed/docs/insights/OptimizeImages',
]),
'#default_value' => $this->configFactory
->get(self::CONFIG)
->get(self::CONFIG_OPTIMIZE),
];
$form[self::CONFIG_RESIZE_FILTER] = [
'#type' => 'select',
'#title' => t('Imagic resize filter'),
'#description' => t('Define the resize filter for image manipulations. If you\'re not sure what you should enter here, leave the default settings.'),
'#options' => [
-1 => t('- None -'),
imagick::FILTER_UNDEFINED => 'FILTER_UNDEFINED',
imagick::FILTER_POINT => 'FILTER_POINT',
imagick::FILTER_BOX => 'FILTER_BOX',
imagick::FILTER_TRIANGLE => 'FILTER_TRIANGLE',
imagick::FILTER_HERMITE => 'FILTER_HERMITE',
imagick::FILTER_HANNING => 'FILTER_HANNING',
imagick::FILTER_HAMMING => 'FILTER_HAMMING',
imagick::FILTER_BLACKMAN => 'FILTER_BLACKMAN',
imagick::FILTER_GAUSSIAN => 'FILTER_GAUSSIAN',
imagick::FILTER_QUADRATIC => 'FILTER_QUADRATIC',
imagick::FILTER_CUBIC => 'FILTER_CUBIC',
imagick::FILTER_CATROM => 'FILTER_CATROM',
imagick::FILTER_MITCHELL => 'FILTER_MITCHELL',
imagick::FILTER_LANCZOS => 'FILTER_LANCZOS',
imagick::FILTER_BESSEL => 'FILTER_BESSEL',
imagick::FILTER_SINC => 'FILTER_SINC',
],
'#default_value' => $this->configFactory
->get(self::CONFIG)
->get(self::CONFIG_RESIZE_FILTER),
];
$form[self::CONFIG_STRIP_METADATA] = [
'#type' => 'checkbox',
'#title' => t('Strip images of all metadata.'),
'#description' => t('Eg. profiles, comments, ...'),
'#default_value' => $this->configFactory
->get(self::CONFIG)
->get(self::CONFIG_STRIP_METADATA),
];
return $form;
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
$form_state
->cleanValues();
/** @var ImageStyle $style */
foreach (ImageStyle::loadMultiple() as $style) {
$style
->flush();
}
$this->configFactory
->getEditable(self::CONFIG)
->set(self::CONFIG_JPEG_QUALITY, $form_state
->getValue([
'imagick',
'jpeg',
self::CONFIG_JPEG_QUALITY,
]))
->set(self::CONFIG_OPTIMIZE, $form_state
->getValue([
'imagick',
'jpeg',
self::CONFIG_OPTIMIZE,
]))
->set(self::CONFIG_RESIZE_FILTER, $form_state
->getValue([
'imagick',
self::CONFIG_RESIZE_FILTER,
]))
->set(self::CONFIG_STRIP_METADATA, $form_state
->getValue([
'imagick',
self::CONFIG_STRIP_METADATA,
]))
->save();
}
/**
* {@inheritdoc}
*/
public static function isAvailable() {
return extension_loaded('imagick');
}
/**
* @param $uri
*
* @return bool
*/
private function isValidUri($uri) {
$scheme = $this->streamWrapperManager
->getScheme($uri);
return $scheme && $this->streamWrapperManager
->isValidScheme($scheme);
}
/**
* Returns TRUE if the $uri points to a remote location, FALSE otherwise.
*
* @param $uri
* @return bool
*/
private function isRemoteUri($uri) {
if (!$this
->isValidUri($uri)) {
return FALSE;
}
$local_wrappers = $this->streamWrapperManager
->getWrappers(StreamWrapperInterface::LOCAL);
return !in_array($this->streamWrapperManager
->getScheme($uri), array_keys($local_wrappers));
}
/**
* Given a remote source it will copy its contents to a local temporary file.
*
* @param $source
* @return bool
*/
private function copyRemoteFileToLocalTemp($source) {
if (!($tmp_file = $this->fileSystem
->copy($source, $this->fileSystem
->tempnam(self::TEMP_DIR, self::TEMP_PREFIX), FileSystemInterface::EXISTS_REPLACE))) {
return FALSE;
}
return $this->fileSystem
->realpath($tmp_file);
}
/**
* {@inheritdoc}
*/
public static function getSupportedExtensions() {
return ImagickConst::getSupportedExtensions();
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
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 | |
ImageToolkitBase:: |
protected | property | The config factory. | |
ImageToolkitBase:: |
protected | property | A logger instance. | |
ImageToolkitBase:: |
protected | property | The image toolkit operation manager. | |
ImageToolkitBase:: |
protected | property | Path of the image file. | |
ImageToolkitBase:: |
public | function |
Applies a toolkit operation to an image. Overrides ImageToolkitInterface:: |
1 |
ImageToolkitBase:: |
public | function |
Gets toolkit requirements in a format suitable for hook_requirements(). Overrides ImageToolkitInterface:: |
1 |
ImageToolkitBase:: |
public | function |
Gets the source path of the image file. Overrides ImageToolkitInterface:: |
|
ImageToolkitBase:: |
protected | function | Gets a toolkit operation plugin instance. | |
ImageToolkitBase:: |
public | function |
Sets the source path of the image file. Overrides ImageToolkitInterface:: |
|
ImageToolkitBase:: |
public | function |
Form validation handler. Overrides PluginFormInterface:: |
1 |
ImagickToolkit:: |
private | property | ||
ImagickToolkit:: |
protected | property | ||
ImagickToolkit:: |
private | property | ||
ImagickToolkit:: |
public | function |
Form constructor. Overrides PluginFormInterface:: |
|
ImagickToolkit:: |
constant | |||
ImagickToolkit:: |
constant | |||
ImagickToolkit:: |
constant | |||
ImagickToolkit:: |
constant | |||
ImagickToolkit:: |
constant | |||
ImagickToolkit:: |
private | function | Given a remote source it will copy its contents to a local temporary file. | |
ImagickToolkit:: |
public static | function |
Creates an instance of the plugin. Overrides ContainerFactoryPluginInterface:: |
|
ImagickToolkit:: |
public | function |
Returns the height of the image. Overrides ImageToolkitInterface:: |
|
ImagickToolkit:: |
public | function |
Returns the MIME type of the image file. Overrides ImageToolkitInterface:: |
|
ImagickToolkit:: |
protected | function | ensure that we have a local filepath since Imagick does not support remote stream wrappers | |
ImagickToolkit:: |
public | function | Retrieves the Imagick image resource. | |
ImagickToolkit:: |
public static | function |
Returns a list of image file extensions supported by the toolkit. Overrides ImageToolkitInterface:: |
|
ImagickToolkit:: |
public | function |
Returns the width of the image. Overrides ImageToolkitInterface:: |
|
ImagickToolkit:: |
public static | function |
Verifies that the Image Toolkit is set up correctly. Overrides ImageToolkitInterface:: |
|
ImagickToolkit:: |
private | function | Returns TRUE if the $uri points to a remote location, FALSE otherwise. | |
ImagickToolkit:: |
public | function |
Checks if the image is valid. Overrides ImageToolkitInterface:: |
|
ImagickToolkit:: |
private | function | ||
ImagickToolkit:: |
public | function |
Determines if a file contains a valid image. Overrides ImageToolkitInterface:: |
|
ImagickToolkit:: |
public | function |
Writes an image resource to a destination file. Overrides ImageToolkitInterface:: |
|
ImagickToolkit:: |
public | function | Sets the Imagick image resource. | |
ImagickToolkit:: |
public | function |
Form submission handler. Overrides PluginFormInterface:: |
|
ImagickToolkit:: |
constant | |||
ImagickToolkit:: |
constant | |||
ImagickToolkit:: |
public | function |
ImagickToolkit constructor. Overrides ImageToolkitBase:: |
|
ImagickToolkit:: |
public | function | Destructs a Imagick object. | |
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. | |
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. |