A tricky question regarding image styles.

I need to do a thumbnail with 2 layers:

  1. background: a cropped picture with a blur effect.
  2. foreground: overlay with the same picture and scale effect.

If you have some hints, or you know how to do it programmatically in a custom ImageEffect plugin I would appreciate any help.

This is an example how the image should look like:

enter image description here

  • 1
    Sounds like a custom field formatter to me.
    – Kevin
    Feb 22, 2017 at 16:37
  • @Kevin, I think you meant custom ImageEffect plugin.
    – milkovsky
    Feb 22, 2017 at 17:00
  • I had to implement something in the past and just did it as a field formatter. That way you can use one image, and give it options for the image style. Then when you are building it, process the image twice and then render it with a template. See drupal.org/project/zurb_twentytwenty - even though this uses 1 image style, it should not be hard to adapt to that. I have never written a image style that does this... though I guess you could, technically.
    – Kevin
    Feb 22, 2017 at 18:10
  • A theming solution would be to build two different image style render elements for the same image, see drupal.stackexchange.com/questions/219039/…
    – 4uk4
    Feb 22, 2017 at 19:34

1 Answer 1


I have solved the task currently without a custom image style. Only custom code:

   * Applies an image effects blur, scale and crop.
   * The result is am image with 2 layers:
   *   - background: a cropped picture with a blur effect.
   *   - foreground: overlay with the same image and scale effect.
   * @param int $width
   *   Result image width.
   * @param int $height
   *   Result image height.
   * @param int $radius
   *   Result image blur radius.
  public function blurScaleAndCrop($width, $height, $radius) {
    $image = $this->getImageFactory()->get($this->path);
    if (!$image->isValid()) {
      throw new \InvalidArgumentException("Image {$this->path} is not valid");

    // Create the background image.
    $image->scaleAndCrop($width, $height);
    /** @var \Drupal\system\Plugin\ImageToolkit\GDToolkit $toolkit */
    $toolkit = $image->getToolkit();
    $resource = $toolkit->getResource();
    // Apply blur.
    if ($radius) {
      for ($i = 0; $i < $radius; $i++) {
        imagefilter($resource, IMG_FILTER_GAUSSIAN_BLUR);
    $image->apply('gaussian-blur', ['radius' => $radius]);

    // Create the foreground image.
    $foreground = $this->getImageFactory()->get($this->path);
    if (!$foreground->isValid()) {
      throw new \InvalidArgumentException("Image {$this->path} is not valid");
    $foreground->scale($width, $height);

    // Merge the 2 image layers.
    $dst_im = $image->getToolkit()->getResource();
    $src_im = $foreground->getToolkit()->getResource();
    $f_width = $foreground->getWidth();
    $f_height = $foreground->getHeight();
    $x = ($width - $f_width) / 2;
    $y = ($height - $f_height) / 2;
    imagecopy($dst_im, $src_im, $x, $y, 0, 0, $f_width, $f_height);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.