Navigation

Related Articles

Back to Latest Articles

Générer des thumbs lors de l’affichage d’une image


thomas
Générer des thumbs lors de l’affichage...

Nous allons voir ici comment générer facilement des thumbs lors de l’affichage d’une image sur le site, plutôt que lors de l’upload de cette image.
L’intérêt: une fois que le site est lancé, qu’il y a des images déjà uploadées, il est beaucoup plus facile de changer dans le code la taille d’affichage et de regénérer automatiquement les images, plutôt que de devoir tout réuploader une seconde fois, voir +.

Afin d’optimiser l’affichage des pages, il est recommandé de généré plusieurs thumb (vignettes) pour une même image. Il y a l’image d’origine, puis une version en 200×200, une en 150×100 et une 50×50, suivant leur position sur le site.
Une première solution est de générer ces thumbs lors de l’upload, c’est très efficace, le travail ce fait une fois lors de la sauvegarde et est opérationnel directement. Mais on a tous eu un projet où finalement il faut créer un nouveau thumb ou changer le 150×100 en 100×100 et là c’est le drame: il faut re-uploader toutes les images une par une (enfin si le site est déjà en prod, le mieux c’est de s’en rendre compte du problème avant).

Bref, la deuxième solution est d’uploader une image source, et lors de l’affichage demander la taille souhaitée. Là on vérifie si le thumb existe, si oui on l’affiche, sinon , on le crée et on l’affiche.
Voila ce que je vous propose aujourd’hui, un petit helper tout fait qui s’occupe de cette deuxième solution.
Il est basé sur le plugin sfImageTransformPlugin qui est excellent et dont vous avez toute la doc ici: http://www.symfony-project.org/plugins/sfImageTransformPlugin.

Pour installer le helper rien de plus simple, vous créez le répertoire lib/helper, et vous placez le fichier dedans.
lors de l’appel il faut penser à le loader avec la fonction suivante dans une action sfProjectConfiguration::getActive()->loadHelpers(‘Thumb’);
ou

<?php use_helper('Thumb');?>

dans la vue.

il y a deux fonctions:

une pour générer le thumb:
doThumb($image_name, $folder, $options = array(), $resize = ‘scale’, $default = ‘default.jpg’)
@param $image_name : le nom de l’image donc généralement le $object->getImage(), pas de répertoire
@param $folder : le nom du répertoire dans uploads où est stocké l’image : uploads/object/source => $folder = object
@param $options : la taille de l’image: width et height
@param $resize : l’opération sur le thumb: « scale » pour garder les proportions, « center » pour tronquer l’image
@param $default : l’image par défaut si image_name n’existe pas
le thumb est créé dans uploads/object/thumb/
le réslutat retourné est le lien vers l’image : /uploads/object/thumb/mon-image.jpg

une autre fonction :
showThumb($image_name, $folder, $options = array(), $resize = ‘scale’, $default = ‘default.jpg’)
elle appelle la précédente avec les même paramètres.
elle retourne l’image tag directement. donc un seul paramètre change:
@param $options : les parametres à passer à l’image: width, height, alt, title, class, id…

Vous pouvez télécharger le helper ici: thumbhelper

Merci de me contacter en cas de soucis.

Show Comments (11)

Comments

  • Sacri

    Bonjour,
    Je trouve l’idée très sympa et son implémentation bonne. Je n’ai pas testé encore le helper mais je le mets de côté, je ne doute pas qu’il me servira 🙂

    ps : le gris clair lors de l’écriture dans le textarea est illisible :p

    • Article Author
  • guil182

    Bonjour,
    Merci pour les très bons articles…par contre j’ai quelques petits soucis.
    J’ai mis ThumbHelper.php sous lib/helper

    J’ai inclus dans apps\backend\templates\layout.php

    Et j’ai mis dans lib\form\doctrine\BackendClubForm.class.php ce code :

    $this->widgetSchema[‘logoclub’] = new sfWidgetFormInputFileEditable(array(
    ‘label’ => ‘Logo’,
    //’file_src’ => ‘/uploads/club/’.$this->getObject()->getlogoclub(),
    ‘file_src’ => ‘/’.basename(sfConfig::get(‘sf_upload_dir’)).’/img/’.$this->getObject()->getlogoclub(),
    ‘is_image’ => true,
    //’edit_mode’ => !$this->isNew(),
    ‘edit_mode’ => doThumb($this->getObject()->getlogoclub(), ‘uploads’, array(‘width’=>’32’,’height’=>’32’), ‘center’, ‘default.jpg’),
    ‘template’ => ‘%file%%input%%delete% %delete_label%’,
    ));

    et à l’exécution, j’ai la belle erreur : Fatal error: Call to undefined function doThumb() in D:\wamp\www\ChampionsL\lib\form\doctrine\BackendClubForm.class.php on line 32

    merci de votre aide.

    • Article Author
  • thomas

    @guil182,

    bonjour,

    nous nous servons de cet helper pour la génération du thumb lors de l’affichage et non lors de l’upload d’une image.
    nous laissons donc le formulaire standard:

    $this->widgetSchema[‘image’] = new sfWidgetFormInputFileEditable(array(
    ‘file_src’ => ‘/uploads/gallery/source/’.$this->getObject()->getImage(),
    ‘is_image’ => true,
    ‘edit_mode’ => !$this->isNew(),
    ‘delete_label’ => ‘Supprimer’,
    ‘template’ => ‘%file%%input%%delete% %delete_label%’
    ));

    $this->validatorSchema[‘image’] = new sfValidatorFile(array(
    ‘required’ => false,
    ‘path’ => sfConfig::get(‘sf_upload_dir’).’/gallery/source/’,
    ‘max_size’ => 2048000),
    array(‘max_size’ => ‘File too large (2MB max).’));

    $this->validatorSchema[‘image_delete’] = new sfValidatorPass();

    les images sont uploadées dans uploads/gallery/source/, les thumbs seront générés dans uploads/gallery/thumb dans cet exemple.

    Dans la vue, aprés avor chargé mon helper, j’appel:
    showThumb($gallery->getImage(), ‘gallery’, array(‘width’=>100, ‘height’=>100), ‘scale’, ‘default.gif’);

    Par contre on peut utiliser le plugin sfImageTransform pour redimensionner lors de l’upload en surchargeant la méthode save de notre formulaire:
    public function save($con = null)
    {
    $gallery = parent::save($con);

    if($file = $this->getValue(‘image’))
    {
    $img = new sfImage($file->getSavedName());
    $img->thumbnail(600, 600, ‘scale’)
    ->saveAs(sfConfig::get(‘sf_upload_dir’).’/gallery/source/’.$pdv->getImage());
    unset($img);
    }

    return $gallery;
    }

    • Article Author
  • Kévin

    Bonjour Thomas,
    Je viens d’essayer ton script sur un site avec Symfony 1.4 et Doctrine.
    J’ai un partial contenu dans une vue où je fais appel à ton helper :

    echo showThumb(
    $p->filename,
    ‘gallerie’,
    array(
    ‘id’ => ‘img’.$i,
    ‘height’ => null,
    ‘width’ => 600,
    ‘alt’ => $p->filename,
    ‘title’ => $p->filename,
    ‘border’ => 0
    ),
    ‘scale’,
    ‘defaut.jpg’);
    endforeach; ?>

    et j’obtiens l’erreur suivante que je ne comprends pas: You must either specify the MIME type for file or enable mime detection. (une exception du sfImageTransform).

    Est-ce que tu vois d’où cela peut bien venir ?
    Merci.

    • Article Author
  • Thomas

    @Kévin
    Bonjour Kévin,

    oui ce problème vient lors de la configuration du plugin sfImageTransformPlugin.
    il faut que dans ton app.yml tu rajoutes les lignes suivantes:
    sfImageTransformPlugin:
    default_adapter: GD
    default_image:
    mime_type: image/png
    filename: Untitled.png
    mime_type:
    auto_detect: true
    library: gd_mime_type

    c’est expliqué là: http://www.symfony-project.org/plugins/sfImageTransformPlugin
    vers le bas de la page dans la configuration du yml.

    • Article Author
  • rahma

    bonjour
    j\’ai utlise votre script et merci de la clarte du tuto.
    voici mon script: ma classForm
    $this->widgetSchema[\’photo\’] = new sfWidgetFormInputFile(array(
    \’label\’ => \’Photo\’,
    ));

    $this->validatorSchema[\’photo\’] = new sfValidatorFile(array(
    \’required\’ => false,
    \’path\’ => sfConfig::get(\’sf_upload_dir\’).\’/photosmembres\’,
    \’mime_types\’ => \’web_images\’,
    ),
    array(\’invalid\’ => \"Ce format d\\\’image est invalide.\" )
    );//sfConfig::get(\’sf_upload_dir\’).
    $this->widgetSchema[\’photo\’] = new sfWidgetFormInputFileEditable(array (
    \’label\’ => \’Photo\’ ,
    \’file_src\’ => \’/uploads/photosmembres/\’.$this->getObject()->getphoto(),
    \’is_image\’ => true,
    \’delete_label\’ => \’supprimer\’,
    \’edit_mode\’ => !$this->isNew() ,
    \’template\’ => \'<div>%input%<br />%delete%%delete_label%%file%<br /></div>\’,
    )) ;

    ma methode Save surcharger.

    public function save(Doctrine_Connection $con = null)
    {
    //$gallery = parent::save($con);

    if($file = $this->getPhoto())
    {
    $img = new sfImage($file->getSavedName());
    $img->thumbnail(50, 50, \’scale\’)
    ->saveAs(sfConfig::get(\’sf_upload_dir\’).\’/photosmembres/\’.$membre->getPhoto());
    unset($img);
    }

    return parent::save($con);
    }

    quand j\’essaye d\’enregistrer j\’obtiens l\’erreur suivante:

    Fatal error: Call to a member function getSavedName() on a non-object in C:\\dossierprojet\\appli\\lib\\model\\doctrine\\Membres.class.php on line 28

    • Article Author
  • rahma

    bonjour
    j’ai utlise votre script et merci de la clarte du tuto.
    voici mon script: ma classForm
    $this->widgetSchema[‘photo’] = new sfWidgetFormInputFile(array(
    ‘label’ => ‘Photo’,
    ));

    $this->validatorSchema[‘photo’] = new sfValidatorFile(array(
    ‘required’ => false,
    ‘path’ => sfConfig::get(‘sf_upload_dir’).’/photosmembres’,
    ‘mime_types’ => ‘web_images’,
    ),
    array(‘invalid’ => « Ce format d\’image est invalide. » )
    );//sfConfig::get(‘sf_upload_dir’).
    $this->widgetSchema[‘photo’] = new sfWidgetFormInputFileEditable(array (
    ‘label’ => ‘Photo’ ,
    ‘file_src’ => ‘/uploads/photosmembres/’.$this->getObject()->getphoto(),
    ‘is_image’ => true,
    ‘delete_label’ => ‘supprimer’,
    ‘edit_mode’ => !$this->isNew() ,
    ‘template’ => ‘%input%%delete%%delete_label%%file%’,
    )) ;

    ma methode Save surcharger.

    public function save(Doctrine_Connection $con = null)
    {
    //$gallery = parent::save($con);

    if($file = $this->getPhoto())
    {
    $img = new sfImage($file->getSavedName());
    $img->thumbnail(50, 50, ‘scale’)
    ->saveAs(sfConfig::get(‘sf_upload_dir’).’/photosmembres/’.$membre->getPhoto());
    unset($img);
    }

    return parent::save($con);
    }

    quand j’essaye d’enregistrer j’obtiens l’erreur suivante:

    Fatal error: Call to a member function getSavedName() on a non-object in C:\dossierprojet\appli\lib\model\doctrine\Membres.class.php on line 28

    • Article Author
  • SAULNIER

    Merci beaucoup pour ce code très bien écrit et qui m’a permis de faire exactement ce que je voulais (miniatures quand la liste de tous les articles est affichée, et image plus grande mais tout de même redimensionnée quand on affiche l’article.

    Encore merci pour ce très bon code.

    • Article Author
  • SAULNIER

    Merci beaucoup pour ce code très bien écrit et qui m\’a permis de faire exactement ce que je voulais (miniatures quand la liste de tous les articles est affichée, et image plus grande mais tout de même redimensionnée quand on affiche l\’article.

    Encore merci pour ce très bon code.

    • Article Author
  • Nicolas

    Bonjour à tous,

    Merci pour ce tutoriel et merci pour le blog en entier … 😉

    Moi aussi, je rencontre un soucis. En effet, j’ai respecté le processus d’installation du tuto.
    – installation du plugin dans plugins/
    – installation du helper dans lib/helper/
    – création du dossier thumb/ + chmod
    – résolution du problème MIME … etc
    … et paf, erreur :
    Fatal error: Call to undefined function image_path() in /var/www/mon_projet/lib/helper/ThumbHelper.php on line 94

    PS : L’image 100x100_9.jpg est bien créée dans le dossier uploads/images/thumb/ à partir de l’image 9.jpg qui est dans /uploads/images/ et ce n’est pas une image vide ; elle correspond bien à l’image de base redimensionnée …

    Pouvez vous m’aider ? Je vous remercie d’avance ! 🙂
    Nico

    • Article Author
  • Nicolas

    Re … Le problème est finalement résolu …
    image_path() est une fonction de lib/vendor/symfony/lib/helper/AssetHelper.php, il suffit donc de ne pas oublier de l’activer …

    sfProjectConfiguration::getActive()->loadHelpers(‘Thumb’);
    sfProjectConfiguration::getActive()->loadHelpers(‘Asset’);
    doThumb(…);

    Bonne journée ! 🙂
    Nico

    • Article Author

Recevez nos articles