
The problem I wanted to solve was - to apply image styles (especially with the Image Effects module), on images, but dynamically & on-demand, and not use dozens of pre-configured Image Styles.
Why would anyone want something like this? I can give you a couple of examples:
There are many ways one might want to achieve these:
Me being lazy, I didn’t want to use neither low level nor mid-level implementations. I wanted to use something that an Image Style would use - higher level. I know some devs like to have more control and would pick a lower level approach, but that’s not me (one of the reasons why I use Drupal in 1st place).
The fun part is that “high level”, I mean, using ConfigurableImageEffectBase - means using plugins - now let’s do a quick recap on Plugins and Plugin Managers.
I’m definitely not the best person to explain what Plugins and Plugin Managers in Drupal are - but here’s an excellent explainer and video 🎥 from Joe Shindelar, on Drupalize.me.
Here’s also a full write-up on api.drupal.org & official docs.
“Plugins are small pieces of functionality that are swappable. Plugins that perform similar functionality are of the same plugin type.”
Drupal uses Plugins & Plugin Managers to create little reusable bits of code, think: Blocks, Entities, Search, etc - and yes, Image Effects (that are used in the Image Styles).
Yep, Image Effects are plugins tpp, and they have a Plugin Manager as well, that manages them. Here’s an example of all the classes that implement ConfigurableImageEffectBase.
We can use all of these. But you can’t just make a new instance of the class and work with it - you have to use a Plugin Manager as a proxy for that. Assuming you’re using a dependency injection (in a service, controller or a custom form):
use Drupal\image\ImageEffectManager;
// [...]
/**
* Image effect manager - used to fetch image effects.
*
* @var \Drupal\Core\Image\ImageEffectManager
*/
protected $imageEffectManager;
/**
* The overridden default constructor.
*/
public function __construct(ImageEffectManager $image_effect_manager) {
$this->imageEffectManager = $image_effect_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('plugin.manager.image.effect'),
);
}Once you have your plugin manager (instance of ImageEffectManager), you can request your plugins this way, and apply the effects on a given image:
// Set the options for a given effect.
$extend_image_options = [
'data' => []
];
/** @var \Drupal\image_effects\Plugin\ImageEffect\SetCanvasImageEffect $extend_image */
$extend_image = $this->imageEffectManager->createInstance('image_effects_set_canvas', $extend_image_options);
if (!$extend_image->applyEffect($image)) {
\Drupal::messenger()->addError('Could not apply the effect - something went wrong');
}Now, let’s see this in practice - let’s apply some Image Effects & Textimage effects. Let’s install and enable Image Effects first.
Then, we can use something like this:
$extend_image_options = [
'data' => [
'canvas_size' => 'exact',
'canvas_color' => '#000000',
'exact' => [
'width' => '800',
'height' => '600',
'placement' => 'top-left',
'x_offset' => 0,
'y_offset' => 0,
],
]
];
/** @var \Drupal\image_effects\Plugin\ImageEffect\SetCanvasImageEffect $extend_image */
$extend_image = $this->imageEffectManager->createInstance('image_effects_set_canvas', $extend_image_options);
if (!$extend_image->applyEffect($image)) {
\Drupal::messenger()->addError('Could not apply the effect - something went wrong');
}This will create a rectangle image 800x600 with a given canvas color. All of these are values so we can set these dynamically.
Now let’s play with text overlays - we need to install and enable the Textimage module. The $data variable for these effects are a bit bigger.
// Set these dynamically, via a form-submit or some other method.
$details = [
'font_uri' => $fonts_path . '/OpenSans.woff',
'font_size' => '80',
'color' => '#ff0000',
'x' => '50',
'y' => '100'
];
// Then you can use these below.
$text_overlay_options = [
'data' => [
'font' => [
'name' => 'OpenSans',
'uri' => $details['font_uri'],
'size' => $details['font_size'],
'angle' => 0,
'color' => $details['color'],
'stroke_mode' => FALSE,
'stroke_color' => '#000000FF',
'outline_top' => 0,
'outline_right' => 0,
'outline_bottom' => 0,
'outline_left' => 0,
'shadow_x_offset' => 1,
'shadow_y_offset' => 1,
'shadow_width' => 0,
'shadow_height' => 0,
],
'layout' => [
'padding_top' => 0,
'padding_right' => 20,
'padding_bottom' => 0,
'padding_left' => 0,
'x_offset' => 0,
'y_offset' => 0,
'background_color' => NULL,
'overflow_action' => 'extend',
'extended_color' => NULL,
'x_pos' => $details['x'],
'y_pos' => $details['y'],
],
'text_string' => $string,
]
];
/** @var \Drupal\image_effects\Plugin\ImageEffect\TextOverlayImageEffect $text_overlay */
$text_overlay = $this->imageEffectManager->createInstance('image_effects_text_overlay', $text_overlay_options);
$text_overlay->applyEffect($image);You can surely make more changes and adopt these to your own needs 🙃 these are just some random examples.
Okay this definitely took some time - but I’ve finally finished working on a demo module. If you want to see this in action - just head to - https://github.com/Nikro/blog-drupal-demos
Make sure you have docksal (and hence - docker) installed, and then just clone and run: fin init
You will be able to navigate to: /admin/config/demo/nikro_image_effects/form-demo - to play with the image effects demo.
This is a small demo:
I hope this gives a general idea of how this can be used and for what. One can even use this to craft amazing NFT collections (imagine overlaying various traits) 😉
Note - this was a quick and dirty implementation, if you spot anything that can be improved, please let me know (or, make a fork and a pull-request).

