Generate programmatically image styles with Drupal 8

Horses running

Drupal 8 allows you to generate image styles for various effects (reduction, cut-out, black-and-white, saturation, etc.) for each uploaded image. You can very quickly have many images styles, and even more if you use responsive images, allowing to propose different dimensions according to the terminal used to consult your website.

These image styles are generated during a first lookup of a page using these, which can be penalizing in terms of performance or even rendering, when you have many media, with so many image styles as break points, such as on a landing page or a listing page.

The snippet below will allow you to automatically generate all possible image styles when uploading the source image.

use Drupal\image\Entity\ImageStyle;
use Drupal\Core\Entity\EntityInterface;
use Drupal\file\FileInterface;

/**
 * Implements hook_entity_insert().
 * Generate all image styles once an Image is uploaded.
 */
function MYMODULE_entity_insert(EntityInterface $entity) {
  /** @var \Drupal\file\Entity\File $entity */
  if ($entity instanceof FileInterface) {
    $image = \Drupal::service('image.factory')->get($entity->getFileUri());
    /** @var \Drupal\Core\Image\Image $image */
    if ($image->isValid()) {
      $styles = ImageStyle::loadMultiple();
      $image_uri = $entity->getFileUri();
      /** @var \Drupal\image\Entity\ImageStyle $style */
      foreach ($styles as $style) {
        $destination = $style->buildUri($image_uri);
        $style->createDerivative($image_uri, $destination);
      }
    }
  }
}

The result will be a slightly longer time for the editor, when he will save the content, but a consequent gain for the visitors, in terms of performance and speed of loading pages, because then all the possible versions of a source image will have already been generated, avoiding many PHP calls during the first lookup of a page, especially if it contains many images.

To improve the user experience, it is also possible to use the Cron API of Drupal 8 to queue the generation of these image styles when saving a source image, reducing the saving time for editors. But this may be the subject of another post.

 

Commentaires

Soumis par Anonyme (non vérifié) le 25/01/2017 à 14:57 - Permalien

Thanks for that :)
I have a problem with image styles in drupal 8, some images are generated, some not, some after launching the page for 2nd, or 20th time...
After putting your module it is better, because plenty of images are being generated on save, however on pages when I have a lot of images, I still have to load page several times in order to have all of them.
Do you maybe know, how to fix it?

Soumis par fabrice le 25/01/2017 à 15:12 - Permalien

You should check if the image styles, for image that are not rendered, have been well created. Simply copy/paste the url image (from the src attribute of the img tag) in a new tab to see if the image style exists. If yes, then you can look at your serveur configuration (time out, etc), if not debug in the snippet above to see why the image style is not well generated. I can't say anymore, I don't know your context.

Soumis par Joost (non vérifié) le 06/07/2017 à 15:32 - Permalien

Thanks for the great snippet. Is it possible to do this for one image style only?

A great thanks, that is too simple. A other question though. I can't seem to get this to work. When I use your example(for all styles) in a custom module I doesn't do a thing. What can ben the problem. I create and .info.yml file and a .module file and in the .module I use your code. The .info is nothing special. Any suggestions how to debug or what can be wrong?

Soumis par fabrice le 06/07/2017 à 22:14 - Permalien

En réponse à par Joost (non vérifié)

Is your module enabled ? Have you update the function name according to your module name ? Have you got some image style ? Otherwise put some dpm() function or put some xdebug breakpoint at each steps to see where and why the code don't generate the image style.

Hi, thanks for the quick replies! The hook works but it doesn't passes this if statement:
if ($entity instanceof FileInterface) {

Okay, fixed that problem by changing FileInterface in the if statement to \Drupal\file\FileInterface. Now when I upload the file the image is created in all styles but when I save and close the node all files dissapear like nothing happend.

Soumis par Joost (non vérifié) le 06/07/2017 à 22:18 - Permalien

Thanks for your quick reply above, that solution was too simple! But I have a other problem. I can't get this to work. I create a .info.yml file and a .module file where I put your code in. I am able to enable the module but it has no effect, no image styles are created on upload. Any idea what I can do to fix this?

Soumis par Maciej Drewniak (non vérifié) le 08/08/2017 à 22:11 - Permalien

The module worked great until I installed Focal Point with Crop API. There is a solution to make it work with these modules?

Soumis par user (non vérifié) le 14/01/2020 à 01:00 - Permalien

i'm use filefieldpath
I still get problem with media field

use dpm from devel i get $destination path is:
"temporary://styles/responsive_image_384/temporary/my-file.jpg"
"temporary://styles/responsive_image_768/temporary/my-file.jpg"

and image style not stored on sites/default/style folder
how to save image style to this folder

Soumis par John (non vérifié) le 26/02/2022 à 13:35 - Permalien

Super cette article !
Je rencontrais un soucis avec des images (style medium) qui doivent s'afficher dans un corps de mail... Les images de ce style n'étant pas générée comme le style n'est jamais utilisé en front, j'ai une url qui pointe vers rien avec : ImageStyle::load('medium')->buildUrl($file->getFileUri())
Maintenant oui en la créant avant :)
A créer au moment de l'envoi du mail et pas à la création de l'entité, car cela reprend des entités antérieures à l'usage de mail !
Par contre il faudrait que je vérifie qu'elle n'a pas été déjà générée avant de la refaire systématiquement , sinon c'est contre productif en perf !

Ajouter un commentaire