Redimensionner une image au vol
1 01 2009Comme vous le savez, je développe en ce moment une application Facebook. Dans cette application, je devrai afficher des images un peu partout, issues d’une sorte de base de données. Pour ne pas révéler le contenu de mon application, supposons qu’il s’agisse de pochettes de CDs. Je dispose donc d’un répertoire dans lequel se trouvent des milliers d’images de pochettes, généralement en bonne qualité, assez grandes. Mais un peu comme sur last.fm, je devrais pouvoir afficher une série de pochettes de taille plus petite, disons 64 pixels de large.
Pour redimesionner ces images, j’ai deux possibilités:
- Faire un traitement en batch avec un logiciel conçu pour des conversions en séries.
- Convertir au vol ces images via GD ou ImageMagick
La première solution ne me convient pas, car de nouvelles pochettes seront ajoutées au fil du temps, et je ne veux pas être obligé de refaire une conversion de temps à autres. La seconde est gourmande en ressources, la conversion d’images prend un grand nombre de cycles processeur, et s’il y a ne serait-ce que 50 personnes qui veulent afficher une page contenant 20 de ces images, le serveur risque de planter.
L’idéal est un mélange entre ces deux solutions. Le redimensionnement de l’image par ImageMagick (ou GD) suivi de son stockage dans un autre répertoire. Mon script va donc faire cela. Cependant cela donne lieu à un problème technique. Comment savoir si l’image a déjà été convertie auparavant?
Ma solution à ce problème est tellement logique qu’elle ne saute pas aux yeux : ne lancer le script de redimensionnement que si l’image stockée n’existe pas.
En pseudo-code, cela donnerait ceci:
1 2 3 4 5 | if(is_file($fichier_demandé)) { envoyer_le_fichier(); } else { generer_le_fichier_redimensionne(); } |
Mais cela voudrait dire qu’on lance un script php et fait un accès au disque pour vérifier si le fichier existe ou pas. Il y a mieux à faire…
Au lieu de faire ce script qui vérifie si le fichier existe ou pas, ne lancer ce script qu’a condition que le fichier n’existe pas à l’endroit attendu. Et comment faire en sorte que cela soit automatisé, ou géré par le serveur lui-même?
ErrorDocument 404 404.php
Toutes mes images sont stockées dans le répertoire /i/ de ma racine de site web. Donc j’ai mis cette directive dans /i/.htaccess.
Mon script n’est ainsi appelé que si l’image n’existe pas. Et au lieu d’afficher le sempiternel message d’erreur, je corrige cette erreur en créant le fichier redimensionné. D’autant que vu qu’on appelle une image, afficher un “message d’erreur” ne sert à rien…
Example:
1 | <img src="/i/w=64/pochette/Aphex-Twin/Hangable-Auto-Bulb.jpg" /> |
Code source de 404.php:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | <?php /* Initialisation des variables */ $requestedWidth = 0; // Largeur demandée $requestedHeight= 0; // Hauteur demandée $filename=''; // Nom du fichier original (avec chemin) $requestedFilename = ''; // Nom de fichier redimensionné (avec chemin) $basePath = '/var/foo/mon_site/'; /* Parcours de l'url demandée */ if(ereg("/w=([0-9]+)/", $_SERVER['REQUEST_URI'], $regs)) { $requestedWidth = (int)$regs[1]; } unset($regs); if(ereg('/h=([0-9]+)/', $_SERVER['REQUEST_URI'], $regs)) { $requestedHeight = (int)$regs[1]; } unset($regs); /* Détermine le fichier à lire */ ereg('i/[wh]{1}=[0-9]*/([a-zA-Z0-9/-\.]*)', $_SERVER['REQUEST_URI'], $regs); if(!is_file($basePath.'i/'.$regs[1])) { error_log("The path doesn't lead to a file: ".$basePath.$regs[1]); } if(!is_readable($basePath.'i/'.$regs[1])) { error_log('The file is not readable:'.$basePath.$regs[1]); } $filename = $basePath.'i/'.$regs[1]; unset($regs); /* Détermine le fichier à créer */ ereg('(i/[wh]{1}=[0-9]*/[a-zA-Z0-9/-\.]*)', $_SERVER['REQUEST_URI'], $regs); $requestedFilename = $basePath.$regs[1]; unset($regs); $image = new Imagick(); $image->readImage($filename); $image->resizeImage($requestedWidth, $requestedHeight, imagick::FILTER_LANCZOS, 1); if(!is_dir(dirname($requestedFilename))) { mkdir(dirname($requestedFilename), 0777, true); } $image->writeImage($requestedFilename); header('Content-Type: image/'.$image->getImageFormat()); echo $image; ?> |
N’oubliez pas, si vous utilisez ce script, que sur mon serveur, toutes les images sont dans /var/foo/mon_site/i/. Aussi, vu que ce répertoire ne contient QUE des images, je ne vérifie pas si le visiteur demande une image ou une page web normale… Pensez donc à faire cette vérification si vous utilisez ce script en tant que page 404 sur tout le serveur, au lieu de limiter l’emploi de celle-ci à un répertoire donné via un .htaccess ou une directive
Enfin, une demande vers l’image donnée en exemple créera un répertoire /var/foo/mon_site/i/w=64/pochette/……
Dernière considération: ce script ne peut gérer le redimensionnement que selon la largeur OU la hauteur, et redimensionne en conservant le rapport largeur/hauteur original.
Catégories : Internet, Programmation
![[del.icio.us]](http://www.thanerd.net/wp-content/plugins/bookmarkify/delicious.png)
![[Digg]](http://www.thanerd.net/wp-content/plugins/bookmarkify/digg.png)
![[Facebook]](http://www.thanerd.net/wp-content/plugins/bookmarkify/facebook.png)
![[Furl]](http://www.thanerd.net/wp-content/plugins/bookmarkify/furl.png)
![[Google]](http://www.thanerd.net/wp-content/plugins/bookmarkify/google.png)
![[MySpace]](http://www.thanerd.net/wp-content/plugins/bookmarkify/myspace.png)
![[Shoutwire]](http://www.thanerd.net/wp-content/plugins/bookmarkify/shoutwire.png)
![[StumbleUpon]](http://www.thanerd.net/wp-content/plugins/bookmarkify/stumbleupon.png)
![[Technorati]](http://www.thanerd.net/wp-content/plugins/bookmarkify/technorati.png)
![[Windows Live]](http://www.thanerd.net/wp-content/plugins/bookmarkify/windowslive.png)
![[Email]](http://www.thanerd.net/wp-content/plugins/bookmarkify/email.png)