X-Git-Url: http://git.cyclocoop.org/?a=blobdiff_plain;f=www%2Fecrire%2Finc%2Ffiltres_images_lib_mini.php;fp=www%2Fecrire%2Finc%2Ffiltres_images_lib_mini.php;h=98af2847b82aa43f535187b2ac0a0a14a8b7f710;hb=4f443dce95ff6f8221c189880a70c74ce1c1f238;hp=468d6190b5dd5bf034c52009912bf106b529b989;hpb=4a628e9b277d3617535f99d663ca79fa2e891177;p=lhc%2Fweb%2Fwww.git diff --git a/www/ecrire/inc/filtres_images_lib_mini.php b/www/ecrire/inc/filtres_images_lib_mini.php index 468d6190..98af2847 100644 --- a/www/ecrire/inc/filtres_images_lib_mini.php +++ b/www/ecrire/inc/filtres_images_lib_mini.php @@ -3,7 +3,7 @@ /* *************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2017 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * @@ -14,11 +14,13 @@ * Ce fichier contient les fonctions utilisées * par les fonctions-filtres de traitement d'image. * - * @package SPIP\image + * @package SPIP\Core\Filtres\Images */ -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} include_spip('inc/filtres'); // par precaution include_spip('inc/filtres_images_mini'); // par precaution @@ -26,23 +28,29 @@ include_spip('inc/filtres_images_mini'); // par precaution * Transforme une couleur vectorielle R,G,B en hexa (par exemple pour usage css) * * @param int $red - * Valeur du rouge de 0 à 255. + * Valeur du rouge de 0 à 255. * @param int $green - * Valeur du vert de 0 à 255. + * Valeur du vert de 0 à 255. * @param int $blue - * Valeur du bleu de 0 à 255. + * Valeur du bleu de 0 à 255. * @return string - * le code de la couleur en hexadécimal. + * Le code de la couleur en hexadécimal. */ function _couleur_dec_to_hex($red, $green, $blue) { $red = dechex($red); $green = dechex($green); $blue = dechex($blue); - - if (strlen($red) == 1) $red = "0".$red; - if (strlen($green) == 1) $green = "0".$green; - if (strlen($blue) == 1) $blue = "0".$blue; - + + if (strlen($red) == 1) { + $red = "0" . $red; + } + if (strlen($green) == 1) { + $green = "0" . $green; + } + if (strlen($blue) == 1) { + $blue = "0" . $blue; + } + return "$red$green$blue"; } @@ -50,17 +58,17 @@ function _couleur_dec_to_hex($red, $green, $blue) { * Transforme une couleur hexa en vectorielle R,G,B * * @param string $couleur - * Code couleur en hexa (#000000 à #FFFFFF). + * Code couleur en hexa (#000000 à #FFFFFF). * @return array - * Un tableau des 3 éléments : rouge, vert, bleu. + * Un tableau des 3 éléments : rouge, vert, bleu. */ function _couleur_hex_to_dec($couleur) { $couleur = couleur_html_to_hex($couleur); - $couleur = preg_replace(",^#,","",$couleur); + $couleur = preg_replace(",^#,", "", $couleur); $retour["red"] = hexdec(substr($couleur, 0, 2)); $retour["green"] = hexdec(substr($couleur, 2, 2)); $retour["blue"] = hexdec(substr($couleur, 4, 2)); - + return $retour; } @@ -68,65 +76,79 @@ function _couleur_hex_to_dec($couleur) { /** * Donne un statut au fichier-image intermédiaire servant au traitement d'image * selon qu'il doit être gravé (fichier .src) ou pas. - * Un appel php direct aux fonctions de filtre d'image produira ainsi une image + * + * Un appel PHP direct aux fonctions de filtre d'image produira ainsi une image * permanente (gravée) ; un appel généré par le compilateur via - * filtrer('image_xx, ...) effacera automatiquement le fichier-image temporaire. + * `filtrer('image_xx, ...)` effacera automatiquement le fichier-image temporaire. * * @param bool|string $stat - * true, false ou le statut déjà défini si traitements enchaînés. + * true, false ou le statut déjà défini si traitements enchaînés. * @return bool - * true si il faut supprimer le fichier temporaire ; false sinon. + * true si il faut supprimer le fichier temporaire ; false sinon. */ -function statut_effacer_images_temporaires($stat){ +function statut_effacer_images_temporaires($stat) { static $statut = false; // par defaut on grave toute les images - if ($stat==='get') return $statut; - $statut = $stat?true:false; + if ($stat === 'get') { + return $statut; + } + $statut = $stat ? true : false; } /** * Fonctions de traitement d'image + * * Uniquement pour GD2. * + * @pipeline_appel image_preparer_filtre + * @uses extraire_attribut() + * @uses inserer_attribut() + * @uses tester_url_absolue() + * @uses copie_locale() Si l'image est distante + * @uses taille_image() + * @uses _image_ratio() + * @uses reconstruire_image_intermediaire() + * * @param string $img - * Un tag html . + * Chemin de l'image ou balise html ``. * @param string $effet - * Les nom et paramètres de l'effet à apporter sur l'image - * (par exemple : reduire-300-200). + * Les nom et paramètres de l'effet à apporter sur l'image + * (par exemple : reduire-300-200). * @param bool|string $forcer_format - * Un nom d'extension spécifique demandé (par exemple : jpg, png, txt... - * par défaut false : GD se débrouille seule). + * Un nom d'extension spécifique demandé (par exemple : jpg, png, txt...). + * Par défaut false : GD se débrouille seule). * @param array $fonction_creation - * Un tableau à 2 éléments. Le premier (string) indique le nom du - * filtre de traitement demandé (par exemple : image_reduire) ; le - * second (array) est lui-même un tableau reprenant la valeur de $img - * et chacun des paramètres passés au filtre. + * Un tableau à 2 éléments : + * 1) string : indique le nom du filtre de traitement demandé (par exemple : `image_reduire`) ; + * 2) array : tableau reprenant la valeur de `$img` et chacun des arguments passés au filtre utilisé. * @param bool $find_in_path - * false (par défaut) indique que l'on travaille sur un fichier - * temporaire (.src) ; true, sur un fichier définitif déjà existant. + * false (par défaut) indique que l'on travaille sur un fichier + * temporaire (.src) ; true, sur un fichier définitif déjà existant. * @return bool|string|array - * false si pas de tag =$date_src) + } else { + if (@file_exists($f = $fichier_dest)) { + if (filemtime($f) >= $date_src) { $creer = false; - } - else if (@file_exists($f = "$fichier_dest.src") - AND lire_fichier($f,$valeurs) - AND $valeurs=unserialize($valeurs) - AND $valeurs["date"]>=$date_src) + } + } else { + if (@file_exists($f = "$fichier_dest.src") + and lire_fichier($f, $valeurs) + and $valeurs = unserialize($valeurs) + and $valeurs["date"] >= $date_src + ) { $creer = false; + } + } } if ($creer) { if (!@file_exists($fichier)) { if (!@file_exists("$fichier.src")) { spip_log("Image absente : $fichier"); + return false; } # on reconstruit l'image source absente a partir de la chaine des .src @@ -259,13 +309,15 @@ function _image_valeurs_trans($img, $effet, $forcer_format = false, $fonction_cr } } - if ($creer) - spip_log("filtre image ".($fonction_creation?reset($fonction_creation):'')."[$effet] sur $fichier","images"._LOG_DEBUG); + if ($creer) { + spip_log("filtre image " . ($fonction_creation ? reset($fonction_creation) : '') . "[$effet] sur $fichier", + "images" . _LOG_DEBUG); + } // TODO: si une image png est nommee .jpg, le reconnaitre avec le bon $f - $ret["fonction_imagecreatefrom"] = "_imagecreatefrom".$term_fonction; + $ret["fonction_imagecreatefrom"] = "_imagecreatefrom" . $term_fonction; $ret["fichier"] = $fichier; - $ret["fonction_image"] = "_image_image".$terminaison_dest; + $ret["fonction_image"] = "_image_image" . $terminaison_dest; $ret["fichier_dest"] = $fichier_dest; $ret["format_source"] = ($terminaison != 'jpeg' ? $terminaison : 'jpg'); $ret["format_dest"] = $terminaison_dest; @@ -275,7 +327,7 @@ function _image_valeurs_trans($img, $effet, $forcer_format = false, $fonction_cr $ret["alt"] = extraire_attribut($img, 'alt'); $ret["style"] = extraire_attribut($img, 'style'); $ret["tag"] = $img; - if ($fonction_creation){ + if ($fonction_creation) { $ret["reconstruction"] = $fonction_creation; # ecrire ici comment creer le fichier, car il est pas sur qu'on l'ecrira reelement # cas de image_reduire qui finalement ne reduit pas l'image source @@ -283,183 +335,218 @@ function _image_valeurs_trans($img, $effet, $forcer_format = false, $fonction_cr #ecrire_fichier($ret['fichier_dest'].'.src',serialize($ret),true); } - $ret = pipeline('image_preparer_filtre',array( - 'args'=>array( - 'img'=>$img, - 'effet'=>$effet, - 'forcer_format'=>$forcer_format, - 'fonction_creation'=>$fonction_creation, - 'find_in_path'=>$find_in_path, + $ret = pipeline('image_preparer_filtre', array( + 'args' => array( + 'img' => $img, + 'effet' => $effet, + 'forcer_format' => $forcer_format, + 'fonction_creation' => $fonction_creation, + 'find_in_path' => $find_in_path, ), - 'data'=>$ret) + 'data' => $ret + ) ); // une globale pour le debug en cas de crash memoire $GLOBALS["derniere_image_calculee"] = $ret; - if (!function_exists($ret["fonction_imagecreatefrom"])) return false; + if (!function_exists($ret["fonction_imagecreatefrom"])) { + return false; + } + return $ret; } /** * Crée une image depuis un fichier ou une URL + * * Utilise les fonctions spécifiques GD. * * @param string $filename - * Le path vers l'image à traiter (par exemple : IMG/distant/jpg/image.jpg - * ou local/cache-vignettes/L180xH51/image.jpg). + * Le path vers l'image à traiter (par exemple : IMG/distant/jpg/image.jpg + * ou local/cache-vignettes/L180xH51/image.jpg). * @return ressource - * Une ressource de type Image GD. + * Une ressource de type Image GD. */ -function _imagecreatefromjpeg($filename){ +function _imagecreatefromjpeg($filename) { $img = @imagecreatefromjpeg($filename); if (!$img) { - spip_log("Erreur lecture imagecreatefromjpeg $filename",_LOG_CRITIQUE); + spip_log("Erreur lecture imagecreatefromjpeg $filename", _LOG_CRITIQUE); erreur_squelette("Erreur lecture imagecreatefromjpeg $filename"); - $img = imagecreate(10,10); + $img = imagecreate(10, 10); } + return $img; } /** - * Crée une image depuis un fichier ou une URL + * Crée une image depuis un fichier ou une URL (au format png) + * * Utilise les fonctions spécifiques GD. * * @param string $filename - * Le path vers l'image à traiter (par exemple : IMG/distant/png/image.png - * ou local/cache-vignettes/L180xH51/image.png). + * Le path vers l'image à traiter (par exemple : IMG/distant/png/image.png + * ou local/cache-vignettes/L180xH51/image.png). * @return ressource - * Une ressource de type Image GD. + * Une ressource de type Image GD. */ -function _imagecreatefrompng($filename){ +function _imagecreatefrompng($filename) { $img = @imagecreatefrompng($filename); if (!$img) { - spip_log("Erreur lecture imagecreatefrompng $filename",_LOG_CRITIQUE); + spip_log("Erreur lecture imagecreatefrompng $filename", _LOG_CRITIQUE); erreur_squelette("Erreur lecture imagecreatefrompng $filename"); - $img = imagecreate(10,10); + $img = imagecreate(10, 10); } + return $img; } /** - * Crée une image depuis un fichier ou une URL + * Crée une image depuis un fichier ou une URL (au format gif) + * * Utilise les fonctions spécifiques GD. * * @param string $filename - * Le path vers l'image à traiter (par exemple : IMG/distant/gif/image.gif - * ou local/cache-vignettes/L180xH51/image.gif). + * Le path vers l'image à traiter (par exemple : IMG/distant/gif/image.gif + * ou local/cache-vignettes/L180xH51/image.gif). * @return ressource - * Une ressource de type Image GD. + * Une ressource de type Image GD. */ -function _imagecreatefromgif($filename){ +function _imagecreatefromgif($filename) { $img = @imagecreatefromgif($filename); if (!$img) { - spip_log("Erreur lecture imagecreatefromgif $filename",_LOG_CRITIQUE); + spip_log("Erreur lecture imagecreatefromgif $filename", _LOG_CRITIQUE); erreur_squelette("Erreur lecture imagecreatefromgif $filename"); - $img = imagecreate(10,10); + $img = imagecreate(10, 10); } + return $img; } /** * Affiche ou sauvegarde une image au format PNG + * * Utilise les fonctions spécifiques GD. * * @param ressource $img - * Une ressource de type Image GD. + * Une ressource de type Image GD. * @param string $fichier - * Le path vers l'image (ex : local/cache-vignettes/L180xH51/image.png). + * Le path vers l'image (ex : local/cache-vignettes/L180xH51/image.png). * @return bool - * false si l'image créée a une largeur nulle ou n'existe pas ; - * true si une image est bien retournée. + * + * - false si l'image créée a une largeur nulle ou n'existe pas ; + * - true si une image est bien retournée. */ function _image_imagepng($img, $fichier) { - if (!function_exists('imagepng')) return false; - $tmp = $fichier.".tmp"; - $ret = imagepng($img,$tmp); - - if(file_exists($tmp)){ + if (!function_exists('imagepng')) { + return false; + } + $tmp = $fichier . ".tmp"; + $ret = imagepng($img, $tmp); + if (file_exists($tmp)) { $taille_test = getimagesize($tmp); - if ($taille_test[0] < 1) return false; - + if ($taille_test[0] < 1) { + return false; + } + spip_unlink($fichier); // le fichier peut deja exister @rename($tmp, $fichier); + return $ret; } + return false; } /** * Affiche ou sauvegarde une image au format GIF + * * Utilise les fonctions spécifiques GD. * * @param ressource $img - * Une ressource de type Image GD. + * Une ressource de type Image GD. * @param string $fichier - * Le path vers l'image (ex : local/cache-vignettes/L180xH51/image.gif). + * Le path vers l'image (ex : local/cache-vignettes/L180xH51/image.gif). * @return bool - * false si l'image créée a une largeur nulle ou n'existe pas; - * true si une image est bien retournée. + * + * - false si l'image créée a une largeur nulle ou n'existe pas ; + * - true si une image est bien retournée. */ -function _image_imagegif($img,$fichier) { - if (!function_exists('imagegif')) return false; - $tmp = $fichier.".tmp"; - $ret = imagegif($img,$tmp); - - if(file_exists($tmp)){ +function _image_imagegif($img, $fichier) { + if (!function_exists('imagegif')) { + return false; + } + $tmp = $fichier . ".tmp"; + $ret = imagegif($img, $tmp); + if (file_exists($tmp)) { $taille_test = getimagesize($tmp); - if ($taille_test[0] < 1) return false; + if ($taille_test[0] < 1) { + return false; + } spip_unlink($fichier); // le fichier peut deja exister @rename($tmp, $fichier); + return $ret; } + return false; } /** * Affiche ou sauvegarde une image au format JPG + * * Utilise les fonctions spécifiques GD. * * @param ressource $img - * Une ressource de type Image GD. + * Une ressource de type Image GD. * @param string $fichier - * Le path vers l'image (ex : local/cache-vignettes/L180xH51/image.jpg). + * Le path vers l'image (ex : local/cache-vignettes/L180xH51/image.jpg). * @param int $qualite - * Le niveau de qualité du fichier résultant : de 0 (pire qualité, petit - * fichier) à 100 (meilleure qualité, gros fichier). Par défaut, prend la - * valeur (85) de la constante _IMG_GD_QUALITE (modifiable depuis - * mes_options.php). + * Le niveau de qualité du fichier résultant : de 0 (pire qualité, petit + * fichier) à 100 (meilleure qualité, gros fichier). Par défaut, prend la + * valeur (85) de la constante _IMG_GD_QUALITE (modifiable depuis + * mes_options.php). * @return bool - * false si l'image créée a une largeur nulle ou n'existe pas ; - * true si une image est bien retournée. + * + * - false si l'image créée a une largeur nulle ou n'existe pas ; + * - true si une image est bien retournée. */ -function _image_imagejpg($img,$fichier,$qualite=_IMG_GD_QUALITE) { - if (!function_exists('imagejpeg')) return false; - $tmp = $fichier.".tmp"; - $ret = imagejpeg($img,$tmp, $qualite); - - if(file_exists($tmp)){ +function _image_imagejpg($img, $fichier, $qualite = _IMG_GD_QUALITE) { + if (!function_exists('imagejpeg')) { + return false; + } + $tmp = $fichier . ".tmp"; + $ret = imagejpeg($img, $tmp, $qualite); + + if (file_exists($tmp)) { $taille_test = getimagesize($tmp); - if ($taille_test[0] < 1) return false; - + if ($taille_test[0] < 1) { + return false; + } + spip_unlink($fichier); // le fichier peut deja exister @rename($tmp, $fichier); + return $ret; } + return false; } /** * Crée un fichier-image au format ICO + * * Utilise les fonctions de la classe phpthumb_functions. * + * @uses phpthumb_functions::GD2ICOstring() + * * @param ressource $img - * Une ressource de type Image GD. + * Une ressource de type Image GD. * @param string $fichier - * Le path vers l'image (ex : local/cache-vignettes/L180xH51/image.jpg). + * Le path vers l'image (ex : local/cache-vignettes/L180xH51/image.jpg). * @return bool - * true si le fichier a bien été créé ; false sinon. + * true si le fichier a bien été créé ; false sinon. */ function _image_imageico($img, $fichier) { $gd_image_array = array($img); @@ -469,60 +556,73 @@ function _image_imageico($img, $fichier) { /** * Finalise le traitement GD + * * Crée un fichier_image temporaire .src ou vérifie que le fichier_image * définitif a bien été créé. * + * @uses statut_effacer_images_temporaires() + * * @param ressource $img - * Une ressource de type Image GD. + * Une ressource de type Image GD. * @param array $valeurs - * Un tableau des informations (tailles, traitement, path...) accompagnant - * l'image. + * Un tableau des informations (tailles, traitement, path...) accompagnant + * l'image. * @param int $qualite - * N'est utilisé que pour les images jpg. - * Le niveau de qualité du fichier résultant : de 0 (pire qualité, petit - * fichier) à 100 (meilleure qualité, gros fichier). Par défaut, prend la - * valeur (85) de la constante _IMG_GD_QUALITE (modifiable depuis - * mes_options.php). + * N'est utilisé que pour les images jpg. + * Le niveau de qualité du fichier résultant : de 0 (pire qualité, petit + * fichier) à 100 (meilleure qualité, gros fichier). Par défaut, prend la + * valeur (85) de la constante _IMG_GD_QUALITE (modifiable depuis + * mes_options.php). * @return bool - * true si le traitement GD s'est bien finalisé ; - * false sinon. + * - true si le traitement GD s'est bien finalisé ; + * - false sinon. */ -function _image_gd_output($img,$valeurs, $qualite=_IMG_GD_QUALITE){ - $fonction = "_image_image".$valeurs['format_dest']; +function _image_gd_output($img, $valeurs, $qualite = _IMG_GD_QUALITE) { + $fonction = "_image_image" . $valeurs['format_dest']; $ret = false; #un flag pour reperer les images gravees - $lock = + $lock = !statut_effacer_images_temporaires('get') // si la fonction n'a pas ete activee, on grave tout - OR (@file_exists($valeurs['fichier_dest']) AND !@file_exists($valeurs['fichier_dest'].'.src')); + or (@file_exists($valeurs['fichier_dest']) and !@file_exists($valeurs['fichier_dest'] . '.src')); if ( - function_exists($fonction) - && ($ret = $fonction($img,$valeurs['fichier_dest'],$qualite)) # on a reussi a creer l'image - && isset($valeurs['reconstruction']) # et on sait comment la resonctruire le cas echeant - && !$lock - ) - if (@file_exists($valeurs['fichier_dest'])){ + function_exists($fonction) + && ($ret = $fonction($img, $valeurs['fichier_dest'], $qualite)) # on a reussi a creer l'image + && isset($valeurs['reconstruction']) # et on sait comment la resonctruire le cas echeant + && !$lock + ) { + if (@file_exists($valeurs['fichier_dest'])) { // dans tous les cas mettre a jour la taille de l'image finale - list ($valeurs["hauteur_dest"],$valeurs["largeur_dest"]) = taille_image($valeurs['fichier_dest']); + list($valeurs["hauteur_dest"], $valeurs["largeur_dest"]) = taille_image($valeurs['fichier_dest']); $valeurs['date'] = @filemtime($valeurs['fichier_dest']); // pour la retrouver apres disparition - ecrire_fichier($valeurs['fichier_dest'].'.src',serialize($valeurs),true); + ecrire_fichier($valeurs['fichier_dest'] . '.src', serialize($valeurs), true); } + } + return $ret; } -// http://doc.spip.org/@reconstruire_image_intermediaire -function reconstruire_image_intermediaire($fichier_manquant){ +/** + * Reconstruit une image à partir des sources de contrôle de son ancienne + * construction + * + * @uses ramasse_miettes() + * + * @param string $fichier_manquant + * Chemin vers le fichier manquant + **/ +function reconstruire_image_intermediaire($fichier_manquant) { $reconstruire = array(); $fichier = $fichier_manquant; while (strpos($fichier,"://")===false and !@file_exists($fichier) - AND lire_fichier($src = "$fichier.src",$source) - AND $valeurs=unserialize($source) - AND ($fichier = $valeurs['fichier']) # l'origine est connue (on ne verifie pas son existence, qu'importe ...) - ) { - spip_unlink($src); // si jamais on a un timeout pendant la reconstruction, elle se fera naturellement au hit suivant - $reconstruire[] = $valeurs['reconstruction']; - } - while (count($reconstruire)){ + and lire_fichier($src = "$fichier.src", $source) + and $valeurs = unserialize($source) + and ($fichier = $valeurs['fichier']) # l'origine est connue (on ne verifie pas son existence, qu'importe ...) + ) { + spip_unlink($src); // si jamais on a un timeout pendant la reconstruction, elle se fera naturellement au hit suivant + $reconstruire[] = $valeurs['reconstruction']; + } + while (count($reconstruire)) { $r = array_pop($reconstruire); $fonction = $r[0]; $args = $r[1]; @@ -558,11 +658,12 @@ function ramasse_miettes($fichier) { } spip_unlink($src); # on supprime la reference a sa source pour marquer cette image comme non intermediaire while ( - ($fichier = $valeurs['fichier']) # l'origine est connue (on ne verifie pas son existence, qu'importe ...) - AND (substr($fichier,0,strlen(_DIR_VAR))==_DIR_VAR) # et est dans local - AND (lire_fichier($src = "$fichier.src",$source)) # le fichier a une source connue (c'est donc une image calculee intermediaire) - AND ($valeurs=unserialize($source)) # et valide - ) { + ($fichier = $valeurs['fichier']) # l'origine est connue (on ne verifie pas son existence, qu'importe ...) + and (substr($fichier, 0, strlen(_DIR_VAR)) == _DIR_VAR) # et est dans local + and (lire_fichier($src = "$fichier.src", + $source)) # le fichier a une source connue (c'est donc une image calculee intermediaire) + and ($valeurs = unserialize($source)) # et valide + ) { # on efface le fichier spip_unlink($fichier); # mais laisse le .src qui permet de savoir comment reconstruire l'image si besoin @@ -570,127 +671,224 @@ function ramasse_miettes($fichier) { } } -// http://doc.spip.org/@image_graver -function image_graver($img){ + +/** + * Clôture une série de filtres d'images + * + * Ce filtre est automatiquement appelé à la fin d'une série de filtres + * d'images dans un squelette. + * + * @filtre + * @uses reconstruire_image_intermediaire() + * Si l'image finale a déjà été supprimée car considérée comme temporaire + * par une autre série de filtres images débutant pareil + * @uses ramasse_miettes() + * Pour déclarer l'image définitive et nettoyer les images intermédiaires. + * + * @pipeline_appel post_image_filtrer + * + * @param string $img + * Code HTML de l'image + * @return string + * Code HTML de l'image + **/ +function image_graver($img) { // appeler le filtre post_image_filtrer qui permet de faire // des traitements auto a la fin d'une serie de filtres - $img = pipeline('post_image_filtrer',$img); + $img = pipeline('post_image_filtrer', $img); - $fichier = extraire_attribut($img, 'src'); - if (($p=strpos($fichier,'?'))!==FALSE) - $fichier=substr($fichier,0,$p); - if (strlen($fichier) < 1) + $fichier_ori = $fichier = extraire_attribut($img, 'src'); + if (($p = strpos($fichier, '?')) !== false) { + $fichier = substr($fichier, 0, $p); + } + if (strlen($fichier) < 1) { $fichier = $img; + } # si jamais le fichier final n'a pas ete calcule car suppose temporaire # et qu'il ne s'agit pas d'une URL if (strpos($fichier,"://")===false and !@file_exists($fichier)) { reconstruire_image_intermediaire($fichier); } ramasse_miettes($fichier); - return $img; // on ne change rien + + // ajouter le timestamp si besoin + if (strpos($fichier_ori, "?") === false) { + // on utilise str_replace pour attraper le onmouseover des logo si besoin + $img = str_replace($fichier_ori, timestamp($fichier_ori), $img); + } + + return $img; } -// Transforme une image a palette indexee (256 couleurs max) en "vraies" couleurs RGB -// Existe seulement pour compatibilite avec PHP < 5.5 -// http://doc.spip.org/@imagepalettetotruecolor + if (!function_exists("imagepalettetotruecolor")) { -function imagepalettetotruecolor(&$img) { - if ($img AND !imageistruecolor($img) AND function_exists('imagecreatetruecolor')) { - $w = imagesx($img); - $h = imagesy($img); - $img1 = imagecreatetruecolor($w,$h); - //Conserver la transparence si possible - if(function_exists('ImageCopyResampled')) { - if (function_exists("imageAntiAlias")) imageAntiAlias($img1,true); - @imagealphablending($img1, false); - @imagesavealpha($img1,true); - @ImageCopyResampled($img1, $img, 0, 0, 0, 0, $w, $h, $w, $h); - } else { - imagecopy($img1,$img,0,0,0,0,$w,$h); + /** + * Transforme une image à palette indexée (256 couleurs max) en "vraies" couleurs RGB + * + * @note Pour compatibilité avec PHP < 5.5 + * + * @link http://php.net/manual/fr/function.imagepalettetotruecolor.php + * + * @param ressource $img + * @return bool + * - true si l'image est déjà en vrai RGB ou peut être transformée + * - false si la transformation ne peut être faite. + **/ + function imagepalettetotruecolor(&$img) { + if (!$img or !function_exists('imagecreatetruecolor')) { + return false; + } elseif (!imageistruecolor($img)) { + $w = imagesx($img); + $h = imagesy($img); + $img1 = imagecreatetruecolor($w, $h); + //Conserver la transparence si possible + if (function_exists('ImageCopyResampled')) { + if (function_exists("imageAntiAlias")) { + imageAntiAlias($img1, true); + } + @imagealphablending($img1, false); + @imagesavealpha($img1, true); + @ImageCopyResampled($img1, $img, 0, 0, 0, 0, $w, $h, $w, $h); + } else { + imagecopy($img1, $img, 0, 0, 0, 0, $w, $h); + } + + $img = $img1; } - $img = $img1; + return true; } } -} -// http://doc.spip.org/@image_tag_changer_taille -function _image_tag_changer_taille($tag,$width,$height,$style=false){ - if ($style===false) $style = extraire_attribut($tag,'style'); +/** + * Applique des attributs de taille (width, height) à une balise HTML + * + * Utilisé avec des balises `` tout particulièrement. + * + * Modifie l'attribut style s'il était renseigné, en enlevant les + * informations éventuelles width / height dedans. + * + * @uses extraire_attribut() + * @uses inserer_attribut() + * + * @param string $tag + * Code html de la balise + * @param int $width + * Hauteur + * @param int $height + * Largeur + * @param bool|string $style + * Attribut html style à appliquer. + * False extrait celui présent dans la balise + * @return string + * Code html modifié de la balise. + **/ +function _image_tag_changer_taille($tag, $width, $height, $style = false) { + if ($style === false) { + $style = extraire_attribut($tag, 'style'); + } + // enlever le width et height du style - $style = preg_replace(",(^|;)\s*(width|height)\s*:\s*[^;]+,ims","",$style); - if ($style AND $style{0}==';') $style=substr($style,1); + $style = preg_replace(",(^|;)\s*(width|height)\s*:\s*[^;]+,ims", "", $style); + if ($style and $style{0} == ';') { + $style = substr($style, 1); + } + // mettre des attributs de width et height sur les images, // ca accelere le rendu du navigateur // ca permet aux navigateurs de reserver la bonne taille // quand on a desactive l'affichage des images. - $tag = inserer_attribut($tag,'width',$width); - $tag = inserer_attribut($tag,'height',$height); - - // Ancien style inline pour IE6 mais qui casse la possibilité de surcharger en CSS - //$style = "height:".$height."px;width:".$width."px;".$style; - + $tag = inserer_attribut($tag, 'width', $width); + $tag = inserer_attribut($tag, 'height', $height); + // attributs deprecies. Transformer en CSS - if ($espace = extraire_attribut($tag, 'hspace')){ - $style = "margin:${espace}px;".$style; - $tag = inserer_attribut($tag,'hspace',''); + if ($espace = extraire_attribut($tag, 'hspace')) { + $style = "margin:${espace}px;" . $style; + $tag = inserer_attribut($tag, 'hspace', ''); } - $tag = inserer_attribut($tag,'style',$style, true, $style ? false : true); + + $tag = inserer_attribut($tag, 'style', $style, true, $style ? false : true); + return $tag; } -// function d'ecriture du de la balise img en sortie des filtre image -// reprend le tag initial et surcharge les tags modifies -function _image_ecrire_tag($valeurs,$surcharge=array()){ - $valeurs = pipeline('image_ecrire_tag_preparer',$valeurs); - $tag = str_replace(">","/>",str_replace("/>",">",$valeurs['tag'])); // fermer les tags img pas bien fermes; - +/** + * Écriture de la balise img en sortie de filtre image + * + * Reprend le tag initial et surcharge les attributs modifiés + * + * @pipeline_appel image_ecrire_tag_preparer + * @pipeline_appel image_ecrire_tag_finir + * + * @uses _image_tag_changer_taille() + * @uses extraire_attribut() + * @uses inserer_attribut() + * @see _image_valeurs_trans() + * + * @param array $valeurs + * Description de l'image tel que retourné par `_image_valeurs_trans()` + * @param array $surcharge + * Permet de surcharger certaines descriptions présentes dans `$valeurs` + * tel que 'style', 'width', 'height' + * @return string + * Retourne le code HTML de l'image + **/ +function _image_ecrire_tag($valeurs, $surcharge = array()) { + $valeurs = pipeline('image_ecrire_tag_preparer', $valeurs); + + // fermer les tags img pas bien fermes; + $tag = str_replace(">", "/>", str_replace("/>", ">", $valeurs['tag'])); + // le style $style = $valeurs['style']; - if (isset($surcharge['style'])){ + if (isset($surcharge['style'])) { $style = $surcharge['style']; unset($surcharge['style']); } - + // traiter specifiquement la largeur et la hauteur $width = $valeurs['largeur']; - if (isset($surcharge['width'])){ + if (isset($surcharge['width'])) { $width = $surcharge['width']; unset($surcharge['width']); } $height = $valeurs['hauteur']; - if (isset($surcharge['height'])){ + if (isset($surcharge['height'])) { $height = $surcharge['height']; unset($surcharge['height']); } - $tag = _image_tag_changer_taille($tag,$width,$height,$style); + $tag = _image_tag_changer_taille($tag, $width, $height, $style); // traiter specifiquement le src qui peut etre repris dans un onmouseout // on remplace toute les ref a src dans le tag - $src = extraire_attribut($tag,'src'); - if (isset($surcharge['src'])){ - $tag = str_replace($src,$surcharge['src'],$tag); + $src = extraire_attribut($tag, 'src'); + if (isset($surcharge['src'])) { + $tag = str_replace($src, $surcharge['src'], $tag); // si il y a des & dans src, alors ils peuvent provenir d'un & // pas garanti comme methode, mais mieux que rien - if (strpos($src,'&') !== false) - $tag = str_replace(str_replace("&","&",$src),$surcharge['src'],$tag); + if (strpos($src, '&') !== false) { + $tag = str_replace(str_replace("&", "&", $src), $surcharge['src'], $tag); + } $src = $surcharge['src']; unset($surcharge['src']); } $class = $valeurs['class']; - if (isset($surcharge['class'])){ + if (isset($surcharge['class'])) { $class = $surcharge['class']; unset($surcharge['class']); } - if(strlen($class)) - $tag = inserer_attribut($tag,'class',$class); + if (strlen($class)) { + $tag = inserer_attribut($tag, 'class', $class); + } + + if (count($surcharge)) { + foreach ($surcharge as $attribut => $valeur) { + $tag = inserer_attribut($tag, $attribut, $valeur); + } + } - if (count($surcharge)) - foreach($surcharge as $attribut=>$valeur) - $tag = inserer_attribut($tag,$attribut,$valeur); - $tag = pipeline('image_ecrire_tag_finir', array( 'args' => array( @@ -704,264 +902,388 @@ function _image_ecrire_tag($valeurs,$surcharge=array()){ return $tag; } -function _image_creer_vignette($valeurs, $maxWidth, $maxHeight, $process='AUTO', $force=false, $test_cache_only = false) { +/** + * Crée si possible une miniature d'une image + * + * @see _image_valeurs_trans() + * @uses _image_ratio() + * + * @param array $valeurs + * Description de l'image, telle que retournée par `_image_valeurs_trans()` + * @param int $maxWidth + * Largeur maximum en px de la miniature à réaliser + * @param int $maxHeight + * Hauteur maximum en px de la miniateure à réaliser + * @param string $process + * Librairie graphique à utiliser (gd1, gd2, netpbm, convert, imagick). + * AUTO utilise la librairie sélectionnée dans la configuration. + * @param bool $force + * @return array|null + * Description de l'image, sinon null. + **/ +function _image_creer_vignette($valeurs, $maxWidth, $maxHeight, $process = 'AUTO', $force = false) { // ordre de preference des formats graphiques pour creer les vignettes // le premier format disponible, selon la methode demandee, est utilise $image = $valeurs['fichier']; $format = $valeurs['format_source']; $destdir = dirname($valeurs['fichier_dest']); - $destfile = basename($valeurs['fichier_dest'],".".$valeurs["format_dest"]); - + $destfile = basename($valeurs['fichier_dest'], "." . $valeurs["format_dest"]); + $format_sortie = $valeurs['format_dest']; - + + if (($process == 'AUTO') and isset($GLOBALS['meta']['image_process'])) { + $process = $GLOBALS['meta']['image_process']; + } + // liste des formats qu'on sait lire $img = isset($GLOBALS['meta']['formats_graphiques']) - ? (strpos($GLOBALS['meta']['formats_graphiques'], $format)!==false) - : false; + ? (strpos($GLOBALS['meta']['formats_graphiques'], $format) !== false) + : false; // si le doc n'est pas une image, refuser - if (!$force AND !$img) return; + if (!$force and !$img) { + return; + } $destination = "$destdir/$destfile"; - // chercher un cache - $vignette = ''; - if ($test_cache_only AND !$vignette) return; + // calculer la taille + if (($srcWidth = $valeurs['largeur']) && ($srcHeight = $valeurs['hauteur'])) { + if (!($destWidth = $valeurs['largeur_dest']) || !($destHeight = $valeurs['hauteur_dest'])) { + list($destWidth, $destHeight) = _image_ratio($valeurs['largeur'], $valeurs['hauteur'], $maxWidth, $maxHeight); + } + } elseif ($process == 'convert' or $process == 'imagick') { + $destWidth = $maxWidth; + $destHeight = $maxHeight; + } else { + spip_log("echec $process sur $image"); - // utiliser le cache ? - if (!$test_cache_only) - if ($force OR !$vignette OR (@filemtime($vignette) < @filemtime($image))) { + return; + } - $creation = true; - // calculer la taille - if (($srcWidth=$valeurs['largeur']) && ($srcHeight=$valeurs['hauteur'])){ - if (!($destWidth=$valeurs['largeur_dest']) || !($destHeight=$valeurs['hauteur_dest'])) - list ($destWidth,$destHeight) = _image_ratio($valeurs['largeur'], $valeurs['hauteur'], $maxWidth, $maxHeight); - } - elseif ($process == 'convert' OR $process == 'imagick') { - $destWidth = $maxWidth; - $destHeight = $maxHeight; - } else { - spip_log("echec $process sur $image"); - return; + // Si l'image est de la taille demandee (ou plus petite), simplement la retourner + if ($srcWidth and $srcWidth <= $maxWidth and $srcHeight <= $maxHeight) { + $vignette = $destination . '.' . $format; + @copy($image, $vignette); + } // imagemagick en ligne de commande + elseif ($process == 'convert') { + if (!defined('_CONVERT_COMMAND')) { + define('_CONVERT_COMMAND', 'convert'); + } // Securite : mes_options.php peut preciser le chemin absolu + if (!defined('_RESIZE_COMMAND')) { + define('_RESIZE_COMMAND', _CONVERT_COMMAND . ' -quality ' . _IMG_CONVERT_QUALITE . ' -resize %xx%y! %src %dest'); } + $vignette = $destination . "." . $format_sortie; + $commande = str_replace( + array('%x', '%y', '%src', '%dest'), + array( + $destWidth, + $destHeight, + escapeshellcmd($image), + escapeshellcmd($vignette) + ), + _RESIZE_COMMAND); + spip_log($commande); + exec($commande); + if (!@file_exists($vignette)) { + spip_log("echec convert sur $vignette"); - // Si l'image est de la taille demandee (ou plus petite), simplement - // la retourner - if ($srcWidth - AND $srcWidth <= $maxWidth AND $srcHeight <= $maxHeight) { - $vignette = $destination.'.'.$format; - @copy($image, $vignette); + return; // echec commande } - // imagemagick en ligne de commande - else if ($process == 'convert') { - define('_CONVERT_COMMAND', 'convert'); - define ('_RESIZE_COMMAND', _CONVERT_COMMAND.' -quality '._IMG_CONVERT_QUALITE.' -resize %xx%y! %src %dest'); - $vignette = $destination.".".$format_sortie; - $commande = str_replace( - array('%x', '%y', '%src', '%dest'), - array( - $destWidth, - $destHeight, - escapeshellcmd($image), - escapeshellcmd($vignette) - ), - _RESIZE_COMMAND); - spip_log($commande); - exec($commande); - if (!@file_exists($vignette)) { - spip_log("echec convert sur $vignette"); - return; // echec commande - } - } - else - // imagick (php4-imagemagick) - if ($process == 'imagick') { + } // php5 imagemagick + elseif ($process == 'imagick') { + $vignette = "$destination." . $format_sortie; - $vignette = "$destination.".$format_sortie; + if (!class_exists('Imagick')) { + spip_log("Classe Imagick absente !", _LOG_ERREUR); - $imagick = new Imagick(); - $imagick->readImage($image); - $imagick->resizeImage($destWidth, $destHeight, Imagick::FILTER_LANCZOS, 1 );//, IMAGICK_FILTER_LANCZOS, _IMG_IMAGICK_QUALITE / 100); - $imagick->writeImage($vignette); + return; + } + $imagick = new Imagick(); + $imagick->readImage($image); + $imagick->resizeImage($destWidth, $destHeight, Imagick::FILTER_LANCZOS, + 1);//, IMAGICK_FILTER_LANCZOS, _IMG_IMAGICK_QUALITE / 100); + $imagick->writeImage($vignette); + if (!@file_exists($vignette)) { + spip_log("echec imagick sur $vignette"); + + return; + } + } // netpbm + elseif ($process == "netpbm") { + if (!defined('_PNMSCALE_COMMAND')) { + define('_PNMSCALE_COMMAND', 'pnmscale'); + } // Securite : mes_options.php peut preciser le chemin absolu + if (_PNMSCALE_COMMAND == '') { + return; + } + $vignette = $destination . "." . $format_sortie; + $pnmtojpeg_command = str_replace("pnmscale", "pnmtojpeg", _PNMSCALE_COMMAND); + if ($format == "jpg") { + + $jpegtopnm_command = str_replace("pnmscale", "jpegtopnm", _PNMSCALE_COMMAND); + exec("$jpegtopnm_command $image | " . _PNMSCALE_COMMAND . " -width $destWidth | $pnmtojpeg_command > $vignette"); + if (!($s = @filesize($vignette))) { + spip_unlink($vignette); + } if (!@file_exists($vignette)) { - spip_log("echec imagick sur $vignette"); + spip_log("echec netpbm-jpg sur $vignette"); + return; } - } - else - // netpbm - if ($process == "netpbm") { - define('_PNMSCALE_COMMAND', 'pnmscale'); // chemin a changer dans mes_options - if (_PNMSCALE_COMMAND == '') return; - $vignette = $destination.".".$format_sortie; - $pnmtojpeg_command = str_replace("pnmscale", "pnmtojpeg", _PNMSCALE_COMMAND); - if ($format == "jpg") { - - $jpegtopnm_command = str_replace("pnmscale", "jpegtopnm", _PNMSCALE_COMMAND); - exec("$jpegtopnm_command $image | "._PNMSCALE_COMMAND." -width $destWidth | $pnmtojpeg_command > $vignette"); - if (!($s = @filesize($vignette))) - spip_unlink($vignette); - if (!@file_exists($vignette)) { - spip_log("echec netpbm-jpg sur $vignette"); - return; - } - } else if ($format == "gif") { + } else { + if ($format == "gif") { $giftopnm_command = str_replace("pnmscale", "giftopnm", _PNMSCALE_COMMAND); - exec("$giftopnm_command $image | "._PNMSCALE_COMMAND." -width $destWidth | $pnmtojpeg_command > $vignette"); - if (!($s = @filesize($vignette))) + exec("$giftopnm_command $image | " . _PNMSCALE_COMMAND . " -width $destWidth | $pnmtojpeg_command > $vignette"); + if (!($s = @filesize($vignette))) { spip_unlink($vignette); + } if (!@file_exists($vignette)) { spip_log("echec netpbm-gif sur $vignette"); + return; } - } else if ($format == "png") { - $pngtopnm_command = str_replace("pnmscale", "pngtopnm", _PNMSCALE_COMMAND); - exec("$pngtopnm_command $image | "._PNMSCALE_COMMAND." -width $destWidth | $pnmtojpeg_command > $vignette"); - if (!($s = @filesize($vignette))) - spip_unlink($vignette); - if (!@file_exists($vignette)) { - spip_log("echec netpbm-png sur $vignette"); - return; + } else { + if ($format == "png") { + $pngtopnm_command = str_replace("pnmscale", "pngtopnm", _PNMSCALE_COMMAND); + exec("$pngtopnm_command $image | " . _PNMSCALE_COMMAND . " -width $destWidth | $pnmtojpeg_command > $vignette"); + if (!($s = @filesize($vignette))) { + spip_unlink($vignette); + } + if (!@file_exists($vignette)) { + spip_log("echec netpbm-png sur $vignette"); + + return; + } } } } - // gd ou gd2 - else if ($process == 'gd1' OR $process == 'gd2') { - if (_IMG_GD_MAX_PIXELS && $srcWidth*$srcHeight>_IMG_GD_MAX_PIXELS){ - spip_log("vignette gd1/gd2 impossible : ".$srcWidth*$srcHeight."pixels"); - return; - } - $destFormat = $format_sortie; - if (!$destFormat) { - spip_log("pas de format pour $image"); - return; - } + } // gd ou gd2 + elseif ($process == 'gd1' or $process == 'gd2') { + if (!function_exists('gd_info')) { + spip_log("Librairie GD absente !", _LOG_ERREUR); - $fonction_imagecreatefrom = $valeurs['fonction_imagecreatefrom']; - if (!function_exists($fonction_imagecreatefrom)) - return ''; - $srcImage = @$fonction_imagecreatefrom($image); - if (!$srcImage) { - spip_log("echec gd1/gd2"); - return; - } - - // Initialisation de l'image destination - if ($process == 'gd2' AND $destFormat != "gif") - $destImage = ImageCreateTrueColor($destWidth, $destHeight); - if (!$destImage) - $destImage = ImageCreate($destWidth, $destHeight); - - // Recopie de l'image d'origine avec adaptation de la taille - $ok = false; - if (($process == 'gd2') AND function_exists('ImageCopyResampled')) { - if ($format == "gif") { - // Si un GIF est transparent, - // fabriquer un PNG transparent - $transp = imagecolortransparent($srcImage); - if ($transp > 0) $destFormat = "png"; + return; + } + if (_IMG_GD_MAX_PIXELS && $srcWidth * $srcHeight > _IMG_GD_MAX_PIXELS) { + spip_log("vignette gd1/gd2 impossible : " . $srcWidth * $srcHeight . "pixels"); + + return; + } + $destFormat = $format_sortie; + if (!$destFormat) { + spip_log("pas de format pour $image"); + + return; + } + + $fonction_imagecreatefrom = $valeurs['fonction_imagecreatefrom']; + if (!function_exists($fonction_imagecreatefrom)) { + return ''; + } + $srcImage = @$fonction_imagecreatefrom($image); + if (!$srcImage) { + spip_log("echec gd1/gd2"); + + return; + } + + // Initialisation de l'image destination + $destImage = null; + if ($process == 'gd2' and $destFormat != "gif") { + $destImage = ImageCreateTrueColor($destWidth, $destHeight); + } + if (!$destImage) { + $destImage = ImageCreate($destWidth, $destHeight); + } + + // Recopie de l'image d'origine avec adaptation de la taille + $ok = false; + if (($process == 'gd2') and function_exists('ImageCopyResampled')) { + if ($format == "gif") { + // Si un GIF est transparent, + // fabriquer un PNG transparent + $transp = imagecolortransparent($srcImage); + if ($transp > 0) { + $destFormat = "png"; } - if ($destFormat == "png") { - // Conserver la transparence - if (function_exists("imageAntiAlias")) imageAntiAlias($destImage,true); - @imagealphablending($destImage, false); - @imagesavealpha($destImage,true); + } + if ($destFormat == "png") { + // Conserver la transparence + if (function_exists("imageAntiAlias")) { + imageAntiAlias($destImage, true); } - $ok = @ImageCopyResampled($destImage, $srcImage, 0, 0, 0, 0, $destWidth, $destHeight, $srcWidth, $srcHeight); + @imagealphablending($destImage, false); + @imagesavealpha($destImage, true); } - if (!$ok) - $ok = ImageCopyResized($destImage, $srcImage, 0, 0, 0, 0, $destWidth, $destHeight, $srcWidth, $srcHeight); + $ok = @ImageCopyResampled($destImage, $srcImage, 0, 0, 0, 0, $destWidth, $destHeight, $srcWidth, $srcHeight); + } + if (!$ok) { + $ok = ImageCopyResized($destImage, $srcImage, 0, 0, 0, 0, $destWidth, $destHeight, $srcWidth, $srcHeight); + } - // Sauvegarde de l'image destination - $valeurs['fichier_dest'] = $vignette = "$destination.$destFormat"; - $valeurs['format_dest'] = $format = $destFormat; - _image_gd_output($destImage,$valeurs); + // Sauvegarde de l'image destination + $valeurs['fichier_dest'] = $vignette = "$destination.$destFormat"; + $valeurs['format_dest'] = $format = $destFormat; + _image_gd_output($destImage, $valeurs); - if ($srcImage) - ImageDestroy($srcImage); - ImageDestroy($destImage); + if ($srcImage) { + ImageDestroy($srcImage); } + ImageDestroy($destImage); } + $size = @getimagesize($vignette); // Gaffe: en safe mode, pas d'acces a la vignette, // donc risque de balancer "width='0'", ce qui masque l'image sous MSIE - if ($size[0] < 1) $size[0] = $destWidth; - if ($size[1] < 1) $size[1] = $destHeight; - + if ($size[0] < 1) { + $size[0] = $destWidth; + } + if ($size[1] < 1) { + $size[1] = $destHeight; + } + $retour['width'] = $largeur = $size[0]; $retour['height'] = $hauteur = $size[1]; - + $retour['fichier'] = $vignette; $retour['format'] = $format; $retour['date'] = @filemtime($vignette); - + // renvoyer l'image return $retour; } -// Calculer le ratio -// http://doc.spip.org/@image_ratio -function _image_ratio ($srcWidth, $srcHeight, $maxWidth, $maxHeight) { - $ratioWidth = $srcWidth/$maxWidth; - $ratioHeight = $srcHeight/$maxHeight; - - if ($ratioWidth <=1 AND $ratioHeight <=1) { +/** + * Réduire des dimensions en respectant un ratio + * + * Réduit des dimensions (hauteur, largeur) pour qu'elles + * soient incluses dans une hauteur et largeur maximum fournies + * en respectant la proportion d'origine + * + * @example `image_ratio(1000, 1000, 100, 10)` donne `array(10, 10, 100)` + * @see ratio_passe_partout() Assez proche. + * + * @param int $srcWidth Largeur de l'image source + * @param int $srcHeight Hauteur de l'image source + * @param int $maxWidth Largeur maximum souhaitée + * @param int $maxHeight Hauteur maximum souhaitée + * @return array Liste [ largeur, hauteur, ratio de réduction ] + **/ +function _image_ratio($srcWidth, $srcHeight, $maxWidth, $maxHeight) { + $ratioWidth = $srcWidth / $maxWidth; + $ratioHeight = $srcHeight / $maxHeight; + + if ($ratioWidth <= 1 and $ratioHeight <= 1) { $destWidth = $srcWidth; $destHeight = $srcHeight; - } else if ($ratioWidth < $ratioHeight) { - $destWidth = $srcWidth/$ratioHeight; + } elseif ($ratioWidth < $ratioHeight) { + $destWidth = $srcWidth / $ratioHeight; $destHeight = $maxHeight; - } - else { + } else { $destWidth = $maxWidth; - $destHeight = $srcHeight/$ratioWidth; + $destHeight = $srcHeight / $ratioWidth; } - return array (ceil($destWidth), ceil($destHeight), - max($ratioWidth,$ratioHeight)); + + return array( + ceil($destWidth), + ceil($destHeight), + max($ratioWidth, $ratioHeight) + ); } -// Calculer le ratio ajuste sur la plus petite dimension -// http://doc.spip.org/@ratio_passe_partout -function ratio_passe_partout ($srcWidth, $srcHeight, $maxWidth, $maxHeight) { - $ratioWidth = $srcWidth/$maxWidth; - $ratioHeight = $srcHeight/$maxHeight; +/** + * Réduire des dimensions en respectant un ratio sur la plus petite dimension + * + * Réduit des dimensions (hauteur, largeur) pour qu'elles + * soient incluses dans la plus grande hauteur ou largeur maximum fournie + * en respectant la proportion d'origine + * + * @example `ratio_passe_partout(1000, 1000, 100, 10)` donne `array(100, 100, 10)` + * @see _image_ratio() Assez proche. + * + * @param int $srcWidth Largeur de l'image source + * @param int $srcHeight Hauteur de l'image source + * @param int $maxWidth Largeur maximum souhaitée + * @param int $maxHeight Hauteur maximum souhaitée + * @return array Liste [ largeur, hauteur, ratio de réduction ] + **/ +function ratio_passe_partout($srcWidth, $srcHeight, $maxWidth, $maxHeight) { + $ratioWidth = $srcWidth / $maxWidth; + $ratioHeight = $srcHeight / $maxHeight; - if ($ratioWidth <=1 AND $ratioHeight <=1) { + if ($ratioWidth <= 1 and $ratioHeight <= 1) { $destWidth = $srcWidth; $destHeight = $srcHeight; - } else if ($ratioWidth > $ratioHeight) { - $destWidth = $srcWidth/$ratioHeight; + } elseif ($ratioWidth > $ratioHeight) { + $destWidth = $srcWidth / $ratioHeight; $destHeight = $maxHeight; - } - else { + } else { $destWidth = $maxWidth; - $destHeight = $srcHeight/$ratioWidth; + $destHeight = $srcHeight / $ratioWidth; } - return array (ceil($destWidth), ceil($destHeight), - min($ratioWidth,$ratioHeight)); + + return array( + ceil($destWidth), + ceil($destHeight), + min($ratioWidth, $ratioHeight) + ); } -// http://doc.spip.org/@process_image_reduire -function process_image_reduire($fonction,$img,$taille,$taille_y,$force,$cherche_image,$process){ + +/** + * Réduit une image + * + * @uses extraire_attribut() + * @uses inserer_attribut() + * @uses _image_valeurs_trans() + * @uses _image_ratio() + * @uses _image_tag_changer_taille() + * @uses _image_ecrire_tag() + * @uses _image_creer_vignette() + * + * @param array $fonction + * Un tableau à 2 éléments : + * 1) string : indique le nom du filtre de traitement demandé (par exemple : `image_reduire`) ; + * 2) array : tableau reprenant la valeur de `$img` et chacun des arguments passés au filtre utilisé. + * @param string $img + * Chemin de l'image ou texte contenant une balise img + * @param int $taille + * Largeur désirée + * @param int $taille_y + * Hauteur désirée + * @param bool $force + * @param string $process + * Librairie graphique à utiliser (gd1, gd2, netpbm, convert, imagick). + * AUTO utilise la librairie sélectionnée dans la configuration. + * @return string + * Code HTML de la balise img produite + **/ +function process_image_reduire($fonction, $img, $taille, $taille_y, $force, $process = 'AUTO') { $image = false; - if (($process == 'AUTO') AND isset($GLOBALS['meta']['image_process'])) + if (($process == 'AUTO') and isset($GLOBALS['meta']['image_process'])) { $process = $GLOBALS['meta']['image_process']; + } # determiner le format de sortie $format_sortie = false; // le choix par defaut sera bon - if ($process == "netpbm") $format_sortie = "jpg"; - else if ($process == 'gd1' OR $process == 'gd2') { - $image = _image_valeurs_trans($img, "reduire-{$taille}-{$taille_y}",$format_sortie,$fonction); + if ($process == "netpbm") { + $format_sortie = "jpg"; + } elseif ($process == 'gd1' or $process == 'gd2') { + $image = _image_valeurs_trans($img, "reduire-{$taille}-{$taille_y}", $format_sortie, $fonction); // on verifie que l'extension choisie est bonne (en principe oui) - $gd_formats = explode(',',$GLOBALS['meta']["gd_formats"]); - if (!in_array($image['format_dest'],$gd_formats) - OR ($image['format_dest']=='gif' AND !function_exists('ImageGif')) - ) { - if ($image['format_source'] == 'jpg') - $formats_sortie = array('jpg','png','gif'); - else // les gif sont passes en png preferentiellement pour etre homogene aux autres filtres images - $formats_sortie = array('png','jpg','gif'); + $gd_formats = explode(',', $GLOBALS['meta']["gd_formats"]); + if (is_array($image) + and (!in_array($image['format_dest'], $gd_formats) + or ($image['format_dest'] == 'gif' and !function_exists('ImageGif')) + ) + ) { + if ($image['format_source'] == 'jpg') { + $formats_sortie = array('jpg', 'png', 'gif'); + } else // les gif sont passes en png preferentiellement pour etre homogene aux autres filtres images + { + $formats_sortie = array('png', 'jpg', 'gif'); + } // Choisir le format destination // - on sauve de preference en JPEG (meilleure compression) // - pour le GIF : les GD recentes peuvent le lire mais pas l'ecrire @@ -970,8 +1292,9 @@ function process_image_reduire($fonction,$img,$taille,$taille_y,$force,$cherche_ $format_sortie = ""; foreach ($formats_sortie as $fmt) { if (in_array($fmt, $gd_formats)) { - if ($fmt <> "gif" OR function_exists('ImageGif')) + if ($fmt <> "gif" or function_exists('ImageGif')) { $format_sortie = $fmt; + } break; } } @@ -979,16 +1302,19 @@ function process_image_reduire($fonction,$img,$taille,$taille_y,$force,$cherche_ } } - if (!$image) - $image = _image_valeurs_trans($img, "reduire-{$taille}-{$taille_y}",$format_sortie,$fonction); + if (!is_array($image)) { + $image = _image_valeurs_trans($img, "reduire-{$taille}-{$taille_y}", $format_sortie, $fonction); + } - if (!$image OR !$image['largeur'] OR !$image['hauteur']){ + if (!is_array($image) or !$image['largeur'] or !$image['hauteur']) { spip_log("image_reduire_src:pas de version locale de $img"); // on peut resizer en mode html si on dispose des elements if ($srcw = extraire_attribut($img, 'width') - AND $srch = extraire_attribut($img, 'height')) { - list($w,$h) = _image_ratio($srcw, $srch, $taille, $taille_y); - return _image_tag_changer_taille($img,$w,$h); + and $srch = extraire_attribut($img, 'height') + ) { + list($w, $h) = _image_ratio($srcw, $srch, $taille, $taille_y); + + return _image_tag_changer_taille($img, $w, $h); } // la on n'a pas d'infos sur l'image source... on refile le truc a css // sous la forme style='max-width: NNpx;' @@ -997,22 +1323,25 @@ function process_image_reduire($fonction,$img,$taille,$taille_y,$force,$cherche_ } // si l'image est plus petite que la cible retourner une copie cachee de l'image - if (($image['largeur']<=$taille)&&($image['hauteur']<=$taille_y)){ - if ($image['creer']){ + if (($image['largeur'] <= $taille) && ($image['hauteur'] <= $taille_y)) { + if ($image['creer']) { @copy($image['fichier'], $image['fichier_dest']); } - return _image_ecrire_tag($image,array('src'=>$image['fichier_dest'])); + + return _image_ecrire_tag($image, array('src' => $image['fichier_dest'])); } - if ($image['creer']==false && !$force) - return _image_ecrire_tag($image,array('src'=>$image['fichier_dest'],'width'=>$image['largeur_dest'],'height'=>$image['hauteur_dest'])); + if ($image['creer'] == false && !$force) { + return _image_ecrire_tag($image, + array('src' => $image['fichier_dest'], 'width' => $image['largeur_dest'], 'height' => $image['hauteur_dest'])); + } - if (in_array($image["format_source"],array('jpg','gif','png'))){ + if (in_array($image["format_source"], array('jpg', 'gif', 'png'))) { $destWidth = $image['largeur_dest']; $destHeight = $image['hauteur_dest']; $logo = $image['fichier']; $date = $image["date_src"]; - $preview = _image_creer_vignette($image, $taille, $taille_y,$process,$force); + $preview = _image_creer_vignette($image, $taille, $taille_y, $process, $force); if ($preview && $preview['fichier']) { $logo = $preview['fichier']; @@ -1024,25 +1353,30 @@ function process_image_reduire($fonction,$img,$taille,$taille_y,$force,$cherche_ // de l'image, de facon a tromper le cache du navigateur // quand on fait supprimer/reuploader un logo // (pas de filemtime si SAFE MODE) - $date = test_espace_prive() ? ('?'.$date) : ''; - return _image_ecrire_tag($image,array('src'=>"$logo$date",'width'=>$destWidth,'height'=>$destHeight)); - } - else - # SVG par exemple ? BMP, tiff ... les redacteurs osent tout! + $date = test_espace_prive() ? ('?' . $date) : ''; + + return _image_ecrire_tag($image, array('src' => "$logo$date", 'width' => $destWidth, 'height' => $destHeight)); + } else # SVG par exemple ? BMP, tiff ... les redacteurs osent tout! + { return $img; + } } /** * Produire des fichiers au format .ico - * avec du code recupere de : - * phpThumb() by James Heinrich - * available at http://phpthumb.sourceforge.net + * + * Avec du code récupéré de phpThumb() + * + * @author James Heinrich + * @link http://phpthumb.sourceforge.net * * Class phpthumb_functions */ class phpthumb_functions { /** + * Retourne la couleur d'un pixel dans une image + * * @param ressource $img * @param int $x * @param int $y @@ -1052,34 +1386,42 @@ class phpthumb_functions { if (!is_resource($img)) { return false; } + return @ImageColorsForIndex($img, @ImageColorAt($img, $x, $y)); } /** + * Retourne un nombre dans une représentation en Little Endian + * * @param int $number * @param int $minbytes * @return string */ - public static function LittleEndian2String($number, $minbytes=1) { + public static function LittleEndian2String($number, $minbytes = 1) { $intstring = ''; while ($number > 0) { - $intstring = $intstring.chr($number & 255); + $intstring = $intstring . chr($number & 255); $number >>= 8; } + return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT); } /** + * Transforme une ressource GD en image au format ICO + * * @param array $gd_image_array + * Tableau de ressources d'images GD * @return string + * Image au format ICO */ public static function GD2ICOstring(&$gd_image_array) { foreach ($gd_image_array as $key => $gd_image) { - $ImageWidths[$key] = ImageSX($gd_image); + $ImageWidths[$key] = ImageSX($gd_image); $ImageHeights[$key] = ImageSY($gd_image); - $bpp[$key] = ImageIsTrueColor($gd_image) ? 32 : 24; - $totalcolors[$key] = ImageColorsTotal($gd_image); + $bpp[$key] = ImageIsTrueColor($gd_image) ? 32 : 24; + $totalcolors[$key] = ImageColorsTotal($gd_image); $icXOR[$key] = ''; for ($y = $ImageHeights[$key] - 1; $y >= 0; $y--) { @@ -1091,9 +1433,9 @@ class phpthumb_functions { $b = $argb['blue']; if ($bpp[$key] == 32) { - $icXOR[$key] .= chr($b).chr($g).chr($r).chr($a); + $icXOR[$key] .= chr($b) . chr($g) . chr($r) . chr($a); } elseif ($bpp[$key] == 24) { - $icXOR[$key] .= chr($b).chr($g).chr($r); + $icXOR[$key] .= chr($b) . chr($g) . chr($r); } if ($a < 128) { @@ -1120,43 +1462,45 @@ class phpthumb_functions { $biSizeImage = $ImageWidths[$key] * $ImageHeights[$key] * ($bpp[$key] / 8); // BITMAPINFOHEADER - 40 bytes - $BitmapInfoHeader[$key] = ''; - $BitmapInfoHeader[$key] .= "\x28\x00\x00\x00"; // DWORD biSize; - $BitmapInfoHeader[$key] .= phpthumb_functions::LittleEndian2String($ImageWidths[$key], 4); // LONG biWidth; + $BitmapInfoHeader[$key] = ''; + $BitmapInfoHeader[$key] .= "\x28\x00\x00\x00"; // DWORD biSize; + $BitmapInfoHeader[$key] .= phpthumb_functions::LittleEndian2String($ImageWidths[$key], 4); // LONG biWidth; // The biHeight member specifies the combined // height of the XOR and AND masks. $BitmapInfoHeader[$key] .= phpthumb_functions::LittleEndian2String($ImageHeights[$key] * 2, 4); // LONG biHeight; - $BitmapInfoHeader[$key] .= "\x01\x00"; // WORD biPlanes; - $BitmapInfoHeader[$key] .= chr($bpp[$key])."\x00"; // wBitCount; - $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // DWORD biCompression; - $BitmapInfoHeader[$key] .= phpthumb_functions::LittleEndian2String($biSizeImage, 4); // DWORD biSizeImage; - $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // LONG biXPelsPerMeter; - $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // LONG biYPelsPerMeter; - $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // DWORD biClrUsed; - $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // DWORD biClrImportant; + $BitmapInfoHeader[$key] .= "\x01\x00"; // WORD biPlanes; + $BitmapInfoHeader[$key] .= chr($bpp[$key]) . "\x00"; // wBitCount; + $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // DWORD biCompression; + $BitmapInfoHeader[$key] .= phpthumb_functions::LittleEndian2String($biSizeImage, 4); // DWORD biSizeImage; + $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // LONG biXPelsPerMeter; + $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // LONG biYPelsPerMeter; + $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // DWORD biClrUsed; + $BitmapInfoHeader[$key] .= "\x00\x00\x00\x00"; // DWORD biClrImportant; } - $icondata = "\x00\x00"; // idReserved; // Reserved (must be 0) - $icondata .= "\x01\x00"; // idType; // Resource Type (1 for icons) + $icondata = "\x00\x00"; // idReserved; // Reserved (must be 0) + $icondata .= "\x01\x00"; // idType; // Resource Type (1 for icons) $icondata .= phpthumb_functions::LittleEndian2String(count($gd_image_array), 2); // idCount; // How many images? $dwImageOffset = 6 + (count($gd_image_array) * 16); foreach ($gd_image_array as $key => $gd_image) { // ICONDIRENTRY idEntries[1]; // An entry for each image (idCount of 'em) - $icondata .= chr($ImageWidths[$key]); // bWidth; // Width, in pixels, of the image - $icondata .= chr($ImageHeights[$key]); // bHeight; // Height, in pixels, of the image - $icondata .= chr($totalcolors[$key]); // bColorCount; // Number of colors in image (0 if >=8bpp) - $icondata .= "\x00"; // bReserved; // Reserved ( must be 0) + $icondata .= chr($ImageWidths[$key]); // bWidth; // Width, in pixels, of the image + $icondata .= chr($ImageHeights[$key]); // bHeight; // Height, in pixels, of the image + $icondata .= chr($totalcolors[$key]); // bColorCount; // Number of colors in image (0 if >=8bpp) + $icondata .= "\x00"; // bReserved; // Reserved ( must be 0) - $icondata .= "\x01\x00"; // wPlanes; // Color Planes - $icondata .= chr($bpp[$key])."\x00"; // wBitCount; // Bits per pixel + $icondata .= "\x01\x00"; // wPlanes; // Color Planes + $icondata .= chr($bpp[$key]) . "\x00"; // wBitCount; // Bits per pixel $dwBytesInRes = 40 + strlen($icXOR[$key]) + strlen($icAND[$key]); - $icondata .= phpthumb_functions::LittleEndian2String($dwBytesInRes, 4); // dwBytesInRes; // How many bytes in this resource? + $icondata .= phpthumb_functions::LittleEndian2String($dwBytesInRes, + 4); // dwBytesInRes; // How many bytes in this resource? - $icondata .= phpthumb_functions::LittleEndian2String($dwImageOffset, 4); // dwImageOffset; // Where in the file is this image? + $icondata .= phpthumb_functions::LittleEndian2String($dwImageOffset, + 4); // dwImageOffset; // Where in the file is this image? $dwImageOffset += strlen($BitmapInfoHeader[$key]); $dwImageOffset += strlen($icXOR[$key]); $dwImageOffset += strlen($icAND[$key]); @@ -1172,5 +1516,3 @@ class phpthumb_functions { } } - -?>