Bien redimensionner ses photos avec ImageMagick

Avec le constant progrès apporté par les ingénieurs, la hausse de la densité de pixels sur les capteurs numériques ne semble pas connaitre de limites. Recemment, le Nikon D800 et ses 36MP ont démontré qu'une très haute définition n'empêchait pas un excellent comportement du capteur au niveau de sa dynamique et de sa sensiblité (ce que les détracteurs reprochent parfois à la course aux pixels).

Mais en photographie comme ailleurs, les usages évoluent. Si les hautes définitions montrent leur avantage sur des impressions grand-formats, l'essor de l'informatique comme média de diffusion d'oeuvres photographiques est devenu incontournable. Permettre à chacun de partager instantanément ses photos, et de recevoir des avis aussi bien de professionnels que d'amateurs de par le monde entier est séduisant.
Or, Internet n'exploite pas vraiment le même genre de définitions qu'une imprimante. Si la mode est aux écrans Full HD, les définitions restent toutefois très modestes. Sur le Web, on veut voir beaucoup de choses, et vite.
Dès lors, comment transmettre l'équivalent de 20 à 30 mégapixels d'informations dans un fichier de moins d'un mégapixel ?

ImageMagick et Lanczos

Pour redimensionner une photo numérique, le programme informatique réalise une interpolation, une opération mathématique visant à construire des éléments graphiques sur base d'un nombre fini de points (les pixels de l'image originale en l'occurence). Il existe de nombreux algorithmes d'interpolation différents, les plus connues étant l'interpolation linéaire, cubique (à l'aide de splines) et d'Hermite (à l'aide de polynômes). Certains ont tendance à davantage lisser l'image, d'autres rendent les traits plus nets et plus précis.
Ci-dessous plusieurs types d'interpolations, que moi et mes yeux ont classé selon leur efficacité à redimensionner une image.

Interpolation cubique
Interpolation cubique
Interpolation quadratique Interpolation quadratique Interpolation d'Hermite Interpolation d'Hermite
Interpolation de Box Interpolation de Box Interpolation de Lanczos Interpolation de Lanczos

Pour manipuler nos images, nous allons utiliser ImageMagick, une librairie libre généralement utilisée en lignes de commandes - bien que différentes interfaces soient disponibles en C, C++, Java, Python, PHP notamment -, et compatible avec plus d'une centaine de formats (PNG, JPEG, GIF, WEBP, SVG, PDF pour citer les plus courants).
Les lignes de commandes retiendront notre préférence, et étant donné que l'application a comme finalité une diffusion sur le Web, nous allons développer notre code de redimensionnement en PHP. Les instructions seront simplement exécutées à l'aide de la fonction exec().

convert -quality 92 -filter Lanczos -resize 840x560 "mesvacances/photo01.jpg" "mesvacances/840px/photo01.jpg" 2>&1

Unsharp et Blur

Profitons-en pour augmenter sensiblement la netteté de l'image de sortie. Deux commandes vont nous servir pour cela.

-unsharp [radius]x[sigma]+[amount]+[threshold]

J'ai essayé différentes combinaisons, la plus efficace est la suivante : -unsharp 0x1.4. Les deux derniers paramètres (amount, threshold) sont donc laissés vides.

Une seconde commande va quant à elle réduire l'adoucissement de l'image de sortie :
-define filter:blur=[amount] -filter Gaussian.
[amount] prend la valeur 1 par défaut. Pour [amount]>1, l'image sera adoucie. Pour [amount]<1, l'image aura plus de "piquant". J'ai personnellement choisi 0.8.

Interpolation de Lanczos
Interpolation de Lanczos
Interpolation de Lanczos, avec unsharp et blur
Interpolation de Lanczos, avec augmentation de la netteté

Récapitulatif

Notre ligne de commandes complète est donc la suivante :
convert -quality 92 -filter Lanczos -resize 840x560 -unsharp 0x1.4 -define filter:blur=0.8 -filter Gaussian "mesvacances/photo01.jpg" "mesvacances/840px/photo01.jpg" 2>&1

Une fois intégré dans un script PHP :

<?php

// Chemins complets des fichiers d'entrée et de sortie
$in = 'mesvacances/photo01.jpg';
$out = 'mesvacances/840px/photo01.jpg';

if (!file_exists($in)) {
	exit('Le fichier d\'entrée n\'existe pas.');
}

if (file_exists($out)) {
	exit('Il existe déjà un fichier du même nom à l\'emplacement de sortie.');
}

// On calcule les dimensions de l'image de sortie
list($width, $height, $type, $attr) = getimagesize($in);
$new_width = 840;
$new_height = round($height/($width/$new_width));

// On exécute la commande 
exec('convert -quality 92 -filter Lanczos -resize '.$new_width.'x'.$new_height.' -unsharp 0x1.4 -define filter:blur=0.8 -filter Gaussian "'.$in.'" "'.$out.'" 2>&1');

// On donne les droits d'écriture au fichier de sortie
chmod($out, 0666);

?>

Haut de page