From ba3ebcf28a6102a938621e0f6b87340bb310acf9 Mon Sep 17 00:00:00 2001
From: Cerdic <cedric@yterium.com>
Date: Tue, 9 Dec 2008 16:27:53 +0000
Subject: [PATCH] report de [13428] [13429] [13430] [13431]

---
 .gitattributes                        |    2 +-
 ecrire/inc/filtres.php                |   40 +-
 ecrire/inc/filtres_images.php         | 3128 +++++++++++++++++++------
 ecrire/inc/filtres_images_etendus.php | 2543 --------------------
 ecrire/inc/filtres_images_mini.php    |  825 +++++++
 ecrire/inc/formater_article.php       |    2 +-
 ecrire/inc/forum.php                  |    2 +-
 ecrire/inc/iconifier.php              |    2 +-
 ecrire/inc/informer.php               |    2 +-
 ecrire/inc/informer_auteur.php        |    2 +-
 ecrire/inc/plugin.php                 |    2 +-
 ecrire/inc/presenter_enfants.php      |    2 +-
 prive/formulaires/login.php           |    2 +-
 13 files changed, 3277 insertions(+), 3277 deletions(-)
 delete mode 100644 ecrire/inc/filtres_images_etendus.php
 create mode 100644 ecrire/inc/filtres_images_mini.php

diff --git a/.gitattributes b/.gitattributes
index 6fe16de5d1..d5c382f7df 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -239,7 +239,7 @@ ecrire/inc/editer_mots.php -text
 ecrire/inc/envoyer_mail.php -text
 ecrire/inc/export.php -text
 ecrire/inc/filtres_images.php -text
-ecrire/inc/filtres_images_etendus.php -text
+ecrire/inc/filtres_images_mini.php -text
 ecrire/inc/filtres_mini.php -text
 ecrire/inc/formater_article.php -text
 ecrire/inc/formater_auteur.php -text
diff --git a/ecrire/inc/filtres.php b/ecrire/inc/filtres.php
index cdbe693336..4c5e22b0ff 100644
--- a/ecrire/inc/filtres.php
+++ b/ecrire/inc/filtres.php
@@ -169,26 +169,26 @@ $GLOBALS['spip_matrice']['image_valeurs_trans'] = true;
 $GLOBALS['spip_matrice']['image_graver'] = true;
 $GLOBALS['spip_matrice']['image_reduire'] = true;
 $GLOBALS['spip_matrice']['image_reduire_par'] = true;
-$GLOBALS['spip_matrice']['image_recadre'] = 'inc/filtres_images_etendus.php';
-$GLOBALS['spip_matrice']['image_alpha'] = 'inc/filtres_images_etendus.php';
-$GLOBALS['spip_matrice']['image_flip_vertical'] = 'inc/filtres_images_etendus.php';
-$GLOBALS['spip_matrice']['image_flip_horizontal'] = 'inc/filtres_images_etendus.php';
-$GLOBALS['spip_matrice']['image_masque'] = 'inc/filtres_images_etendus.php';
-$GLOBALS['spip_matrice']['image_nb'] = 'inc/filtres_images_etendus.php';
-$GLOBALS['spip_matrice']['image_flou'] = 'inc/filtres_images_etendus.php';
-$GLOBALS['spip_matrice']['image_RotateBicubic'] = 'inc/filtres_images_etendus.php';
-$GLOBALS['spip_matrice']['image_rotation'] = 'inc/filtres_images_etendus.php';
-$GLOBALS['spip_matrice']['image_distance_pixel'] = 'inc/filtres_images_etendus.php';
-$GLOBALS['spip_matrice']['image_decal_couleur'] = 'inc/filtres_images_etendus.php';
-$GLOBALS['spip_matrice']['image_gamma'] = 'inc/filtres_images_etendus.php';
-$GLOBALS['spip_matrice']['image_decal_couleur_127'] = 'inc/filtres_images_etendus.php';
-$GLOBALS['spip_matrice']['image_sepia'] = 'inc/filtres_images_etendus.php';
-$GLOBALS['spip_matrice']['image_aplatir'] = 'inc/filtres_images_etendus.php';
-$GLOBALS['spip_matrice']['image_format'] = 'inc/filtres_images_etendus.php';
-$GLOBALS['spip_matrice']['image_couleur_extraire'] = 'inc/filtres_images_etendus.php';
+$GLOBALS['spip_matrice']['image_recadre'] = 'inc/filtres_images.php';
+$GLOBALS['spip_matrice']['image_alpha'] = 'inc/filtres_images.php';
+$GLOBALS['spip_matrice']['image_flip_vertical'] = 'inc/filtres_images.php';
+$GLOBALS['spip_matrice']['image_flip_horizontal'] = 'inc/filtres_images.php';
+$GLOBALS['spip_matrice']['image_masque'] = 'inc/filtres_images.php';
+$GLOBALS['spip_matrice']['image_nb'] = 'inc/filtres_images.php';
+$GLOBALS['spip_matrice']['image_flou'] = 'inc/filtres_images.php';
+$GLOBALS['spip_matrice']['image_RotateBicubic'] = 'inc/filtres_images.php';
+$GLOBALS['spip_matrice']['image_rotation'] = 'inc/filtres_images.php';
+$GLOBALS['spip_matrice']['image_distance_pixel'] = 'inc/filtres_images.php';
+$GLOBALS['spip_matrice']['image_decal_couleur'] = 'inc/filtres_images.php';
+$GLOBALS['spip_matrice']['image_gamma'] = 'inc/filtres_images.php';
+$GLOBALS['spip_matrice']['image_decal_couleur_127'] = 'inc/filtres_images.php';
+$GLOBALS['spip_matrice']['image_sepia'] = 'inc/filtres_images.php';
+$GLOBALS['spip_matrice']['image_aplatir'] = 'inc/filtres_images.php';
+$GLOBALS['spip_matrice']['image_format'] = 'inc/filtres_images.php';
+$GLOBALS['spip_matrice']['image_couleur_extraire'] = 'inc/filtres_images.php';
 $GLOBALS['spip_matrice']['image_select'] = true;
-$GLOBALS['spip_matrice']['image_renforcement'] = 'inc/filtres_images_etendus.php';
-$GLOBALS['spip_matrice']['image_imagick'] = 'inc/filtres_images_etendus.php';
+$GLOBALS['spip_matrice']['image_renforcement'] = 'inc/filtres_images.php';
+$GLOBALS['spip_matrice']['image_imagick'] = 'inc/filtres_images.php';
 $GLOBALS['spip_matrice']['image_ramasse_miettes'] = true;
 $GLOBALS['spip_matrice']['image_passe_partout'] = true;
 
@@ -233,7 +233,7 @@ function image_filtrer($args){
 	$filtre = array_shift($args); # enlever $filtre
 	$texte = array_shift($args);
 	if (!strlen($texte)) return;
-	find_in_path('filtres_images.php','inc/', true);
+	find_in_path('filtres_images_mini.php','inc/', true);
 	statut_effacer_images_temporaires(true); // activer la suppression des images temporaires car le compilo finit la chaine par un image_graver
 	// Cas du nom de fichier local
 	if ( strpos(substr($texte,strlen(_DIR_RACINE)),'..')===FALSE
diff --git a/ecrire/inc/filtres_images.php b/ecrire/inc/filtres_images.php
index a05e31eb53..a81dc0c351 100644
--- a/ecrire/inc/filtres_images.php
+++ b/ecrire/inc/filtres_images.php
@@ -1,5 +1,4 @@
 <?php
-
 /***************************************************************************\
  *  SPIP, Systeme de publication pour l'internet                           *
  *                                                                         *
@@ -10,816 +9,2535 @@
  *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
 \***************************************************************************/
 
+include_spip('inc/filtres_images_mini');
+
+// Transforme l'image en PNG transparent
+// alpha = 0: aucune transparence
+// alpha = 127: completement transparent
+// http://doc.spip.org/@image_alpha
+function image_alpha($im, $alpha = 63)
+{
+	$fonction = array('image_alpha', func_get_args());
+	$image = image_valeurs_trans($im, "alpha-$alpha", "png",$fonction);
+	if (!$image) return("");
+	
+	$x_i = $image["largeur"];
+	$y_i = $image["hauteur"];
+	
+	$im = $image["fichier"];
+	$dest = $image["fichier_dest"];
+	
+	$creer = $image["creer"];
+	
+	if ($creer) {
+		// Creation de l'image en deux temps
+		// de facon a conserver les GIF transparents
+		$im = $image["fonction_imagecreatefrom"]($im);
+		imagepalettetotruecolor($im);
+		$im2 = imagecreatetruecolor($x_i, $y_i);
+		@imagealphablending($im2, false);
+		@imagesavealpha($im2,true);
+		$color_t = ImageColorAllocateAlpha( $im2, 255, 255, 255 , 127 );
+		imagefill ($im2, 0, 0, $color_t);
+		imagecopy($im2, $im, 0, 0, 0, 0, $x_i, $y_i);
+
+		$im_ = imagecreatetruecolor($x_i, $y_i);
+		imagealphablending ($im_, FALSE );
+		imagesavealpha ( $im_, TRUE );
+
+
+
+		for ($x = 0; $x < $x_i; $x++) {
+			for ($y = 0; $y < $y_i; $y++) {
+				$rgb = ImageColorAt($im2, $x, $y);
+				
+				if (function_exists('imagecolorallocatealpha')) {
+					$a = ($rgb >> 24) & 0xFF;
+					$r = ($rgb >> 16) & 0xFF;
+					$g = ($rgb >> 8) & 0xFF;
+					$b = $rgb & 0xFF;
+					
+					
+					$a_ = $alpha + $a - round($a*$alpha/127);
+					$rgb = imagecolorallocatealpha($im_, $r, $g, $b, $a_);
+				}
+				imagesetpixel ( $im_, $x, $y, $rgb );
+			}
+		}
+		image_gd_output($im_,$image);
+		imagedestroy($im_);
+		imagedestroy($im);
+		imagedestroy($im2);
+	}
+	
 
-if (!defined("_ECRIRE_INC_VERSION")) return;
-include_spip('inc/filtres'); // par precaution
-
-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;
+	return image_ecrire_tag($image,array('src'=>$dest));
+	
 }
 
-// http://doc.spip.org/@cherche_image_nommee
-function cherche_image_nommee($nom, $formats = array ('gif', 'jpg', 'png')) {
+// http://doc.spip.org/@image_recadre
+function image_recadre($im,$width,$height,$position='center', $background_color='white')
+{
+	$fonction = array('image_recadre', func_get_args());
+	$image = image_valeurs_trans($im, "recadre-$width-$height-$position-$background_color",false,$fonction);
+	
+	if (!$image) return("");
+	
+	$x_i = $image["largeur"];
+	$y_i = $image["hauteur"];
+	
+	if ($width==0) $width=$x_i;
+	if ($height==0) $height=$y_i;
+	
+	$offset_width = $x_i-$width;
+	$offset_height = $y_i-$height;
+	$position=strtolower($position);
+	if (strpos($position,'left')!==FALSE){
+		if (preg_match(';left=(\d{1}\d+);', $position, $left)){
+			$offset_width=$left[1];	
+		}
+		else{
+			$offset_width=0;
+		}
+	}
+	elseif (strpos($position,'right')!==FALSE)
+		$offset_width=$offset_width;
+	else
+		$offset_width=intval(ceil($offset_width/2));
 
-	if (strncmp(_DIR_IMG, $nom,$n=strlen(_DIR_IMG))==0) {
-		$nom = substr($nom,$n);
-	} else 	if (strncmp(_DIR_IMG_PACK, $nom,$n=strlen(_DIR_IMG_PACK))==0) {
-		$nom = substr($nom,$n);
-	} else if (strncmp(_DIR_IMG_ICONE_DIST, $nom,$n=strlen(_DIR_IMG_ICONES_DIST))==0) {
-		$nom = substr($nom,$n);
+	if (strpos($position,'top')!==FALSE){
+		if (preg_match(';top=(\d{1}\d+);', $position, $top)){
+			$offset_height=$top[1];
+		}
+		else{
+			$offset_height=0;
+		}
 	}
-	$pos = strrpos($nom, "/");
-	if ($pos > 0) {
-		$chemin = substr($nom, 0, $pos+1);
-		$nom = substr($nom, $pos+1);
-	} else {
-		$chemin = "";
+	elseif (strpos($position,'bottom')!==FALSE)
+		$offset_height=$offset_height;
+	else
+		$offset_height=intval(ceil($offset_height/2));
+	
+	$im = $image["fichier"];
+	$dest = $image["fichier_dest"];
+	
+	$creer = $image["creer"];
+	
+	if ($creer) {
+		$im = $image["fonction_imagecreatefrom"]($im);
+		imagepalettetotruecolor($im);
+		$im_ = imagecreatetruecolor($width, $height);
+		@imagealphablending($im_, false);
+		@imagesavealpha($im_,true);
+
+		if ($background_color=='transparent')
+			$color_t = imagecolorallocatealpha( $im_, 255, 255, 255 , 127 );
+		else {
+			$bg = couleur_hex_to_dec($background_color);
+			$color_t = imagecolorallocate( $im_, $bg['red'], $bg['green'], $bg['blue']);
+		}
+		imagefill ($im_, 0, 0, $color_t);
+		imagecopy($im_, $im, max(0,-$offset_width), max(0,-$offset_height), max(0,$offset_width), max(0,$offset_height), min($width,$x_i), min($height,$y_i));
+
+		image_gd_output($im_,$image);
+		imagedestroy($im_);
+		imagedestroy($im);
 	}
+	
+	return image_ecrire_tag($image,array('src'=>$dest,'width'=>$width,'height'=>$height));
+}
+
+// http://doc.spip.org/@image_flip_vertical
+function image_flip_vertical($im)
+{
+	$fonction = array('image_flip_vertical', func_get_args());
+	$image = image_valeurs_trans($im, "flip_v", false,$fonction);
+	if (!$image) return("");
+	
+	$x_i = $image["largeur"];
+	$y_i = $image["hauteur"];
+	
+	$im = $image["fichier"];
+	$dest = $image["fichier_dest"];
+	
+	$creer = $image["creer"];
+	
+	if ($creer) {
+		$im = $image["fonction_imagecreatefrom"]($im);
+		imagepalettetotruecolor($im);
+		$im_ = imagecreatetruecolor($x_i, $y_i);
+		@imagealphablending($im_, false);
+		@imagesavealpha($im_,true);
+	
+		$color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
+		imagefill ($im_, 0, 0, $color_t);
 
-	reset($formats);
-	while (list(, $format) = each($formats)) {
-		if (@file_exists(_DIR_IMG . "$chemin$nom.$format")){ 
-			return array((_DIR_IMG . $chemin), $nom, $format);
-		} else if (@file_exists(_DIR_IMG_PACK . "$chemin$nom.$format")){ 
-			return array((_DIR_IMG_PACK . $chemin), $nom, $format);
-		} else if (@file_exists(_DIR_IMG_ICONES_DIST . "$chemin$nom.$format")){ 
-			return array((_DIR_IMG_ICONES_DIST . $chemin), $nom, $format);
+		for ($x = 0; $x < $x_i; $x++) {
+			for ($y = 0; $y < $y_i; $y++) {
+				imagecopy($im_, $im, $x_i - $x - 1, $y, $x, $y, 1, 1);
+			}
 		}
+
+		image_gd_output($im_,$image);
+		imagedestroy($im_);
+		imagedestroy($im);
 	}
+	
+	return image_ecrire_tag($image,array('src'=>$dest));
 }
 
-// Fonctions de traitement d'image
-// uniquement pour GD2
-// http://doc.spip.org/@image_valeurs_trans
-function image_valeurs_trans($img, $effet, $forcer_format = false, $fonction_creation = NULL) {
-	static $images_recalcul = array();
-	if (strlen($img)==0) return false;
+// http://doc.spip.org/@image_flip_horizontal
+function image_flip_horizontal($im)
+{
+	$fonction = array('image_flip_horizontal', func_get_args());
+	$image = image_valeurs_trans($im, "flip_h",false,$fonction);
+	if (!$image) return("");
 	
-	$source = trim(extraire_attribut($img, 'src'));
-	if (strlen($source) < 1){
-		$source = $img;
-		$img = "<img src='$source' />";
-	}
+	$x_i = $image["largeur"];
+	$y_i = $image["hauteur"];
+	
+	$im = $image["fichier"];
+	$dest = $image["fichier_dest"];
+	
+	$creer = $image["creer"];
+	
+	if ($creer) {
+		$im = $image["fonction_imagecreatefrom"]($im);
+		imagepalettetotruecolor($im);
+		$im_ = imagecreatetruecolor($x_i, $y_i);
+		@imagealphablending($im_, false);
+		@imagesavealpha($im_,true);
+	
+		$color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
+		imagefill ($im_, 0, 0, $color_t);
 
-	// les protocoles web prennent au moins 3 lettres
-	if (preg_match(';^(\w{3,7}://);', $source)){
-		include_spip('inc/distant');
-		$fichier = _DIR_RACINE . copie_locale($source);
-		if (!$fichier) return "";
-	}	else {
-		// enlever le timestamp eventuel
-		$source=preg_replace(',[?][0-9]+$,','',$source);
-		$fichier = $source;
+		for ($x = 0; $x < $x_i; $x++) {
+			for ($y = 0; $y < $y_i; $y++) {
+   				imagecopy($im_, $im, $x, $y_i - $y - 1, $x, $y, 1, 1);
+			}
+		}
+		image_gd_output($im_,$image);
+		imagedestroy($im_);
+		imagedestroy($im);
 	}
+	
+	return image_ecrire_tag($image,array('src'=>$dest));
+}
 
-	$terminaison_dest = "";
-	if (preg_match(",^(?>.*)(?<=\.(gif|jpg|png)),", $fichier, $regs)) {
-		$terminaison = $regs[1];
-		$terminaison_dest = $terminaison;
-		
-		if ($terminaison == "gif") $terminaison_dest = "png";
+// http://doc.spip.org/@image_masque
+function image_masque($im, $masque, $pos="") {
+	// Passer, en plus de l'image d'origine,
+	// une image de "masque": un fichier PNG24 transparent.
+	// Le decoupage se fera selon la transparence du "masque",
+	// et les couleurs seront eclaircies/foncees selon de couleur du masque.
+	// Pour ne pas modifier la couleur, le masque doit etre en gris 50%.
+	//
+	// Si l'image source est plus grande que le masque, alors cette image est reduite a la taille du masque.
+	// Sinon, c'est la taille de l'image source qui est utilisee.
+	//
+	// $pos est une variable libre, qui permet de passer left=..., right=..., bottom=..., top=...
+	// dans ce cas, le pasque est place a ces positions sur l'image d'origine,
+	// et evidemment cette image d'origine n'est pas redimensionnee
+	// 
+	// Positionnement horizontal: text-align=left, right, center
+	// Positionnement vertical : vertical-align: top, bottom, middle
+	// (les positionnements left, right, top, left sont relativement inutiles, mais coherence avec CSS)
+	//
+	// Choix du mode de fusion: mode=masque, normal, eclaircir, obscurcir, produit, difference
+	// masque: mode par defaut
+	// normal: place la nouvelle image par dessus l'ancienne
+	// eclaircir: place uniquement les points plus clairs
+	// obscurcir: place uniquement les points plus fonc'es
+	// produit: multiplie par le masque (points noirs rendent l'image noire, points blancs ne changent rien)
+	// difference: remplit avec l'ecart entre les couleurs d'origine et du masque
+
+	$mode = "masque";
+
+
+	$numargs = func_num_args();
+	$arg_list = func_get_args();
+	$texte = $arg_list[0];
+	for ($i = 1; $i < $numargs; $i++) {
+		if ( ($p = strpos($arg_list[$i],"=")) !==false) {
+			$nom_variable = substr($arg_list[$i], 0, $p);
+			$val_variable = substr($arg_list[$i], $p+1);
+			$variable["$nom_variable"] = $val_variable;
+			$defini["$nom_variable"] = 1;
+		}
 	}
-	if ($forcer_format!==false) $terminaison_dest = $forcer_format;
+	if ($defini["mode"]) $mode = $variable["mode"];
 
-	if (!$terminaison_dest) return false;
+	$masque = find_in_path($masque);
+	$pos = md5(serialize($variable).@filemtime($masque));
 
-	$term_fonction = $terminaison;
-	if ($term_fonction == "jpg") $term_fonction = "jpeg";
+	$fonction = array('image_masque', func_get_args());
+	$image = image_valeurs_trans($im, "masque-$masque-$pos", "png",$fonction);
+	if (!$image) return("");
 
-	$nom_fichier = substr($fichier, 0, strlen($fichier) - 4);
-	$fichier_dest = $nom_fichier;
+	$x_i = $image["largeur"];
+	$y_i = $image["hauteur"];
+	
+	$im = $image["fichier"];
+	$dest = $image["fichier_dest"];
 	
-	if (@file_exists($f = $fichier)){
-		list ($ret["hauteur"],$ret["largeur"]) = taille_image($img);
-		$date_src = @filemtime($f);
+	$creer = $image["creer"];
+
+
+	if ($defini["right"] OR $defini["left"] OR $defini["bottom"] OR $defini["top"] OR $defini["text-align"] OR $defini["vertical-align"]) {
+		$placer = true;
 	}
-	elseif (@file_exists($f = "$fichier.src")
-		AND lire_fichier($f,$valeurs)
-		AND $valeurs=unserialize($valeurs)) {
-		$ret["hauteur"] = $valeurs["hauteur_dest"];
-		$ret["largeur"] = $valeurs["largeur_dest"];
-		$date_src = $valeurs["date"];
+	else $placer = false;
+
+	if ($creer) {
+		
+		$mask = image_valeurs_trans($masque,"");
+		if (!is_array($mask)) return("");
+		$im_m = $mask["fichier"];
+		$x_m = $mask["largeur"];
+		$y_m = $mask["hauteur"];
+	
+		$im2 = $mask["fonction_imagecreatefrom"]($masque);
+		if ($mask["format_source"] == "gif" AND function_exists('ImageCopyResampled')) { 
+			$im2_ = imagecreatetruecolor($x_m, $y_m);
+			// Si un GIF est transparent, 
+			// fabriquer un PNG transparent  
+			// Conserver la transparence 
+			if (function_exists("imageAntiAlias")) imageAntiAlias($im2_,true); 
+			@imagealphablending($im2_, false); 
+			@imagesavealpha($im2_,true); 
+			@ImageCopyResampled($im2_, $im2, 0, 0, 0, 0, $x_m, $y_m, $x_m, $y_m);
+			imagedestroy($im2);
+			$im2 = $im2_;
+		}
+		
+		if ($placer) {
+			// On fabriquer une version "agrandie" du masque,
+			// aux dimensions de l'image source
+			// et on "installe" le masque dans cette image
+			// ainsi: aucun redimensionnement
+			
+			$dx = 0;
+			$dy = 0;
+			
+			if ($defini["right"]) {
+				$right = $variable["right"];
+				$dx = ($x_i - $x_m) - $right;
+			}
+			if ($defini["bottom"]) {
+				$bottom = $variable["bottom"];
+				$dy = ($y_i - $y_m) - $bottom;
+				}
+			if ($defini["top"]) {
+				$top = $variable["top"];
+				$dy = $top;
+			}
+			if ($defini["left"]) {
+				$left = $variable["left"];
+				$dx = $left;
+			}
+			if ($defini["text-align"]) {
+				$align = $variable["text-align"];
+				if ($align == "right") {
+					$right = 0;
+					$dx = ($x_i - $x_m);
+				} else if ($align == "left") {
+					$left = 0;
+					$dx = 0;
+				} else if ($align = "center") {
+					$dx = round( ($x_i - $x_m) / 2 ) ;
+				}
+			}
+			if ($defini["vertical-align"]) {
+				$valign = $variable["vertical-align"];
+				if ($valign == "bottom") {
+					$bottom = 0;
+					$dy = ($y_i - $y_m);
+				} else if ($valign == "top") {
+					$top = 0;
+					$dy = 0;
+				} else if ($valign = "middle") {
+					$dy = round( ($y_i - $y_m) / 2 ) ;
+				}
+			}
+			
+			
+			$im3 = imagecreatetruecolor($x_i, $y_i);
+			@imagealphablending($im3, false);
+			@imagesavealpha($im3,true);
+			if ($mode == "masque") $color_t = ImageColorAllocateAlpha( $im3, 128, 128, 128 , 0 );
+			else $color_t = ImageColorAllocateAlpha( $im3, 128, 128, 128 , 127 );
+			imagefill ($im3, 0, 0, $color_t);
+
+			
+
+			imagecopy ( $im3, $im2, $dx, $dy, 0, 0, $x_m, $y_m);	
+
+			imagedestroy($im2);
+			$im2 = imagecreatetruecolor($x_i, $y_i);
+			@imagealphablending($im2, false);
+			@imagesavealpha($im2,true);
+			
+			
+			
+			imagecopy ( $im2, $im3, 0, 0, 0, 0, $x_i, $y_i);			
+			imagedestroy($im3);
+			$x_m = $x_i;
+			$y_m = $y_i;
+		}
+		
+	
+		$rapport = $x_i / $x_m;
+		if (($y_i / $y_m) < $rapport ) {
+			$rapport = $y_i / $y_m;
+		}
+			
+		$x_d = ceil($x_i / $rapport);
+		$y_d = ceil($y_i / $rapport);
+		
+
+		if ($x_i < $x_m OR $y_i < $y_m) {
+			$x_dest = $x_i;
+			$y_dest = $y_i;
+			$x_dec = 0;
+			$y_dec = 0;
+		} else {
+			$x_dest = $x_m;
+			$y_dest = $y_m;
+			$x_dec = round(($x_d - $x_m) /2);
+			$y_dec = round(($y_d - $y_m) /2);
+		}
+
+
+		$nouveau = image_valeurs_trans(image_reduire($im, $x_d, $y_d),"");
+		if (!is_array($nouveau)) return("");
+		$im_n = $nouveau["fichier"];
+		
+	
+		$im = $nouveau["fonction_imagecreatefrom"]($im_n);
+		imagepalettetotruecolor($im);
+		if ($nouveau["format_source"] == "gif" AND function_exists('ImageCopyResampled')) { 
+			$im_ = imagecreatetruecolor($x_dest, $y_dest);
+			// Si un GIF est transparent, 
+			// fabriquer un PNG transparent  
+			// Conserver la transparence 
+			if (function_exists("imageAntiAlias")) imageAntiAlias($im_,true); 
+			@imagealphablending($im_, false); 
+			@imagesavealpha($im_,true); 
+			@ImageCopyResampled($im_, $im, 0, 0, 0, 0, $x_dest, $y_dest, $x_dest, $y_dest);
+			imagedestroy($im);
+			$im = $im_;
+		}
+		$im_ = imagecreatetruecolor($x_dest, $y_dest);
+		@imagealphablending($im_, false);
+		@imagesavealpha($im_,true);
+		$color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
+		imagefill ($im_, 0, 0, $color_t);
+
+
+		for ($x = 0; $x < $x_dest; $x++) {
+			for ($y=0; $y < $y_dest; $y++) {
+				$rgb = ImageColorAt($im2, $x, $y);
+				$a = ($rgb >> 24) & 0xFF;
+				$r = ($rgb >> 16) & 0xFF;
+				$g = ($rgb >> 8) & 0xFF;
+				$b = $rgb & 0xFF;
+				
+
+				$rgb2 = ImageColorAt($im, $x+$x_dec, $y+$y_dec);
+				$a2 = ($rgb2 >> 24) & 0xFF;
+				$r2 = ($rgb2 >> 16) & 0xFF;
+				$g2 = ($rgb2 >> 8) & 0xFF;
+				$b2 = $rgb2 & 0xFF;
+				
+				
+				
+				if ($mode == "normal") {
+					$v = (127 - $a) / 127;
+					if ($v == 1) {
+						$r_ = $r;
+						$g_ = $g;
+						$b_ = $b;
+					} else {
+						$v2 = (127 - $a2) / 127;
+						if ($v+$v2 == 0) {
+							$r_ = $r2;
+							$g_ = $g2;
+							$b_ = $b2;
+						} else if ($v2 ==0) {
+							$r_ = $r;
+							$g_ = $g;
+							$b_ = $b;
+						} else if ($v == 0) {
+							$r_ = $r2;
+							$g_ = $g2;
+							$b_ = $b2;
+						}else {
+							$r_ = $r + (($r2 - $r) * $v2 * (1 - $v));
+							$g_ = $g + (($g2 - $g) * $v2 * (1 - $v));
+							$b_ = $b + (($b2 - $b) * $v2 * (1 - $v));
+						}
+					}
+					$a_ = min($a,$a2);
+				} elseif ($mode == "produit" OR $mode == "difference") {					
+
+					if ($mode == "produit") {
+						$r = ($r/255) * $r2;
+						$g = ($g/255) * $g2;
+						$b = ($b/255) * $b2;
+					} else if ($mode == "difference") {
+						$r = abs($r-$r2);
+						$g = abs($g-$g2);
+						$b = abs($b-$b2);				
+					}
+
+					$r = max(0, min($r, 255));
+					$g = max(0, min($g, 255));
+					$b = max(0, min($b, 255));
+
+					$v = (127 - $a) / 127;
+					if ($v == 1) {
+						$r_ = $r;
+						$g_ = $g;
+						$b_ = $b;
+					} else {
+						$v2 = (127 - $a2) / 127;
+						if ($v+$v2 == 0) {
+							$r_ = $r2;
+							$g_ = $g2;
+							$b_ = $b2;
+						} else {
+							$r_ = $r + (($r2 - $r) * $v2 * (1 - $v));
+							$g_ = $g + (($g2 - $g) * $v2 * (1 - $v));
+							$b_ = $b + (($b2 - $b) * $v2 * (1 - $v));
+						}
+					}
+
+
+					$a_ = $a2;
+				} elseif ($mode == "eclaircir" OR $mode == "obscurcir") {
+					$v = (127 - $a) / 127;
+					if ($v == 1) {
+						$r_ = $r;
+						$g_ = $g;
+						$b_ = $b;
+					} else {
+						$v2 = (127 - $a2) / 127;
+						if ($v+$v2 == 0) {
+							$r_ = $r2;
+							$g_ = $g2;
+							$b_ = $b2;
+						} else {
+							$r_ = $r + (($r2 - $r) * $v2 * (1 - $v));
+							$g_ = $g + (($g2 - $g) * $v2 * (1 - $v));
+							$b_ = $b + (($b2 - $b) * $v2 * (1 - $v));
+						}
+					}
+					if ($mode == "eclaircir") {
+						$r_ = max ($r_, $r2);
+						$g_ = max ($g_, $g2);
+						$b_ = max ($b_, $b2);
+					} else {
+						$r_ = min ($r_, $r2);
+						$g_ = min ($g_, $g2);
+						$b_ = min ($b_, $b2);					
+					}
+					
+					$a_ = min($a,$a2);
+				} else {
+					$r_ = $r2 + 1 * ($r - 127);
+					$r_ = max(0, min($r_, 255));
+					$g_ = $g2 + 1 * ($g - 127);
+					$g_ = max(0, min($g_, 255));
+					$b_ = $b2 + 1 * ($b - 127);
+					$b_ = max(0, min($b_, 255));
+					
+					$a_ = $a + $a2 - round($a*$a2/127);
+				}
+
+				$color = ImageColorAllocateAlpha( $im_, $r_, $g_, $b_ , $a_ );
+				imagesetpixel ($im_, $x, $y, $color);			
+			}
+		}
+
+		image_gd_output($im_,$image);
+		imagedestroy($im_);
+		imagedestroy($im);
+		imagedestroy($im2);
+
 	}
+	$x_dest = largeur($dest);
+	$y_dest = hauteur($dest);
+	return image_ecrire_tag($image,array('src'=>$dest,'width'=>$x_dest,'height'=>$y_dest));
+}
 
-	// pas de fichier source par la
-	if (!($ret["hauteur"] OR $ret["largeur"]))
-		return false;
+// Passage de l'image en noir et blanc
+// un noir & blanc "photo" n'est pas "neutre": les composantes de couleur sont
+// ponderees pour obtenir le niveau de gris;
+// on peut ici regler cette ponderation en "pour mille"
+// http://doc.spip.org/@image_nb
+function image_nb($im, $val_r = 299, $val_g = 587, $val_b = 114)
+{
+	$fonction = array('image_nb', func_get_args());
+	$image = image_valeurs_trans($im, "nb-$val_r-$val_g-$val_b",false,$fonction);
+	if (!$image) return("");
+	
+	$x_i = $image["largeur"];
+	$y_i = $image["hauteur"];
+	
+	$im = $image["fichier"];
+	$dest = $image["fichier_dest"];
+	
+	$creer = $image["creer"];
 	
-	// cas general :
-	// on a un dossier cache commun et un nom de fichier qui varie avec l'effet
-	// cas particulier de reduire :
-	// un cache par dimension, et le nom de fichier est conserve, suffixe par la dimension aussi
-	$cache = "cache-gd2";
-	if (substr($effet,0,7)=='reduire') {
-		list(,$maxWidth,$maxHeight) = explode('-',$effet);
-		list ($destWidth,$destHeight) = image_ratio($ret['largeur'], $ret['hauteur'], $maxWidth, $maxHeight);
-		$ret['largeur_dest'] = $destWidth;
-		$ret['hauteur_dest'] = $destHeight;
-		$effet = "L{$destWidth}xH$destHeight";
-		$cache = "cache-vignettes";
-		$fichier_dest = basename($fichier_dest);
-		if (($ret['largeur']<=$maxWidth)&&($ret['hauteur']<=$maxHeight)){
-			// on garde la terminaison initiale car image simplement copiee
-			// et on postfixe son nom avec un md5 du path
-			$terminaison_dest = $terminaison;
-			$fichier_dest .= '-'.substr(md5("$fichier"),0,5);
+	// Methode precise
+	// resultat plus beau, mais tres lourd
+	// Et: indispensable pour preserver transparence!
+
+	if ($creer) {
+		// Creation de l'image en deux temps
+		// de facon a conserver les GIF transparents
+		$im = $image["fonction_imagecreatefrom"]($im);
+		imagepalettetotruecolor($im);
+		$im_ = imagecreatetruecolor($x_i, $y_i);
+		@imagealphablending($im_, false);
+		@imagesavealpha($im_,true);
+		$color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
+		imagefill ($im_, 0, 0, $color_t);
+		imagecopy($im_, $im, 0, 0, 0, 0, $x_i, $y_i);
+		
+		for ($x = 0; $x < $x_i; $x++) {
+			for ($y=0; $y < $y_i; $y++) {
+				$rgb = ImageColorAt($im_, $x, $y);
+				$a = ($rgb >> 24) & 0xFF;
+				$r = ($rgb >> 16) & 0xFF;
+				$g = ($rgb >> 8) & 0xFF;
+				$b = $rgb & 0xFF;
+
+				$c = round(($val_r * $r / 1000) + ($val_g * $g / 1000) + ($val_b * $b / 1000));
+				if ($c < 0) $c = 0;
+				if ($c > 254) $c = 254;
+				
+				
+				$color = ImageColorAllocateAlpha( $im_, $c, $c, $c , $a );
+				imagesetpixel ($im_, $x, $y, $color);			
+			}
 		}
-		else
-			$fichier_dest .= '-'.substr(md5("$fichier-$effet"),0,5);
-		$cache = sous_repertoire(_DIR_VAR, $cache);
-		$cache = sous_repertoire($cache, $effet);
-		# cherche un cache existant
-		/*foreach (array('gif','jpg','png') as $fmt)
-			if (@file_exists($cache . $fichier_dest . '.' . $fmt)) {
-				$terminaison_dest = $fmt;
-			}*/
+		image_gd_output($im_,$image);
+		imagedestroy($im_);
+		imagedestroy($im);
 	}
-	else 	{
-		$fichier_dest = md5("$fichier-$effet");
-		$cache = sous_repertoire(_DIR_VAR, $cache);
+
+	return image_ecrire_tag($image,array('src'=>$dest));
+}
+
+// http://doc.spip.org/@image_flou
+function image_flou($im,$niveau=3)
+{
+	// Il s'agit d'une modification du script blur qu'on trouve un peu partout:
+	// + la transparence est geree correctement
+	// + les dimensions de l'image sont augmentees pour flouter les bords
+	$coeffs = array (
+				array ( 1),
+				array ( 1, 1), 
+				array ( 1, 2, 1),
+				array ( 1, 3, 3, 1),
+				array ( 1, 4, 6, 4, 1),
+				array ( 1, 5, 10, 10, 5, 1),
+				array ( 1, 6, 15, 20, 15, 6, 1),
+				array ( 1, 7, 21, 35, 35, 21, 7, 1),
+				array ( 1, 8, 28, 56, 70, 56, 28, 8, 1),
+				array ( 1, 9, 36, 84, 126, 126, 84, 36, 9, 1),
+				array ( 1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1),
+				array ( 1, 11, 55, 165, 330, 462, 462, 330, 165, 55, 11, 1)
+				);
+	
+	$fonction = array('image_flou', func_get_args());
+	$image = image_valeurs_trans($im, "flou-$niveau", false,$fonction);
+	if (!$image) return("");
+	
+	$x_i = $image["largeur"];
+	$y_i = $image["hauteur"];
+	$sum = pow (2, $niveau);
+
+	$im = $image["fichier"];
+	$dest = $image["fichier_dest"];
+	
+	$creer = $image["creer"];
+	
+	// Methode precise
+	// resultat plus beau, mais tres lourd
+	// Et: indispensable pour preserver transparence!
+
+	if ($creer) {
+		// Creation de l'image en deux temps
+		// de facon a conserver les GIF transparents
+		$im = $image["fonction_imagecreatefrom"]($im);
+		imagepalettetotruecolor($im);
+		$temp1 = imagecreatetruecolor($x_i+$niveau, $y_i);
+		$temp2 = imagecreatetruecolor($x_i+$niveau, $y_i+$niveau);
+		
+		@imagealphablending($temp1, false);
+		@imagesavealpha($temp1,true);
+		@imagealphablending($temp2, false);
+		@imagesavealpha($temp2,true);
+
+		
+		for ($i = 0; $i < $x_i+$niveau; $i++) {
+			for ($j=0; $j < $y_i; $j++) {
+				$suma=0;
+				$sumr=0;
+				$sumg=0;
+				$sumb=0;
+				$sum = 0;
+				$sum_ = 0;
+				for ( $k=0 ; $k <= $niveau ; ++$k ) {
+					$color = imagecolorat($im, $i_ = ($i-$niveau)+$k , $j);
+
+					$a = ($color >> 24) & 0xFF;
+					$r = ($color >> 16) & 0xFF;
+					$g = ($color >> 8) & 0xFF;
+					$b = ($color) & 0xFF;
+					
+					if ($i_ < 0 OR $i_ >= $x_i) $a = 127;
+					
+					$coef = $coeffs[$niveau][$k];
+					$suma += $a*$coef;
+					$ac = ((127-$a) / 127);
+					
+					$ac = $ac*$ac;
+					
+					$sumr += $r * $coef * $ac;
+					$sumg += $g * $coef * $ac;
+					$sumb += $b * $coef * $ac;
+					$sum += $coef * $ac;
+					$sum_ += $coef;
+				}
+				if ($sum > 0) $color = ImageColorAllocateAlpha ($temp1, $sumr/$sum, $sumg/$sum, $sumb/$sum, $suma/$sum_);
+				else $color = ImageColorAllocateAlpha ($temp1, 255, 255, 255, 127);
+				imagesetpixel($temp1,$i,$j,$color);
+			}
+		}
+		imagedestroy($im);
+		for ($i = 0; $i < $x_i+$niveau; $i++) {
+			for ($j=0; $j < $y_i+$niveau; $j++) {
+				$suma=0;
+				$sumr=0;
+				$sumg=0;
+				$sumb=0;
+				$sum = 0;
+				$sum_ = 0;
+				for ( $k=0 ; $k <= $niveau ; ++$k ) {
+					$color = imagecolorat($temp1, $i, $j_ = $j-$niveau+$k);
+					$a = ($color >> 24) & 0xFF;
+					$r = ($color >> 16) & 0xFF;
+					$g = ($color >> 8) & 0xFF;
+					$b = ($color) & 0xFF;
+					if ($j_ < 0 OR $j_ >= $y_i) $a = 127;
+					
+					$suma += $a*$coeffs[$niveau][$k];
+					$ac = ((127-$a) / 127);
+										
+					$sumr += $r * $coeffs[$niveau][$k] * $ac;
+					$sumg += $g * $coeffs[$niveau][$k] * $ac;
+					$sumb += $b * $coeffs[$niveau][$k] * $ac;
+					$sum += $coeffs[$niveau][$k] * $ac;
+					$sum_ += $coeffs[$niveau][$k];
+					
+				}
+				if ($sum > 0) $color = ImageColorAllocateAlpha ($temp2, $sumr/$sum, $sumg/$sum, $sumb/$sum, $suma/$sum_);
+				else $color = ImageColorAllocateAlpha ($temp2, 255, 255, 255, 127);
+				imagesetpixel($temp2,$i,$j,$color);
+			}
+		}
+	
+		image_gd_output($temp2,$image);
+		imagedestroy($temp1);	
+		imagedestroy($temp2);	
 	}
 	
-	$fichier_dest = $cache . $fichier_dest . "." .$terminaison_dest;
+	return image_ecrire_tag($image,array('src'=>$dest,'width'=>($x_i+$niveau),'height'=>($y_i+$niveau)));
+}
+
+// http://doc.spip.org/@image_RotateBicubic
+function image_RotateBicubic($src_img, $angle, $bicubic=0) {
+   
+   if (round($angle/90)*90 == $angle) {
+		$droit = true;
+   		if (round($angle/180)*180 == $angle) $rot = 180;
+   		else $rot = 90;
+   }
+   else $droit = false;
+   
+  // convert degrees to radians
+   $angle = $angle + 180;
+   $angle = deg2rad($angle);
+  
+
+
+   $src_x = imagesx($src_img);
+   $src_y = imagesy($src_img);
+   
+  
+   $center_x = floor(($src_x-1)/2);
+   $center_y = floor(($src_y-1)/2);
+
+   $cosangle = cos($angle);
+   $sinangle = sin($angle);
+
+	// calculer dimensions en simplifiant angles droits, ce qui evite "floutage"
+	// des rotations a angle droit
+	if (!$droit) {
+	   $corners=array(array(0,0), array($src_x,0), array($src_x,$src_y), array(0,$src_y));
 	
-	$GLOBALS["images_calculees"][] =  $fichier_dest;
+	   foreach($corners as $key=>$value) {
+		 $value[0]-=$center_x;        //Translate coords to center for rotation
+		 $value[1]-=$center_y;
+		 $temp=array();
+		 $temp[0]=$value[0]*$cosangle+$value[1]*$sinangle;
+		 $temp[1]=$value[1]*$cosangle-$value[0]*$sinangle;
+		 $corners[$key]=$temp;    
+	   }
+	   
+	   $min_x=1000000000000000;
+	   $max_x=-1000000000000000;
+	   $min_y=1000000000000000;
+	   $max_y=-1000000000000000;
+	   
+	   foreach($corners as $key => $value) {
+		 if($value[0]<$min_x)
+		   $min_x=$value[0];
+		 if($value[0]>$max_x)
+		   $max_x=$value[0];
+	   
+		 if($value[1]<$min_y)
+		   $min_y=$value[1];
+		 if($value[1]>$max_y)
+		   $max_y=$value[1];
+	   }
 	
-	$creer = true;
-	// si recalcul des images demande, recalculer chaque image une fois
-	if (isset($GLOBALS['var_images']) && $GLOBALS['var_images'] && !isset($images_recalcul[$fichier_dest])){
-		$images_recalcul[$fichier_dest] = true;
+	   $rotate_width=ceil($max_x-$min_x);
+	   $rotate_height=ceil($max_y-$min_y);
+   }
+   else {
+   	if ($rot == 180) {
+   		$rotate_height = $src_y;
+   		$rotate_width = $src_x;
+   	} else {
+   		$rotate_height = $src_x;
+   		$rotate_width = $src_y;
+   	}
+   	$bicubic = false;
+   }
+   
+   
+   $rotate=imagecreatetruecolor($rotate_width,$rotate_height);
+   imagealphablending($rotate, false);
+   imagesavealpha($rotate, true);
+
+   $cosangle = cos($angle);
+   $sinangle = sin($angle);
+   
+	// arrondir pour rotations angle droit (car cos et sin dans {-1,0,1})
+	if ($droit) {
+		$cosangle = round($cosangle);
+		$sinangle = round($sinangle);
 	}
-	else {
-		if (@file_exists($f = $fichier_dest)){
-			if (filemtime($f)>=$date_src)
-				$creer = false;
+
+   $newcenter_x = ($rotate_width-1)/2;
+   $newcenter_y = ($rotate_height-1)/2;
+
+   
+   for ($y = 0; $y < $rotate_height; $y++) {
+     for ($x = 0; $x < $rotate_width; $x++) {
+   // rotate...
+       $old_x = ((($newcenter_x-$x) * $cosangle + ($newcenter_y-$y) * $sinangle))
+         + $center_x;
+       $old_y = ((($newcenter_y-$y) * $cosangle - ($newcenter_x-$x) * $sinangle))
+         + $center_y;  
+         
+         $old_x = ceil($old_x);
+         $old_y = ceil($old_y);
+         
+   if ( $old_x >= 0 && $old_x < $src_x
+         && $old_y >= 0 && $old_y < $src_y ) {
+     if ($bicubic == true) {
+       $xo = $old_x;
+       $x0 = floor($xo);
+       $x1 = ceil($xo);
+       $yo = $old_y;
+       $y0 = floor($yo);
+       $y1 = ceil($yo);
+       
+		// on prend chaque point, mais on pondere en fonction de la distance
+		$rgb = ImageColorAt($src_img, $x0, $y0); 
+		$a1 = ($rgb >> 24) & 0xFF;
+		$r1 = ($rgb >> 16) & 0xFF;
+		$g1 = ($rgb >> 8) & 0xFF;
+		$b1 = $rgb & 0xFF;
+		$d1 = image_distance_pixel($xo, $yo, $x0, $y0);
+
+		$rgb = ImageColorAt($src_img, $x1, $y0); 
+		$a2 = ($rgb >> 24) & 0xFF;
+		$r2 = ($rgb >> 16) & 0xFF;
+		$g2 = ($rgb >> 8) & 0xFF;
+		$b2 = $rgb & 0xFF;
+		$d2 = image_distance_pixel($xo, $yo, $x1, $y0);
+
+		$rgb = ImageColorAt($src_img,$x0, $y1); 
+		$a3 = ($rgb >> 24) & 0xFF;
+		$r3 = ($rgb >> 16) & 0xFF;
+		$g3 = ($rgb >> 8) & 0xFF;
+		$b3 = $rgb & 0xFF;
+		$d3 = image_distance_pixel($xo, $yo, $x0, $y1);
+
+		$rgb = ImageColorAt($src_img,$x1, $y1);
+		$a4 = ($rgb >> 24) & 0xFF;
+		$r4 = ($rgb >> 16) & 0xFF;
+		$g4 = ($rgb >> 8) & 0xFF;
+		$b4 = $rgb & 0xFF;
+		$d4 = image_distance_pixel($xo, $yo, $x1, $y1);
+
+		$ac1 = ((127-$a1) / 127);
+		$ac2 = ((127-$a2) / 127);
+		$ac3 = ((127-$a3) / 127);
+		$ac4 = ((127-$a4) / 127);
+		
+		// limiter impact des couleurs transparentes, 
+		// mais attention tout transp: division par 0
+		if ($ac1*$d1 + $ac2*$d2 + $ac3+$d3 + $ac4+$d4 > 0) {
+			if ($ac1 > 0) $d1 = $d1 * $ac1;
+			if ($ac2 > 0) $d2 = $d2 * $ac2;
+			if ($ac3 > 0) $d3 = $d3 * $ac3;
+			if ($ac4 > 0) $d4 = $d4 * $ac4;
 		}
-		else if (@file_exists($f = "$fichier_dest.src")
-		  AND lire_fichier($f,$valeurs)
-		  AND $valeurs=unserialize($valeurs)
-			AND $valeurs["date"]>=$date_src)
-				$creer = false;
-	}
+		
+		$tot  = $d1 + $d2 + $d3 + $d4;
+
+       $r = round((($d1*$r1)+($d2*$r2)+($d3*$r3)+($d4*$r4))/$tot);
+       $g = round((($d1*$g1+($d2*$g2)+$d3*$g3+$d4*$g4))/$tot);
+       $b = round((($d1*$b1+($d2*$b2)+$d3*$b3+$d4*$b4))/$tot);
+       $a = round((($d1*$a1+($d2*$a2)+$d3*$a3+$d4*$a4))/$tot);
+        $color = imagecolorallocatealpha($src_img, $r,$g,$b,$a);
+     } else {
+       $color = imagecolorat($src_img, round($old_x), round($old_y));
+     }
+   } else {
+         // this line sets the background colour
+     $color = imagecolorallocatealpha($src_img, 255, 255, 255, 127);
+   }
+   @imagesetpixel($rotate, $x, $y, $color);
+     }
+   }
+   return $rotate;
+}
+
+// permet de faire tourner une image d'un angle quelconque
+// la fonction "crop" n'est pas implementee...
+// http://doc.spip.org/@image_rotation
+function image_rotation($im, $angle, $crop=false)
+{
+	$fonction = array('image_rotation', func_get_args());
+	$image = image_valeurs_trans($im, "rot-$angle-$crop", "png", $fonction);
+	if (!$image) return("");
+	
+	$im = $image["fichier"];
+	$dest = $image["fichier_dest"];
+	
+	$creer = $image["creer"];
+	
 	if ($creer) {
-		if (!file_exists($fichier)) {
-			if (!file_exists("$fichier.src")) {
-				spip_log("Image absente : $fichier");
-				return false;
+		$effectuer_gd = true;
+
+		if (function_exists('imagick_rotate')) {
+			$mask = imagick_getcanvas( "#ff0000", $x, $y );
+			$handle = imagick_readimage ($im);
+			if ($handle && imagick_isopaqueimage( $handle )) {
+				imagick_rotate( $handle, $angle);
+				imagick_writeimage( $handle, $dest);
+				$effectuer_gd = false;
 			}
-			# on reconstruit l'image source absente a partir de la chaine des .src
-			reconstruire_image_intermediaire($fichier);
-		}
-	}
-	// todo: si une image png est nommee .jpg, le reconnaitre avec le bon $f
-	$f = "imagecreatefrom".$term_fonction;
-	if (!function_exists($f)) return false;
-	$ret["fonction_imagecreatefrom"] = $f;
-	$ret["fichier"] = $fichier;
-	$ret["fonction_image"] = "image_image".$terminaison_dest;
-	$ret["fichier_dest"] = $fichier_dest;
-	$ret["format_source"] = $terminaison;
-	$ret["format_dest"] = $terminaison_dest;
-	$ret["date_src"] = $date_src;
-	$ret["creer"] = $creer;
-	$ret["class"] = extraire_attribut($img, 'class');
-	$ret["alt"] = extraire_attribut($img, 'alt');
-	$ret["style"] = extraire_attribut($img, 'style');
-	$ret["tag"] = $img;
-	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
-		# ca evite d'essayer de le creer au prochain hit si il n'est pas la
-		#ecrire_fichier($ret['fichier_dest'].'.src',serialize($ret),true);
+		}
+		elseif(is_callable(array('Imagick','rotateImage'))){
+			$imagick = new Imagick();
+			$imagick->readImage($im);
+			$imagick->rotateImage(new ImagickPixel('#ffffff'), $angle);
+			$imagick->writeImage($dest);
+			$effectuer_gd = false;
+		}
+		if ($effectuer_gd) {
+			// Creation de l'image en deux temps
+			// de facon a conserver les GIF transparents
+			$im = $image["fonction_imagecreatefrom"]($im);
+			imagepalettetotruecolor($im);
+			$im = image_RotateBicubic($im, $angle, true);
+			image_gd_output($im,$image);
+			imagedestroy($im);
+		}
 	}
-	return $ret;
+	list ($src_y,$src_x) = taille_image($dest);
+	return image_ecrire_tag($image,array('src'=>$dest,'width'=>$src_x,'height'=>$src_y));
 }
 
-// http://doc.spip.org/@image_imagepng
-function image_imagepng($img,$fichier) {
-	$tmp = $fichier.".tmp";
-	$ret = imagepng($img,$tmp);
+// Permet d'appliquer un filtre php_imagick a une image
+// par exemple: [(#LOGO_ARTICLE||image_imagick{imagick_wave,20,60})]
+// liste des fonctions: http://www.linux-nantes.org/~fmonnier/doc/imagick/
+// http://doc.spip.org/@image_imagick
+function image_imagick () {
+	$tous = func_get_args();
+	$img = $tous[0];
+	$fonc = $tous[1];
+	$tous[0]="";
+	$tous_var = join($tous, "-");
+
+	$fonction = array('image_imagick', func_get_args());
+	$image = image_valeurs_trans($img, "$tous_var", "png",$fonction);
+	if (!$image) return("");
+	
+	$im = $image["fichier"];
+	$dest = $image["fichier_dest"];
+	
+	$creer = $image["creer"];
 	
-	$taille_test = getimagesize($tmp);
-	if ($taille_test[0] < 1) return false;
+	if ($creer) {
+		if (function_exists($fonc)) {
+
+			$handle = imagick_readimage ($im);
+			$arr[0] = $handle;
+			for ($i=2; $i < count($tous); $i++) $arr[] = $tous[$i];
+			call_user_func_array($fonc, $arr);
+			// Creer image dans fichier temporaire, puis renommer vers "bon" fichier
+			// de facon a eviter time_out pendant creation de l'image definitive
+			$tmp = preg_replace(",[.]png$,i", "-tmp.png", $dest);
+			imagick_writeimage( $handle, $tmp);
+			rename($tmp, $dest);
+			ecrire_fichier($dest.".src",serialize($image));
+		} 
+	}
+	list ($src_y,$src_x) = taille_image($dest);
+	return image_ecrire_tag($image,array('src'=>$dest,'width'=>$src_x,'height'=>$src_y));
 
-	spip_unlink($fichier); // le fichier peut deja exister
-	@rename($tmp, $fichier);
-	return $ret;
 }
 
-// http://doc.spip.org/@image_imagegif
-function image_imagegif($img,$fichier) {
-	$tmp = $fichier.".tmp";
-	$ret = imagegif($img,$tmp);
 
-	$taille_test = getimagesize($tmp);
-	if ($taille_test[0] < 1) return false;
+// $src_img - a GD image resource
+// $angle - degrees to rotate clockwise, in degrees
+// returns a GD image resource
+// script de php.net lourdement corrig'e
+// (le bicubic deconnait completement,
+// et j'ai ajoute la ponderation par la distance au pixel)
 
+// http://doc.spip.org/@image_distance_pixel
+function image_distance_pixel($xo, $yo, $x0, $y0) {
+	$vx = $xo - $x0;
+	$vy = $yo - $y0;
+	$d = 1 - (sqrt(($vx)*($vx) + ($vy)*($vy)) / sqrt(2));
+	return $d;
+}
 
-	spip_unlink($fichier); // le fichier peut deja exister
-	@rename($tmp, $fichier);
-	return $ret;
+// http://doc.spip.org/@image_decal_couleur
+function image_decal_couleur($coul, $gamma) {
+	$coul = $coul + $gamma;
+	
+	if ($coul > 255) $coul = 255;
+	if ($coul < 0) $coul = 0;
+	return $coul;
+}
+// Permet de rendre une image
+// plus claire (gamma > 0)
+// ou plus foncee (gamma < 0)
+// http://doc.spip.org/@image_gamma
+function image_gamma($im, $gamma = 0)
+{
+	$fonction = array('image_gamma', func_get_args());
+	$image = image_valeurs_trans($im, "gamma-$gamma",false,$fonction);
+	if (!$image) return("");
+	
+	$x_i = $image["largeur"];
+	$y_i = $image["hauteur"];
+	
+	$im = $image["fichier"];
+	$dest = $image["fichier_dest"];
+	
+	$creer = $image["creer"];
+	
+	if ($creer) {
+		// Creation de l'image en deux temps
+		// de facon a conserver les GIF transparents
+		$im = $image["fonction_imagecreatefrom"]($im);
+		imagepalettetotruecolor($im);
+		$im_ = imagecreatetruecolor($x_i, $y_i);
+		@imagealphablending($im_, false);
+		@imagesavealpha($im_,true);
+		$color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
+		imagefill ($im_, 0, 0, $color_t);
+		imagecopy($im_, $im, 0, 0, 0, 0, $x_i, $y_i);
+	
+		for ($x = 0; $x < $x_i; $x++) {
+			for ($y=0; $y < $y_i; $y++) {
+				$rgb = ImageColorAt($im_, $x, $y);
+				$a = ($rgb >> 24) & 0xFF;
+				$r = ($rgb >> 16) & 0xFF;
+				$g = ($rgb >> 8) & 0xFF;
+				$b = $rgb & 0xFF;
+
+				$r = image_decal_couleur($r, $gamma);
+				$g = image_decal_couleur($g, $gamma);
+				$b = image_decal_couleur($b, $gamma);
+
+				$color = ImageColorAllocateAlpha( $im_, $r, $g, $b , $a );
+				imagesetpixel ($im_, $x, $y, $color);			
+			}
+		}
+		image_gd_output($im_,$image);
+	}
+	return image_ecrire_tag($image,array('src'=>$dest));
 }
-// http://doc.spip.org/@image_imagejpg
-function image_imagejpg($img,$fichier,$qualite=_IMG_GD_QUALITE) {
-	$tmp = $fichier.".tmp";
-	$ret = imagejpeg($img,$tmp, $qualite);
 
-	$taille_test = getimagesize($tmp);
-	if ($taille_test[0] < 1) return false;
+// Passe l'image en "sepia"
+// On peut fixer les valeurs RVB 
+// de la couleur "complementaire" pour forcer une dominante
 
-	spip_unlink($fichier); // le fichier peut deja exister
-	@rename($tmp, $fichier);
-	return $ret;
+// http://doc.spip.org/@image_decal_couleur_127
+function image_decal_couleur_127 ($coul, $val) {
+	if ($coul < 127) $y = round((($coul - 127) / 127) * $val) + $val;
+	else if ($coul >= 127) $y = round((($coul - 127) / 128) * (255-$val)) + $val;
+	else $y= $coul;
+	
+	if ($y < 0) $y = 0;
+	if ($y > 255) $y = 255;
+	return $y;
 }
-// http://doc.spip.org/@image_imageico
-function image_imageico($img, $fichier) {
-	$gd_image_array = array($img);
+//function image_sepia($im, $dr = 137, $dv = 111, $db = 94)
+// http://doc.spip.org/@image_sepia
+function image_sepia($im, $rgb = "896f5e")
+{
+	
+	if (!function_exists("imagecreatetruecolor")) return $im;
+	
+	$couleurs = couleur_hex_to_dec($rgb);
+	$dr= $couleurs["red"];
+	$dv= $couleurs["green"];
+	$db= $couleurs["blue"];
+		
+	$fonction = array('image_sepia', func_get_args());
+	$image = image_valeurs_trans($im, "sepia-$dr-$dv-$db",false,$fonction);
+	if (!$image) return("");
+	
+	$x_i = $image["largeur"];
+	$y_i = $image["hauteur"];
+	
+	$im = $image["fichier"];
+	$dest = $image["fichier_dest"];
+	
+	$creer = $image["creer"];
+	
+	if ($creer) {
+		// Creation de l'image en deux temps
+		// de facon a conserver les GIF transparents
+		$im = $image["fonction_imagecreatefrom"]($im);
+		imagepalettetotruecolor($im);
+		$im_ = imagecreatetruecolor($x_i, $y_i);
+		@imagealphablending($im_, false);
+		@imagesavealpha($im_,true);
+		$color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
+		imagefill ($im_, 0, 0, $color_t);
+		imagecopy($im_, $im, 0, 0, 0, 0, $x_i, $y_i);
+	
+		for ($x = 0; $x < $x_i; $x++) {
+			for ($y=0; $y < $y_i; $y++) {
+				$rgb = ImageColorAt($im_, $x, $y);
+				$a = ($rgb >> 24) & 0xFF;
+				$r = ($rgb >> 16) & 0xFF;
+				$g = ($rgb >> 8) & 0xFF;
+				$b = $rgb & 0xFF;
 
-	return ecrire_fichier($fichier, phpthumb_functions::GD2ICOstring($gd_image_array));
-}
+				$r = round(.299 * $r + .587 * $g + .114 * $b);
+				$g = $r;
+				$b = $r;
 
-// $qualite est utilise pour la qualite de compression des jpeg
-// http://doc.spip.org/@image_gd_output
-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 = 
-		!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'));
-	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'])){
-			$valeurs['date'] = @filemtime($valeurs['fichier_dest']); // pour la retrouver apres disparition
-			ecrire_fichier($valeurs['fichier_dest'].'.src',serialize($valeurs),true);
+
+				$r = image_decal_couleur_127($r, $dr);
+				$g = image_decal_couleur_127($g, $dv);
+				$b = image_decal_couleur_127($b, $db);
+
+				$color = ImageColorAllocateAlpha( $im_, $r, $g, $b , $a );
+				imagesetpixel ($im_, $x, $y, $color);			
+			}
 		}
-	return $ret;
+		image_gd_output($im_,$image);
+		imagedestroy($im_);
+		imagedestroy($im);
+	}
+	
+	return image_ecrire_tag($image,array('src'=>$dest));
 }
 
-// http://doc.spip.org/@reconstruire_image_intermediaire
-function reconstruire_image_intermediaire($fichier_manquant){
-	$reconstruire = array();
-	$fichier = $fichier_manquant;
-	while (
-		!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)){
-		$r = array_pop($reconstruire);
-		$fonction = $r[0];
-		$args = $r[1];
-		call_user_func_array($fonction, $args);
-	}
-	// cette image intermediaire est commune a plusieurs series de filtre, il faut la conserver
-	// mais l'on peut nettoyer les miettes de sa creation
-	ramasse_miettes($fichier_manquant);
-}
-
-// http://doc.spip.org/@ramasse_miettes
-function ramasse_miettes($fichier){
-	if (!lire_fichier($src = "$fichier.src",$source) 
-		OR !$valeurs=unserialize($source)) return;
-	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
-		) {
-		# on efface le fichier
-		spip_unlink($fichier);
-		# mais laisse le .src qui permet de savoir comment reconstruire l'image si besoin
-		#spip_unlink($src);
-	}
-}
-
-// http://doc.spip.org/@image_graver
-function image_graver($img){
-	$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
-	if (!file_exists($fichier)) 
-		reconstruire_image_intermediaire($fichier);
-	ramasse_miettes($fichier);
-	return $img; // on ne change rien
-}
-
-// Transforme une image a palette indexee (256 couleurs max) en "vraies" couleurs RGB
-// http://doc.spip.org/@imagepalettetotruecolor
- function imagepalettetotruecolor(&$img) {
-	if (!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);
-		}
 
-		$img = $img1;
+// Renforcer la nettete d'une image
+// http://doc.spip.org/@image_renforcement
+function image_renforcement($im, $k=0.5)
+{
+	$fonction = array('image_flou', func_get_args());
+	$image = image_valeurs_trans($im, "renforcement-$k",false,$fonction);
+	if (!$image) return("");
+	
+	$x_i = $image["largeur"];
+	$y_i = $image["hauteur"];
+	$im = $image["fichier"];
+	$dest = $image["fichier_dest"];
+	$creer = $image["creer"];
+	
+	if ($creer) {
+		$im = $image["fonction_imagecreatefrom"]($im);
+		imagepalettetotruecolor($im);
+		$im_ = imagecreatetruecolor($x_i, $y_i);
+		@imagealphablending($im_, false);
+		@imagesavealpha($im_,true);
+		$color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
+		imagefill ($im_, 0, 0, $color_t);
+
+		for ($x = 0; $x < $x_i; $x++) {
+			for ($y=0; $y < $y_i; $y++) {		
+
+                $rgb[1][0]=imagecolorat($im,$x,$y-1);
+                $rgb[0][1]=imagecolorat($im,$x-1,$y);
+                $rgb[1][1]=imagecolorat($im,$x,$y);
+                $rgb[2][1]=imagecolorat($im,$x+1,$y);
+                $rgb[1][2]=imagecolorat($im,$x,$y+1);
+                
+                
+                if ($x-1 < 0) $rgb[0][1] = $rgb[1][1];
+                if ($y-1 < 0) $rgb[1][0] = $rgb[1][1];
+                if ($x+1 == $x_i) $rgb[2][1] = $rgb[1][1];
+                if ($y+1 == $y_i) $rgb[1][2] = $rgb[1][1];
+
+                $a = ($rgb[0][0] >> 24) & 0xFF;
+                $r = -$k *(($rgb[1][0] >> 16) & 0xFF) +
+                         -$k *(($rgb[0][1] >> 16) & 0xFF) +
+                        (1+4*$k) *(($rgb[1][1] >> 16) & 0xFF) +
+                         -$k *(($rgb[2][1] >> 16) & 0xFF) +
+                         -$k *(($rgb[1][2] >> 16) & 0xFF) ;
+
+                $g = -$k *(($rgb[1][0] >> 8) & 0xFF) +
+                         -$k *(($rgb[0][1] >> 8) & 0xFF) +
+                         (1+4*$k) *(($rgb[1][1] >> 8) & 0xFF) +
+                         -$k *(($rgb[2][1] >> 8) & 0xFF) +
+                         -$k *(($rgb[1][2] >> 8) & 0xFF) ;
+
+                $b = -$k *($rgb[1][0] & 0xFF) +
+                         -$k *($rgb[0][1] & 0xFF) +
+                        (1+4*$k) *($rgb[1][1] & 0xFF) +
+                         -$k *($rgb[2][1] & 0xFF) +
+                         -$k *($rgb[1][2] & 0xFF) ;
+
+                $r=min(255,max(0,$r));
+                $g=min(255,max(0,$g));
+                $b=min(255,max(0,$b));
+
+
+		$color = ImageColorAllocateAlpha( $im_, $r, $g, $b , $a );
+		imagesetpixel ($im_, $x, $y, $color);			
+			}
+		}		
+		image_gd_output($im_,$image);
 	}
+
+	return image_ecrire_tag($image,array('src'=>$dest));
 }
 
-// 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');
-	// 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);
-	// 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);
-	$style = "height:".$height."px;width:".$width."px;".$style;
-	// attributs deprecies. Transformer en CSS
-	if ($espace = extraire_attribut($tag, 'hspace')){
-		$style = "margin:${espace}px;".$style;
-		$tag = inserer_attribut($tag,'hspace','');
-	}
-	$tag = inserer_attribut($tag,'style',$style);
-	return $tag;
-}
-
-// function d'ecriture du tag img en sortie des filtre image
-// reprend le tag initial et surcharge les tags modifies
-// http://doc.spip.org/@image_ecrire_tag
-function image_ecrire_tag($valeurs,$surcharge){
-	$tag = 	str_replace(">","/>",str_replace("/>",">",$valeurs['tag'])); // fermer les tags img pas bien fermes;
-	
-	// le style
-	$style = $valeurs['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'])){
-		$width = $surcharge['width'];
-		unset($surcharge['width']);
-	}
-	$height = $valeurs['hauteur'];
-	if (isset($surcharge['height'])){
-		$height = $surcharge['height'];
-		unset($surcharge['height']);
-	}
-
-	$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 = $surcharge['src'];
-		unset($surcharge['src']);
-	}
-
-	$class = $valeurs['class'];
-	if (isset($surcharge['class'])){
-		$class = $surcharge['class'];
-		unset($surcharge['class']);
-	}
-	if(strlen($class))
-		$tag = inserer_attribut($tag,'class',$class);
-
-	if (count($surcharge))
-		foreach($surcharge as $attribut=>$valeur)
-			$tag = inserer_attribut($tag,$attribut,$valeur);
-
-	return $tag;
-}
-
-// selectionner les images qui vont subir une transformation sur un critere de taille
-// ls images exclues sont marquees d'une class no_image_filtrer qui bloque les filtres suivants
-// dans la fonction image_filtrer
-// http://doc.spip.org/@image_select
-function image_select($img,$width_min=0, $height_min=0, $width_max=10000, $height_max=1000){
-	if (!$img) return $img;
-	list ($h,$l) = taille_image($img);
-	$select = true;
-	if ($l<$width_min OR $l>$width_max OR $h<$height_min OR $h>$height_max)
-		$select = false;
-
-	$class = extraire_attribut($img,'class');
-	$p = strpos($class,'no_image_filtrer');
-	if (($select==false) AND ($p===FALSE)){
-		$class .= " no_image_filtrer";
-		$img = inserer_attribut($img,'class',$class);
-	}
-	if (($select==true) AND ($p!==FALSE)){
-		$class = preg_replace(",\s*no_image_filtrer,","",$class);
-		$img = inserer_attribut($img,'class',$class);
-	}
-	return $img;
-}
-
-// http://doc.spip.org/@image_creer_vignette
-function image_creer_vignette($valeurs, $maxWidth, $maxHeight, $process='AUTO', $force=false, $test_cache_only = 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"]);
-	
-	$format_sortie = $valeurs['format_dest'];
-	
-	// liste des formats qu'on sait lire
-	$img = isset($GLOBALS['meta']['formats_graphiques'])
-	  ? (strpos($GLOBALS['meta']['formats_graphiques'], $format)!==false)
-	  : false;
-
-	// si le doc n'est pas une image, refuser
-	if (!$force AND !$img) return;
-	$destination = "$destdir/$destfile";
-
-	// chercher un cache
-	$vignette = '';
-	if ($test_cache_only AND !$vignette) return;
-
-	// utiliser le cache ?
-	if (!$test_cache_only)
-	if ($force OR !$vignette OR (@filemtime($vignette) < @filemtime($image))) {
-
-		$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
-		else if ($process == 'convert') {
-			define('_CONVERT_COMMAND', 'convert');
-			define ('_RESIZE_COMMAND', _CONVERT_COMMAND.' -quality 85 -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
-			}
+
+// 1/ Aplatir une image semi-transparente (supprimer couche alpha)
+// en remplissant la transparence avec couleur choisir $coul.
+// 2/ Forcer le format de sauvegarde (jpg, png, gif)
+// pour le format jpg, $qualite correspond au niveau de compression (defaut 85)
+// pour le format gif, $qualite correspond au nombre de couleurs dans la palette (defaut 128)
+// pour le format png, $qualite correspond au nombre de couleur dans la palette ou si 0 a une image truecolor (defaut truecolor)
+// attention, seul 128 est supporte en l'etat (production d'images avec palette reduite pas satisfaisante)
+// http://doc.spip.org/@image_aplatir
+// 3/ $transparence a "true" permet de conserver la transparence (utile pour conversion GIF)
+// http://doc.spip.org/@image_aplatir
+function image_aplatir($im, $format='jpg', $coul='000000', $qualite=NULL, $transparence=false)
+{
+	if ($qualite===NULL){
+		if ($format=='jpg') $qualite=_IMG_GD_QUALITE;
+		elseif ($format=='png') $qualite=0;
+		else $qualite=128;
+	}
+	$fonction = array('image_aplatir', func_get_args());
+	$image = image_valeurs_trans($im, "aplatir-$format-$coul-$qualite-$transparence", $format, $fonction);
+
+	if (!$image) return("");
+
+	include_spip('inc/filtres');
+	$couleurs = couleur_hex_to_dec($coul);
+	$dr= $couleurs["red"];
+	$dv= $couleurs["green"];
+	$db= $couleurs["blue"];
+
+	$x_i = $image["largeur"];
+	$y_i = $image["hauteur"];
+	
+	$im = $image["fichier"];
+	$dest = $image["fichier_dest"];
+	
+	$creer = $image["creer"];
+
+	if ($creer) {
+		$im = @$image["fonction_imagecreatefrom"]($im);
+		imagepalettetotruecolor($im);
+		$im_ = imagecreatetruecolor($x_i, $y_i);
+		if ($image["format_source"] == "gif" AND function_exists('ImageCopyResampled')) { 
+			// Si un GIF est transparent, 
+			// fabriquer un PNG transparent  
+			// Conserver la transparence 
+			@imagealphablending($im_, false); 
+			@imagesavealpha($im_,true); 
+			if (function_exists("imageAntiAlias")) imageAntiAlias($im_,true); 
+			@ImageCopyResampled($im_, $im, 0, 0, 0, 0, $x_i, $y_i, $x_i, $y_i);
+			imagedestroy($im);
+			$im = $im_;
 		}
-		else
-		// imagick (php4-imagemagick)
-		if ($process == 'imagick') {
-			$vignette = "$destination.".$format_sortie;
-			$handle = imagick_readimage($image);
-			imagick_resize($handle, $destWidth, $destHeight, IMAGICK_FILTER_LANCZOS, 0.75);
-			imagick_write($handle, $vignette);
-			if (!@file_exists($vignette)) {
-				spip_log("echec imagick sur $vignette");
-				return;
-			}
+		
+		// allouer la couleur de fond
+		if ($transparence) {
+			@imagealphablending($im_, false); 
+			@imagesavealpha($im_,true); 
+			$color_t = imagecolorallocatealpha( $im_, $dr, $dv, $db, 127);
 		}
-		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") {
+		else $color_t = ImageColorAllocate( $im_, $dr, $dv, $db);
+		
+		imagefill ($im_, 0, 0, $color_t);
+
+		//??
+		//$dist = abs($trait);
+		
+		$transp_x = false;
+		
+		for ($x = 0; $x < $x_i; $x++) {
+			for ($y=0; $y < $y_i; $y++) {
+			
+				$rgb = ImageColorAt($im, $x, $y);
+				$a = ($rgb >> 24) & 0xFF;
+				$r = ($rgb >> 16) & 0xFF;
+				$g = ($rgb >> 8) & 0xFF;
+				$b = $rgb & 0xFF;
+
+				$a = (127-$a) / 127;
 				
-				$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;
+				if ($a == 1) { // Limiter calculs
+					$r = $r;
+					$g = $g;
+					$b = $b;
 				}
-			} 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)))
-					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 ($a == 0) { // Limiter calculs
+					$r = $dr;
+					$g = $dv;
+					$b = $db;
+					
+					$transp_x = $x; // Memoriser un point transparent
+					$transp_y = $y;
+					
+				} else {
+					$r = round($a * $r + $dr * (1-$a));
+					$g = round($a * $g + $dv * (1-$a));
+					$b = round($a * $b + $db * (1-$a));
 				}
+				$a = (1-$a) *127;
+				$color = ImageColorAllocateAlpha( $im_, $r, $g, $b, $a);
+				imagesetpixel ($im_, $x, $y, $color);	
 			}
 		}
-		// 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;
-			}
+		// passer en palette si besoin
+		if ($format=='gif' OR ($format=='png' AND $qualite!==0)){
+			// creer l'image finale a palette (on recycle l'image initiale)			
 
-			$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"; 
-				}
-				if ($destFormat == "png") { 
-					// Conserver la transparence 
-					if (function_exists("imageAntiAlias")) imageAntiAlias($destImage,true); 
-					@imagealphablending($destImage, false); 
-					@imagesavealpha($destImage,true); 
-				}
-				$ok = @ImageCopyResampled($destImage, $srcImage, 0, 0, 0, 0, $destWidth, $destHeight, $srcWidth, $srcHeight);
+
+			@imagetruecolortopalette($im,true,$qualite);
+
+
+			//$im = imagecreate($x_i, $y_i);
+			// copier l'image true color vers la palette
+			imagecopy($im, $im_, 0, 0, 0, 0, $x_i, $y_i);
+			// matcher les couleurs au mieux par rapport a l'image initiale
+			// si la fonction est disponible (php>=4.3)
+			if (function_exists('imagecolormatch'))
+				@imagecolormatch($im_, $im);
+				
+			if ($format=='gif' && $transparence && $transp_x) {	
+				$color_t = ImagecolorAt( $im, $transp_x, $transp_y);
+				if ($format == "gif" && $transparence) @imagecolortransparent($im, $color_t);
 			}
-			if (!$ok)
-				$ok = ImageCopyResized($destImage, $srcImage, 0, 0, 0, 0, $destWidth, $destHeight, $srcWidth, $srcHeight);
+				
+				
+			// produire le resultat
+			image_gd_output($im, $image, $qualite);
+		}
+		else
+			image_gd_output($im_, $image, $qualite);
+		imagedestroy($im_);
+		imagedestroy($im);
+	}
+	return image_ecrire_tag($image,array('src'=>$dest));
+}
+
+
+// Enregistrer une image dans un format donne
+// (conserve la transparence gif, png, ico)
+// utilise [->@image_aplatir]
+// http://doc.spip.org/@image_format
+function image_format($img, $format='png') {
+	return image_aplatir($img, $format, 'cccccc', null, true);
+}
 
-			// 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);
+
+// A partir d'une image,
+// recupere une couleur
+// renvoit sous la forme hexadecimale ("F26C4E" par exemple).
+// Par defaut, la couleur choisie se trouve un peu au-dessus du centre de l'image.
+// On peut forcer un point en fixant $x et $y, entre 0 et 20.
+// http://doc.spip.org/@image_couleur_extraire
+function image_couleur_extraire($img, $x=10, $y=6) {
+
+	$cache = image_valeurs_trans($img, "coul-$x-$y", "php");
+	if (!$cache) return "F26C4E";
+	
+	$fichier = $cache["fichier"];
+	$dest = $cache["fichier_dest"];
+	$terminaison = $cache["format_source"];
+	
+	$creer = $cache["creer"];
+	if ($creer) {
+		if (!$GLOBALS["couleur_extraite"]["$fichier-$x-$y"]) {	
+			if (file_exists($fichier)) {
+				list($width, $height) = getimagesize($fichier);
+			
+			
+				$newwidth = 20;
+				$newheight = 20;
+			
+				$thumb = imagecreate($newwidth, $newheight);
+
+				if (preg_match(",\.jpe?g$,i", $fichier)) $source = imagecreatefromjpeg($fichier);
+				if (preg_match(",\.gif$,i", $fichier)) $source = imagecreatefromgif($fichier);
+				if (preg_match(",\.png$,i", $fichier)) $source = imagecreatefrompng($fichier);
+				imagepalettetotruecolor($source);
+
+				imagecopyresized($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
+			
+				// get a color
+				$color_index = imagecolorat($thumb, $x, $y);
+				
+				// make it human readable
+				$color_tran = imagecolorsforindex($thumb, $color_index);
+				
+				$couleur = couleur_dec_to_hex($color_tran["red"], $color_tran["green"], $color_tran["blue"]);
+			}
+			else {
+				$couleur = "F26C4E";
+			}
+			$GLOBALS["couleur_extraite"]["$fichier-$x-$y"] = $couleur;
+
+			$handle = fopen($dest, 'w');
+			fwrite($handle, "<"."?php \$GLOBALS[\"couleur_extraite\"][\"".$fichier."-".$x."-".$y."\"] = \"".$couleur."\"; ?".">");
+			fclose($handle);
+		
 		}
+		// Mettre en cache le resultat
+		
+	} else {
+		include("$dest");
 	}
-	$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;
 	
-	$retour['width'] = $largeur = $size[0];
-	$retour['height'] = $hauteur = $size[1];
 	
-	$retour['fichier'] = $vignette;
-	$retour['format'] = $format;
-	$retour['date'] = @filemtime($vignette);
+	return $GLOBALS["couleur_extraite"]["$fichier-$x-$y"];
+}
+
+// http://doc.spip.org/@couleur_html_to_hex
+function couleur_html_to_hex($couleur){
+	$couleurs_html=array(
+		'aqua'=>'00FFFF','black'=>'000000','blue'=>'0000FF','fuchsia'=>'FF00FF','gray'=>'808080','green'=>'008000','lime'=>'00FF00','maroon'=>'800000',
+		'navy'=>'000080','olive'=>'808000','purple'=>'800080','red'=>'FF0000','silver'=>'C0C0C0','teal'=>'008080','white'=>'FFFFFF','yellow'=>'FFFF00');
+	if (isset($couleurs_html[$lc=strtolower($couleur)]))
+		return $couleurs_html[$lc];
+	return $couleur;
+}
+
+// http://doc.spip.org/@couleur_dec_to_hex
+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;
+	
+	return "$red$green$blue";
+}
+
+// http://doc.spip.org/@couleur_hex_to_dec
+function couleur_hex_to_dec($couleur) {
+	$couleur = couleur_html_to_hex($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));
 	
-	// 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;
+// http://doc.spip.org/@couleur_multiple_de_trois
+function couleur_multiple_de_trois($val) {
+	$val = hexdec($val);
+	$val = round($val / 3) * 3;
+	$val = dechex($val);
+	return $val;
+	
+}
+
+// http://doc.spip.org/@couleur_web
+function couleur_web($couleur) {
+	$r = couleur_multiple_de_trois(substr($couleur, 0, 1));
+	$v = couleur_multiple_de_trois(substr($couleur, 2, 1));
+	$b = couleur_multiple_de_trois(substr($couleur, 4, 1));
+	
+	return "$r$r$v$v$b$b";
+}
+
+// http://doc.spip.org/@couleur_4096
+function couleur_4096($couleur) {
+	$r = (substr($couleur, 0, 1));
+	$v = (substr($couleur, 2, 1));
+	$b = (substr($couleur, 4, 1));
+	
+	return "$r$r$v$v$b$b";
+}
+
+
+// http://doc.spip.org/@couleur_extreme
+function couleur_extreme ($couleur, $limite=0.5) {
+	// force la couleur au noir ou au blanc le plus proche
+	// -> donc couleur foncee devient noire
+	//    et couleur claire devient blanche
+	// -> la limite est une valeur de 0 a 255, permettant de regler le point limite entre le passage noir ou blanc
+
+	$couleurs = couleur_hex_to_dec($couleur);
+	$red = $couleurs["red"];
+	$green = $couleurs["green"];
+	$blue = $couleurs["blue"];
+	
+	
+	/*	
+	$moyenne = round(($red+$green+$blue)/3);
+
+	if ($moyenne > $limite) $couleur_texte = "ffffff";
+	else $couleur_texte = "000000";
+	*/
+
+	$hsl = couleur_rgb2hsl ($red, $green, $blue);
+
+	if ($hsl["l"] > $limite) $couleur_texte = "ffffff";
+	else $couleur_texte = "000000";
+
+	return $couleur_texte;
+}
+
+// http://doc.spip.org/@couleur_inverser
+function couleur_inverser ($couleur) {
+	$couleurs = couleur_hex_to_dec($couleur);
+	$red = 255 - $couleurs["red"];
+	$green = 255 - $couleurs["green"];
+	$blue = 255 - $couleurs["blue"];
+
+	$couleur = couleur_dec_to_hex($red, $green, $blue);
+	
+	return $couleur;
+}
+
+// http://doc.spip.org/@couleur_eclaircir
+function couleur_eclaircir ($couleur) {
+	$couleurs = couleur_hex_to_dec($couleur);
+
+	$red = $couleurs["red"] + round((255 - $couleurs["red"])/2);
+	$green = $couleurs["green"] + round((255 - $couleurs["green"])/2);
+	$blue = $couleurs["blue"] + round((255 - $couleurs["blue"])/2);
+
+	$couleur = couleur_dec_to_hex($red, $green, $blue);
+	
+	return $couleur;
+
+}
+// http://doc.spip.org/@couleur_foncer
+function couleur_foncer ($couleur) {
+	$couleurs = couleur_hex_to_dec($couleur);
+
+	$red = $couleurs["red"] - round(($couleurs["red"])/2);
+	$green = $couleurs["green"] - round(($couleurs["green"])/2);
+	$blue = $couleurs["blue"] - round(($couleurs["blue"])/2);
+
+	$couleur = couleur_dec_to_hex($red, $green, $blue);
+	
+	return $couleur;
+}
+// http://doc.spip.org/@couleur_foncer_si_claire
+function couleur_foncer_si_claire ($couleur) {
+	// ne foncer que les couleurs claires
+	// utile pour ecrire sur fond blanc, 
+	// mais sans changer quand la couleur est deja foncee
+	$couleurs = couleur_hex_to_dec($couleur);
+	$red = $couleurs["red"];
+	$green = $couleurs["green"];
+	$blue = $couleurs["blue"];
+	
+	$moyenne = round(($red+$green+$blue)/3);
+	
+	if ($moyenne > 122) return couleur_foncer($couleur);
+	else return $couleur;
+}
+// http://doc.spip.org/@couleur_eclaircir_si_foncee
+function couleur_eclaircir_si_foncee ($couleur) {
+	$couleurs = couleur_hex_to_dec($couleur);
+	$red = $couleurs["red"];
+	$green = $couleurs["green"];
+	$blue = $couleurs["blue"];
+	
+	$moyenne = round(($red+$green+$blue)/3);
+	
+	if ($moyenne < 123) return couleur_eclaircir($couleur);
+	else return $couleur;
+}
+
+
+// http://doc.spip.org/@couleur_saturation
+function couleur_saturation($couleur, $val) {
+	if ($couleur == "ffffff") $couleur = "eeeeee";
+
+	$couleurs = couleur_hex_to_dec($couleur);
+	$r= 255 - $couleurs["red"];
+	$g= 255 - $couleurs["green"];
+	$b= 255 - $couleurs["blue"];
 
-	if ($ratioWidth <=1 AND $ratioHeight <=1) {
-		$destWidth = $srcWidth;
-		$destHeight = $srcHeight;
-	} else if ($ratioWidth < $ratioHeight) {
-		$destWidth = $srcWidth/$ratioHeight;
-		$destHeight = $maxHeight;
+	$max = max($r,$g,$b);
+
+	$r = 255 - $r / $max * 255 * $val;
+	$g = 255 - $g / $max * 255 * $val;
+	$b = 255 - $b / $max * 255 * $val;
+	
+	$couleur = couleur_dec_to_hex($r, $g, $b);
+	
+	return $couleur;
+		
+}
+
+
+
+// http://doc.spip.org/@couleur_rgb2hsv
+function couleur_rgb2hsv ($R,$G,$B) {
+	$var_R = ( $R / 255 ) ;                    //Where RGB values = 0 ÷ 255
+	$var_G = ( $G / 255 );
+	$var_B = ( $B / 255 );
+
+	$var_Min = min( $var_R, $var_G, $var_B ) ;   //Min. value of RGB
+	$var_Max = max( $var_R, $var_G, $var_B ) ;   //Max. value of RGB
+	$del_Max = $var_Max - $var_Min  ;           //Delta RGB value
+
+	$V = $var_Max;
+	$L = ( $var_Max + $var_Min ) / 2;
+	
+	if ( $del_Max == 0 )                     //This is a gray, no chroma...
+	{
+	   $H = 0 ;                            //HSL results = 0 ÷ 1
+	   $S = 0 ;
 	}
-	else {
-		$destWidth = $maxWidth;
-		$destHeight = $srcHeight/$ratioWidth;
+	else                                    //Chromatic data...
+	{
+	   $S = $del_Max / $var_Max;
+	
+	   $del_R = ( ( ( $var_Max - $var_R ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
+	   $del_G = ( ( ( $var_Max - $var_G ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
+	   $del_B = ( ( ( $var_Max - $var_B ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
+	
+	   if      ( $var_R == $var_Max ) $H = $del_B - $del_G;
+	   else if ( $var_G == $var_Max ) $H = ( 1 / 3 ) + $del_R - $del_B;
+	   else if ( $var_B == $var_Max ) $H = ( 2 / 3 ) + $del_G - $del_R;
+	
+	   if ( $H < 0 )  $H =  $H + 1;
+	   if ( $H > 1 )  $H = $H - 1;
 	}
-	return array (ceil($destWidth), ceil($destHeight),
-		max($ratioWidth,$ratioHeight));
+				
+	$ret["h"] = $H;
+	$ret["s"] = $S;
+	$ret["v"] = $V;
+	
+	return $ret;
 }
 
-// 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;
 
-	if ($ratioWidth <=1 AND $ratioHeight <=1) {
-		$destWidth = $srcWidth;
-		$destHeight = $srcHeight;
-	} else if ($ratioWidth > $ratioHeight) {
-		$destWidth = $srcWidth/$ratioHeight;
-		$destHeight = $maxHeight;
+// http://doc.spip.org/@couleur_hsv2rgb
+function couleur_hsv2rgb ($H,$S,$V) {
+	
+	if ( $S == 0 )                       //HSV values = 0 ÷ 1
+	{
+	   $R = $V * 255;
+	   $G = $V * 255;
+	   $B = $V * 255;
 	}
-	else {
-		$destWidth = $maxWidth;
-		$destHeight = $srcHeight/$ratioWidth;
-	}
-	return array (floor($destWidth), floor($destHeight),
-		min($ratioWidth,$ratioHeight));
-}
-
-// http://doc.spip.org/@image_passe_partout
-function image_passe_partout($img,$taille_x = -1, $taille_y = -1,$force = false,$cherche_image=false,$process='AUTO'){
-	if (!$img) return '';
-	list ($hauteur,$largeur) = taille_image($img);
-	if ($taille_x == -1)
-		$taille_x = isset($GLOBALS['meta']['taille_preview'])?$GLOBALS['meta']['taille_preview']:150;
-	if ($taille_y == -1)
-		$taille_y = $taille_x;
-
-	if ($taille_x == 0 AND $taille_y > 0)
-		$taille_x = 1; # {0,300} -> c'est 300 qui compte
-	elseif ($taille_x > 0 AND $taille_y == 0)
-		$taille_y = 1; # {300,0} -> c'est 300 qui compte
-	elseif ($taille_x == 0 AND $taille_y == 0)
-		return '';
-	
-	list($destWidth,$destHeight,$ratio) = ratio_passe_partout($largeur,$hauteur,$taille_x,$taille_y);
-	$fonction = array('image_passe_partout', func_get_args());
-	return process_image_reduire($fonction,$img,$destWidth,$destHeight,$force,$cherche_image,$process);
-}
-
-// http://doc.spip.org/@image_reduire
-function image_reduire($img, $taille = -1, $taille_y = -1, $force=false, $cherche_image=false, $process='AUTO') {
-	// Determiner la taille x,y maxi
-	// prendre le reglage de previsu par defaut
-	if ($taille == -1)
-		$taille = isset($GLOBALS['meta']['taille_preview'])?$GLOBALS['meta']['taille_preview']:150;
-	if ($taille_y == -1)
-		$taille_y = $taille;
-
-	if ($taille == 0 AND $taille_y > 0)
-		$taille = 100000; # {0,300} -> c'est 300 qui compte
-	elseif ($taille > 0 AND $taille_y == 0)
-		$taille_y = 100000; # {300,0} -> c'est 300 qui compte
-	elseif ($taille == 0 AND $taille_y == 0)
-		return '';
-
-	$fonction = array('image_reduire', func_get_args());
-	return process_image_reduire($fonction,$img,$taille,$taille_y,$force,$cherche_image,$process);
-}
-
-// http://doc.spip.org/@process_image_reduire
-function process_image_reduire($fonction,$img,$taille,$taille_y,$force,$cherche_image,$process){
-	$image = false;
-	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);
-		// 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');
-			// 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
-			# bug : gd_formats contient la liste des fichiers qu'on sait *lire*,
-			# pas *ecrire*
-			$format_sortie = "";
-			foreach ($formats_sortie as $fmt) {
-				if (in_array($fmt, $gd_formats)) {
-					if ($fmt <> "gif" OR function_exists('ImageGif'))
-						$format_sortie = $fmt;
-					break;
+	else
+	{
+	   $var_h = $H * 6;
+	   if ( $var_h == 6 ) $var_h = 0 ;     //H must be < 1
+	   $var_i = floor( $var_h )  ;           //Or ... var_i = floor( var_h )
+	   $var_1 = $V * ( 1 - $S );
+	   $var_2 = $V * ( 1 - $S * ( $var_h - $var_i ) );
+	   $var_3 = $V * ( 1 - $S * ( 1 - ( $var_h - $var_i ) ) );
+	
+	
+	   if      ( $var_i == 0 ) { $var_r = $V     ; $var_g = $var_3 ; $var_b = $var_1 ; }
+	   else if ( $var_i == 1 ) { $var_r = $var_2 ; $var_g = $V     ; $var_b = $var_1 ; }
+	   else if ( $var_i == 2 ) { $var_r = $var_1 ; $var_g = $V     ; $var_b = $var_3 ; }
+	   else if ( $var_i == 3 ) { $var_r = $var_1 ; $var_g = $var_2 ; $var_b = $V ;     }
+	   else if ( $var_i == 4 ) { $var_r = $var_3 ; $var_g = $var_1 ; $var_b = $V ; }
+	   else                   { $var_r = $V     ; $var_g = $var_1 ; $var_b = $var_2; }
+	
+	   $R = $var_r * 255;                  //RGB results = 0 ÷ 255
+	   $G = $var_g * 255;
+	   $B = $var_b * 255;
+	}
+	$ret["r"] = floor($R);
+	$ret["g"] = floor($G);
+	$ret["b"] = floor($B);
+	
+	return $ret;
+}
+
+
+// http://doc.spip.org/@couleur_rgb2hsl
+function couleur_rgb2hsl ($R,$G,$B) {
+	$var_R = ( $R / 255 ) ;                    //Where RGB values = 0 ÷ 255
+	$var_G = ( $G / 255 );
+	$var_B = ( $B / 255 );
+
+	$var_Min = min( $var_R, $var_G, $var_B ) ;   //Min. value of RGB
+	$var_Max = max( $var_R, $var_G, $var_B ) ;   //Max. value of RGB
+	$del_Max = $var_Max - $var_Min  ;           //Delta RGB value
+
+	$L = ( $var_Max + $var_Min ) / 2;
+	
+	if ( $del_Max == 0 )                     //This is a gray, no chroma...
+	{
+	   $H = 0 ;                            //HSL results = 0 ÷ 1
+	   $S = 0 ;
+	}
+	else                                    //Chromatic data...
+	{
+		if ($L < 0.5 ) $S = $del_Max / ( $var_Max+ $var_Min);
+		else $S = $del_Max/ ( 2 - $var_Max - $var_Min);
+
+		$del_R = ( ( ( $var_Max- $var_R) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
+		$del_G = ( ( ( $var_Max- $var_G) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
+		$del_B = ( ( ( $var_Max- $var_B) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
+
+		if ( $var_R == $var_Max) $H= $del_B - $del_G;
+		else if ( $var_G == $var_Max) $H= ( 1 / 3 ) + $del_R - $del_B;
+		else if ( $var_B == $var_Max) $H= ( 2 / 3 ) + $del_G - $del_R;
+
+		if ( $H < 0 ) $H+= 1;
+		if ( $H > 1 ) $H-= 1;
+	}
+				
+	$ret["h"] = $H;
+	$ret["s"] = $S;
+	$ret["l"] = $L;
+	
+	return $ret;
+}
+
+
+// http://doc.spip.org/@hue_2_rgb
+function hue_2_rgb( $v1, $v2, $vH ) {
+   if ( $vH < 0 ) $vH += 1;
+   if ( $vH > 1 ) $vH -= 1;
+   if ( ( 6 * $vH ) < 1 ) return ( $v1 + ( $v2 - $v1 ) * 6 * $vH );
+   if ( ( 2 * $vH ) < 1 ) return ( $v2 );
+   if ( ( 3 * $vH ) < 2 ) return ( $v1 + ( $v2 - $v1 ) * ( ( 2 / 3 ) - $vH ) * 6 );
+   return ( $v1 );
+}
+
+// http://doc.spip.org/@couleur_hsl2rgb
+function couleur_hsl2rgb ($H,$S,$L) {
+	
+	if ( $S == 0 )                       //HSV values = 0 ÷ 1
+	{
+	   $R = $V * 255;
+	   $G = $V * 255;
+	   $B = $V * 255;
+	}
+	else
+	{
+		if ( $L < 0.5 ) $var_2 = $L * ( 1 + $S );
+		else            $var_2 = ( $L + $S ) - ( $S * $L );
+
+		$var_1 = 2 * $L - $var_2;
+
+		$R = 255 * hue_2_rgb( $var_1, $var_2, $H + ( 1 / 3 ) ) ;
+		$G = 255 * hue_2_rgb( $var_1, $var_2, $H );
+		$B = 255 * hue_2_rgb( $var_1, $var_2, $H - ( 1 / 3 ) );
+	}
+	$ret["r"] = floor($R);
+	$ret["g"] = floor($G);
+	$ret["b"] = floor($B);
+	
+	return $ret;
+}
+
+
+
+
+// Image typographique
+
+// Fonctions pour l'arabe
+
+
+// http://doc.spip.org/@rtl_mb_ord
+function rtl_mb_ord($char){
+
+	if (($c = ord($char)) < 216) return $c;
+	else return 256 * rtl_mb_ord(substr($char, 0, -1)) + ord(substr($char, -1));
+
+/*	return (strlen($char) < 2) ?
+		ord($char) : 256 * mb_ord(substr($char, 0, -1))
+			+ ord(substr($char, -1));
+			
+*/			
+  }
+
+
+
+// http://doc.spip.org/@rtl_reverse
+function rtl_reverse($mot, $rtl_global) {
+
+	$ponctuations = array("«","»", "“", "”", ",", ".", " ", ":", ";", "(", ")", "،", "؟", "?", "!", " ");
+	foreach($ponctuations as $ponct) {
+		$ponctuation[$ponct] = true;
+	}
+
+		
+
+	for ($i = 0; $i < spip_strlen($mot); $i++) {
+		$lettre = spip_substr($mot, $i, 1);
+		
+		
+		$code = rtl_mb_ord($lettre);
+//		echo "<li>$lettre - $code";
+
+		
+//			echo "<li>$code";
+		if (($code >= 54928 && $code <= 56767) ||  ($code >= 15707294 && $code <= 15711164)) {
+			$rtl = true;
+		}
+		else $rtl = false;
+		
+		if ($lettre == "٠" || $lettre == "١" || $lettre == "٢" || $lettre == "٣" || $lettre == "٤" || $lettre == "٥"
+				 || $lettre == "٦" || $lettre == "٧" || $lettre == "٨" || $lettre == "٩") $rtl = false;
+		
+		if ($ponctuation[$lettre]) {
+			$rtl = $rtl_global;
+			
+			if ($rtl) {
+				switch ($lettre) {
+					case "(": $lettre = ")"; break;
+					case ")": $lettre = "("; break;
+					case "«": $lettre = "»"; break;
+					case "»": $lettre = "«"; break;
+					case "“": $lettre = "”"; break;
+					case "”": $lettre = "“"; break;
 				}
 			}
-			$image = false;
 		}
+		
+		
+		if ($rtl) $res = $lettre.$res;
+		else $res = $res.$lettre;
+		
+	}
+	return $res;
+}
+
+
+
+// http://doc.spip.org/@rtl_visuel
+function rtl_visuel($texte, $rtl_global) {
+	// hebreu + arabe: 54928 => 56767
+	// hebreu + presentation A: 15707294 => 15710140
+	// arabe presentation: 15708336 => 15711164
+	
+//	echo hexdec("efb7bc");
+
+	// premiere passe pour determiner s'il y a du rtl
+	// de facon a placer ponctuation et mettre les mots dans l'ordre
+	
+
+
+
+	$arabic_letters = array(
+		array("ي", // lettre 0
+			"ﻱ",  // isolee 1
+			"ﻳ", // debut 2
+			"ﻴ", // milieu 3
+			"ﻲ"),
+		array("ب", // lettre 0
+			"ﺏ",  // isolee 1
+			"ﺑ", // debut 2
+			"ﺒ", // milieu 3
+			"ﺐ"),
+		array("ا", // lettre 0
+			"ا",  // isolee 1
+			"ﺍ", // debut 2
+			"ﺍ", // milieu 3
+			"ﺎ"),
+		array("إ", // lettre 0
+			"إ",  // isolee 1
+			"إ", // debut 2
+			"ﺈ", // milieu 3
+			"ﺈ"),
+		array("ل", // lettre 0
+			"ﻝ",  // isolee 1
+			"ﻟ", // debut 2
+			"ﻠ", // milieu 3
+			"ﻞ"),
+		array("خ", // lettre 0
+			"ﺥ",  // isolee 1
+			"ﺧ", // debut 2
+			"ﺨ", // milieu 3
+			"ﺦ"),
+		array("ج", // lettre 0
+			"ﺝ",  // isolee 1
+			"ﺟ", // debut 2
+			"ﺠ", // milieu 3
+			"ﺞ"),
+		array("س", // lettre 0
+			"ﺱ",  // isolee 1
+			"ﺳ", // debut 2
+			"ﺴ", // milieu 3
+			"ﺲ"),
+		array("ن", // lettre 0
+			"ﻥ",  // isolee 1
+			"ﻧ", // debut 2
+			"ﻨ", // milieu 3
+			"ﻦ"),
+		array("ش", // lettre 0
+			"ﺵ",  // isolee 1
+			"ﺷ", // debut 2
+			"ﺸ", // milieu 3
+			"ﺶ"),
+		array("ق", // lettre 0
+			"ﻕ",  // isolee 1
+			"ﻗ", // debut 2
+			"ﻘ", // milieu 3
+			"ﻖ"),
+		array("ح", // lettre 0
+			"ﺡ",  // isolee 1
+			"ﺣ", // debut 2
+			"ﺤ", // milieu 3
+			"ﺢ"),
+		array("م", // lettre 0
+			"ﻡ",  // isolee 1
+			"ﻣ", // debut 2
+			"ﻤ", // milieu 3
+			"ﻢ"),
+		array("ر", // lettre 0
+			"ر",  // isolee 1
+			"ﺭ", // debut 2
+			"ﺮ", // milieu 3
+			"ﺮ"),
+		array("ع", // lettre 0
+			"ع",  // isolee 1
+			"ﻋ", // debut 2
+			"ﻌ", // milieu 3
+			"ﻊ"),
+		array("و", // lettre 0
+			"و",  // isolee 1
+			"ﻭ", // debut 2
+			"ﻮ", // milieu 3
+			"ﻮ"),
+		array("ة", // lettre 0
+			"ة",  // isolee 1
+			"ة", // debut 2
+			"ﺔ", // milieu 3
+			"ﺔ"),
+		array("ف", // lettre 0
+			"ﻑ",  // isolee 1
+			"ﻓ", // debut 2
+			"ﻔ", // milieu 3
+			"ﻒ"),
+		array("ﻻ", // lettre 0
+			"ﻻ",  // isolee 1
+			"ﻻ", // debut 2
+			"ﻼ", // milieu 3
+			"ﻼ"),
+		array("ح", // lettre 0
+			"ﺡ",  // isolee 1
+			"ﺣ", // debut 2
+			"ﺤ", // milieu 3
+			"ﺢ"),
+		array("ت", // lettre 0
+			"ﺕ",  // isolee 1
+			"ﺗ", // debut 2
+			"ﺘ", // milieu 3
+			"ﺖ"),
+		array("ض", // lettre 0
+			"ﺽ",  // isolee 1
+			"ﺿ", // debut 2
+			"ﻀ", // milieu 3
+			"ﺾ"),
+		array("ك", // lettre 0
+			"ك",  // isolee 1
+			"ﻛ", // debut 2
+			"ﻜ", // milieu 3
+			"ﻚ"),
+		array("ه", // lettre 0
+			"ﻩ",  // isolee 1
+			"ﻫ", // debut 2
+			"ﻬ", // milieu 3
+			"ﻪ"),
+		array("ي", // lettre 0
+			"ي",  // isolee 1
+			"ﻳ", // debut 2
+			"ﻴ", // milieu 3
+			"ﻲ"),
+		array("ئ", // lettre 0
+			"ﺉ",  // isolee 1
+			"ﺋ", // debut 2
+			"ﺌ", // milieu 3
+			"ﺊ"),
+		array("ص", // lettre 0
+			"ﺹ",  // isolee 1
+			"ﺻ", // debut 2
+			"ﺼ", // milieu 3
+			"ﺺ"),
+		array("ث", // lettre 0
+			"ﺙ",  // isolee 1
+			"ﺛ", // debut 2
+			"ﺜ", // milieu 3
+			"ﺚ"),
+		array("ﻷ", // lettre 0
+			"ﻷ",  // isolee 1
+			"ﻷ", // debut 2
+			"ﻸ", // milieu 3
+			"ﻸ"),
+		array("د", // lettre 0
+			"ﺩ",  // isolee 1
+			"ﺩ", // debut 2
+			"ﺪ", // milieu 3
+			"ﺪ"),
+		array("ذ", // lettre 0
+			"ﺫ",  // isolee 1
+			"ﺫ", // debut 2
+			"ﺬ", // milieu 3
+			"ﺬ"),
+		array("ط", // lettre 0
+			"ﻁ",  // isolee 1
+			"ﻃ", // debut 2
+			"ﻄ", // milieu 3
+			"ﻂ"),
+		array("آ", // lettre 0
+			"آ",  // isolee 1
+			"آ", // debut 2
+			"ﺂ", // milieu 3
+			"ﺂ"),
+		array("أ", // lettre 0
+			"أ",  // isolee 1
+			"أ", // debut 2
+			"ﺄ", // milieu 3
+			"ﺄ"),
+		array("ؤ", // lettre 0
+			"ؤ",  // isolee 1
+			"ؤ", // debut 2
+			"ﺆ", // milieu 3
+			"ﺆ"),
+		array("ز", // lettre 0
+			"ز",  // isolee 1
+			"ز", // debut 2
+			"ﺰ", // milieu 3
+			"ﺰ"),
+		array("ظ", // lettre 0
+			"ظ",  // isolee 1
+			"ﻇ", // debut 2
+			"ﻈ", // milieu 3
+			"ﻆ"),
+		array("غ", // lettre 0
+			"غ",  // isolee 1
+			"ﻏ", // debut 2
+			"ﻐ", // milieu 3
+			"ﻎ"),
+		array("ى", // lettre 0
+			"ى",  // isolee 1
+			"ﯨ", // debut 2
+			"ﯩ", // milieu 3
+			"ﻰ"),
+		array("پ", // lettre 0
+			"پ",  // isolee 1
+			"ﭘ", // debut 2
+			"ﭙ", // milieu 3
+			"ﭗ"),
+		array("چ", // lettre 0
+			"چ",  // isolee 1
+			"ﭼ", // debut 2
+			"ﭽ", // milieu 3
+			"ﭻ")
+	);
+	
+	if(init_mb_string() AND mb_regex_encoding() !== "UTF-8") echo "Attention: dans php.ini, il faut indiquer:<br /><strong>mbstring.internal_encoding = UTF-8</strong>";
+	
+	
+	$texte = explode(" ", $texte);
+	
+	foreach ($texte as $mot) {
+		$res = "";
+
+
+
+		// Inserer des indicateurs de debut/fin
+		$mot = "^".$mot."^";
+
+		$mot = preg_replace(",&nbsp;,u", " ", $mot);
+		$mot = preg_replace(",&#171;,u", "«", $mot);
+		$mot = preg_replace(",&#187;,u", "»", $mot);
+
+
+
+
+		// ponctuations
+		$ponctuations = array("«","»", "“", "”", ",", ".", " ", ":", ";", "(", ")", "،", "؟", "?", "!"," ");
+		foreach($ponctuations as $ponct) {
+			$mot = str_replace("$ponct", "^$ponct^", $mot);
+		}
+
+		// lettres forcant coupure
+		$mot = preg_replace(",ا,u", "ا^", $mot);
+		$mot = preg_replace(",د,u", "د^", $mot);
+		$mot = preg_replace(",أ,u", "أ^", $mot);
+		$mot = preg_replace(",إ,u", "إ^", $mot);
+		$mot = preg_replace(",أ,u", "أ^", $mot);
+		$mot = preg_replace(",ر,u", "ر^", $mot);
+		$mot = preg_replace(",ذ,u", "ذ^", $mot);
+		$mot = preg_replace(",ز,u", "ز^", $mot);
+		$mot = preg_replace(",و,u", "و^", $mot);
+		$mot = preg_replace(",و,u", "و^", $mot);
+		$mot = preg_replace(",ؤ,u", "ؤ^", $mot);
+		$mot = preg_replace(",ة,u", "ة^", $mot);
+		//		$mot = preg_replace(",ل,u", "^ل", $mot);
+		//		$mot = preg_replace(",,", "^", $mot);
+
+
+		$mot = preg_replace(",٠,u", "^٠^", $mot);
+		$mot = preg_replace(",١,u", "^١^", $mot);
+		$mot = preg_replace(",٢,u", "^٢^", $mot);
+		$mot = preg_replace(",٣,u", "^٣^", $mot);
+		$mot = preg_replace(",٤,u", "^٤^", $mot);
+		$mot = preg_replace(",٥,u", "^٥^", $mot);
+		$mot = preg_replace(",٦,u", "^٦^", $mot);
+		$mot = preg_replace(",٧,u", "^٧^", $mot);
+		$mot = preg_replace(",٨,u", "^٨^", $mot);
+		$mot = preg_replace(",٩,u", "^٩^", $mot);
+
+
+		// Ligatures
+		$mot = preg_replace(",لا,u", "ﻻ", $mot);
+		$mot = preg_replace(",لأ,u", "ﻷ", $mot);
+		
+		
+		foreach ($arabic_letters as $a_l) {
+			$mot = preg_replace(",([^\^])".$a_l[0]."([^\^]),u", "\\1".$a_l[3]."\\2", $mot);
+			$mot = preg_replace(",\^".$a_l[0]."([^\^]),u", "^".$a_l[2]."\\1", $mot);
+			$mot = preg_replace(",([^\^])".$a_l[0]."\^,u", "\\1".$a_l[4]."^", $mot);
+			// il semble qu'il ne soit pas necessaire de remplacer
+			// la lettre isolee
+			//			$mot = preg_replace(",\^".$a_l[0]."\^,u", "^".$a_l[1]."^", $mot);
+		}
+		
+		
+
+		$mot = preg_replace(",\^,u", "", $mot);
+		
+		$res = $mot;
+		$res = rtl_reverse($mot, $rtl_global);
+
+		/*
+		$rtl = false;		
+		for ($i = 0; $i < spip_strlen($mot); $i++) {
+			$lettre = spip_substr($mot, $i, 1);
+			$code = rtl_mb_ord($lettre);
+			if (($code >= 54928 && $code <= 56767) ||  ($code >= 15708336 && $code <= 15711164)) $rtl = true;
+		}
+		*/
+		
+		
+		if ($rtl_global) $retour = $res . " " . $retour;
+		else $retour = $retour. " ".$res;
 	}
+	
+	
+	return $retour;
+}
+
+
 
-	if (!$image)
-		$image = image_valeurs_trans($img, "reduire-{$taille}-{$taille_y}",$format_sortie,$fonction);
 
-	if (!$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);
+// http://doc.spip.org/@printWordWrapped
+function printWordWrapped($image, $top, $left, $maxWidth, $font, $couleur, $text, $textSize, $align="left", $hauteur_ligne = 0) {
+	static $memps = array();
+
+	// imageftbbox exige un float, et settype aime le double pour php < 4.2.0
+	settype($textSize, 'double');
+
+	// calculer les couleurs ici, car fonctionnement different selon TTF ou PS
+	$black = imagecolorallocatealpha($image, hexdec("0x{".substr($couleur, 0,2)."}"), hexdec("0x{".substr($couleur, 2,2)."}"), hexdec("0x{".substr($couleur, 4,2)."}"), 0);
+	$grey2 = imagecolorallocatealpha($image, hexdec("0x{".substr($couleur, 0,2)."}"), hexdec("0x{".substr($couleur, 2,2)."}"), hexdec("0x{".substr($couleur, 4,2)."}"), 127);
+
+	// Gaffe, T1Lib ne fonctionne carrement pas bien des qu'on sort de ASCII
+	// C'est dommage, parce que la rasterisation des caracteres est autrement plus jolie qu'avec TTF.
+	// A garder sous le coude en attendant que ca ne soit plus une grosse bouse.
+	// Si police Postscript et que fonction existe...
+	if (
+	false AND
+	strtolower(substr($font,-4)) == ".pfb"
+	AND function_exists("imagepstext")) {
+		// Traitement specifique pour polices PostScript (experimental)
+		$textSizePs = round(1.32 * $textSize);
+		if (!$fontps = $memps["$font"]) {
+			$fontps = imagepsloadfont($font);
+			// Est-ce qu'il faut reencoder? Pas testable proprement, alors... 
+			// imagepsencodefont($fontps,find_in_path('polices/standard.enc'));
+			$memps["$font"] = $fontps;
 		}
-		// la on n'a pas d'infos sur l'image source... on refile le truc a css
-		// sous la forme style='max-width: NNpx;'
-		return inserer_attribut($img, 'style',
-			"max-width: ${taille}px; max-height: ${taille_y}px");
 	}
 
-	// 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']){
-			@copy($image['fichier'], $image['fichier_dest']);
+	$rtl_global = false;
+	for ($i = 0; $i < spip_strlen($text); $i++) {
+		$lettre = spip_substr($text, $i, 1);
+		$code = rtl_mb_ord($lettre);
+		if (($code >= 54928 && $code <= 56767) ||  ($code >= 15707294 && $code <= 15711164)) {
+			$rtl_global = true;
 		}
-		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 ($cherche_image){
-		$cherche = cherche_image_nommee(substr($image['fichier'],0,-4), array($image["format_source"]));
-		if (!$cherche) return $img;
-		//list($chemin,$nom,$format) = $cherche;
+	// split the text into an array of single words
+	$words = explode(' ', $text);
+
+	// les espaces
+	foreach($words as $k=>$v)
+		$words[$k] = str_replace(array('~'), array(' '), $v);
+
+
+	if ($hauteur_ligne == 0) $lineHeight = floor($textSize * 1.3);
+	else $lineHeight = $hauteur_ligne;
+
+	$dimensions_espace = imageftbbox($textSize, 0, $font, ' ', array());
+	$largeur_espace = $dimensions_espace[2] - $dimensions_espace[0];
+	$retour["espace"] = $largeur_espace;
+
+
+	$line = '';
+	while (count($words) > 0) {
+		
+		$mot = $words[0];
+		
+		if ($rtl_global) $mot = rtl_visuel($mot,$rtl_global);
+	
+		$dimensions = imageftbbox($textSize, 0, $font, $line.' '.$mot, array());
+		$lineWidth = $dimensions[2] - $dimensions[0]; // get the length of this line, if the word is to be included
+		if ($lineWidth > $maxWidth) { // if this makes the text wider that anticipated
+			$lines[] = $line; // add the line to the others
+			$line = ''; // empty it (the word will be added outside the loop)
+		}
+		$line .= ' '.$words[0]; // add the word to the current sentence
+		$words = array_slice($words, 1); // remove the word from the array
 	}
-	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);
+	if ($line != '') { $lines[] = $line; } // add the last line to the others, if it isn't empty
+	$height = count($lines) * $lineHeight; // the height of all the lines total
+	// do the actual printing
+	$i = 0;
+
+	// Deux passes pour recuperer, d'abord, largeur_ligne
+	// necessaire pour alignement right et center
+	foreach ($lines as $line) {
+		if ($rtl_global) $line = rtl_visuel($line, $rtl_global);
+		
+		$dimensions = imageftbbox($textSize, 0, $font, $line, array());
+		$largeur_ligne = $dimensions[2] - $dimensions[0];
+		if ($largeur_ligne > $largeur_max) $largeur_max = $largeur_ligne;
+	}
+
+	foreach ($lines as $i => $line) {
+		if ($rtl_global) $line = rtl_visuel($line, $rtl_global);
 
-		if ($preview && $preview['fichier']) {
-			$logo = $preview['fichier'];
-			$destWidth = $preview['width'];
-			$destHeight = $preview['height'];
-			$date = $preview['date'];
+		$dimensions = imageftbbox($textSize, 0, $font, $line, array());
+		$largeur_ligne = $dimensions[2] - $dimensions[0];
+		if ($align == "right") $left_pos = $largeur_max - $largeur_ligne;
+		else if ($align == "center") $left_pos = floor(($largeur_max - $largeur_ligne)/2);
+		else $left_pos = 0;
+		
+		
+		if ($fontps) {
+			$line = trim($line);
+			imagepstext ($image, "$line", $fontps, $textSizePs, $black, $grey2, $left + $left_pos, $top + $lineHeight * $i, 0, 0, 0, 16);
 		}
-		// dans l'espace prive mettre un timestamp sur l'adresse 
-		// 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='.$date) : '';
-		return image_ecrire_tag($image,array('src'=>"$logo$date",'width'=>$destWidth,'height'=>$destHeight));
+		else imagefttext($image, $textSize, 0, $left + $left_pos, $top + $lineHeight * $i, $black, $font, trim($line), array());
 	}
-	else
-		# SVG par exemple ? BMP, tiff ... les redacteurs osent tout!
-		return $img;
+	$retour["height"] = $height;# + round(0.3 * $hauteur_ligne);
+	$retour["width"] = $largeur_max;
+                 
+	return $retour;
 }
+//array imagefttext ( resource image, float size, float angle, int x, int y, int col, string font_file, string text [, array extrainfo] )
+//array imagettftext ( resource image, float size, float angle, int x, int y, int color, string fontfile, string text )
+
+// http://doc.spip.org/@produire_image_typo
+function produire_image_typo() {
+	/*
+	arguments autorises:
+	
+	$texte : le texte a transformer; attention: c'est toujours le premier argument, et c'est automatique dans les filtres
+	$couleur : la couleur du texte dans l'image - pas de dieze
+	$police: nom du fichier de la police (inclure terminaison)
+	$largeur: la largeur maximale de l'image ; attention, l'image retournee a une largeur inferieure, selon les limites reelles du texte
+	$hauteur_ligne: la hauteur de chaque ligne de texte si texte sur plusieurs lignes
+	(equivalent a "line-height")
+	$padding: forcer de l'espace autour du placement du texte; necessaire pour polices a la con qui "depassent" beaucoup de leur boite 
+	$align: alignement left, right, center
+	*/
+
+
+
+	// Recuperer les differents arguments
+	$numargs = func_num_args();
+	$arg_list = func_get_args();
+	$texte = $arg_list[0];
+	for ($i = 1; $i < $numargs; $i++) {
+		if (($p = strpos($arg_list[$i], "="))!==FALSE) {
+			$nom_variable = substr($arg_list[$i], 0, $p);
+			$val_variable = substr($arg_list[$i], $p+1);
+		
+			$variable["$nom_variable"] = $val_variable;
+		}
+		
+	}
 
-// Reduire une image d'un certain facteur
-// http://doc.spip.org/@image_reduire_par
-function image_reduire_par ($img, $val=1, $force=false) {
-	list ($hauteur,$largeur) = taille_image($img);
+	// Construire requete et nom fichier
+	$text = str_replace("&nbsp;", "~", $texte);	
+	$text = preg_replace(",(\r|\n)+,ms", " ", $text);
+	include_spip('inc/charsets');
+	$text = html2unicode(strip_tags($text));
+	if (strlen($text) == 0) return "";
 
-	$l = round($largeur/$val);
-	$h = round($hauteur/$val);
+	$taille = $variable["taille"];
+	if ($taille < 1) $taille = 16;
+
+	$couleur = couleur_html_to_hex($variable["couleur"]);
+	if (strlen($couleur) < 6) $couleur = "000000";
+
+	$alt = $texte;
+		
+	$align = $variable["align"];
+	if (!$variable["align"]) $align="left";
+	 
+	$police = $variable["police"];
+	if (strlen($police) < 2) $police = "dustismo.ttf";
+
+	$largeur = $variable["largeur"];
+	if ($largeur < 5) $largeur = 600;
+
+	if ($variable["hauteur_ligne"] > 0) $hauteur_ligne = $variable["hauteur_ligne"];
+	else $hauteur_ligne = 0;
+	if ($variable["padding"] > 0) $padding = $variable["padding"];
+	else $padding = 0;
 	
-	if ($l > $h) $h = 0;
-	else $l = 0;
+
+
+	$string = "$text-$taille-$couleur-$align-$police-$largeur-$hauteur_ligne-$padding";
+	$query = md5($string);
+	$dossier = sous_repertoire(_DIR_VAR, 'cache-texte');
+	$fichier = "$dossier$query.png";
+
+	$flag_gd_typo = function_exists("imageftbbox")
+		&& function_exists('imageCreateTrueColor');
+
 	
-	$img = image_reduire($img, $l, $h, $force);
+	if (file_exists($fichier))
+		$image = $fichier;
+	else if (!$flag_gd_typo)
+		return $texte;
+	else {
+		$font = find_in_path('polices/'.$police);
+		if (!$font) {
+			spip_log(_T('fichier_introuvable', array('fichier' => $police)));
+			$font = find_in_path('polices/'."dustismo.ttf");
+		}
+
+		$imgbidon = imageCreateTrueColor($largeur, 45);
+		$retour = printWordWrapped($imgbidon, $taille+5, 0, $largeur, $font, $couleur, $text, $taille, 'left', $hauteur_ligne);
+		$hauteur = $retour["height"];
+		$largeur_reelle = $retour["width"];
+		$espace = $retour["espace"];
+		imagedestroy($imgbidon);
+
+		$im = imageCreateTrueColor($largeur_reelle-$espace+(2*$padding), $hauteur+5+(2*$padding));
+		imagealphablending ($im, FALSE );
+		imagesavealpha ( $im, TRUE );
+		
+		// Creation de quelques couleurs
+		
+		$grey2 = imagecolorallocatealpha($im, hexdec("0x{".substr($couleur, 0,2)."}"), hexdec("0x{".substr($couleur, 2,2)."}"), hexdec("0x{".substr($couleur, 4,2)."}"), 127);
+		ImageFilledRectangle ($im,0,0,$largeur_reelle+(2*$padding),$hauteur+5+(2*$padding),$grey2);
+		
+		// Le texte a dessiner
+		printWordWrapped($im, $taille+5+$padding, $padding, $largeur, $font, $couleur, $text, $taille, $align, $hauteur_ligne);
+		
+		
+		// Utiliser imagepng() donnera un texte plus claire,
+		// compare a l'utilisation de la fonction imagejpeg()
+		imagepng($im, $fichier);
+		imagedestroy($im);
+		
+		$image = $fichier;
+	}
+
+
+	$dimensions = getimagesize($image);
+	$largeur = $dimensions[0];
+	$hauteur = $dimensions[1];
+	return inserer_attribut("<img src='$image' width='$largeur' height='$hauteur' style='width:".$largeur."px;height:".$hauteur."px;' />", 'alt', $alt);
+}
+
+
+
+//
+// Produire des fichiers au format .ico
+// avec du code recupere de :
+//
+//////////////////////////////////////////////////////////////
+///  phpThumb() by James Heinrich <info@silisoftware.com>   //
+//        available at http://phpthumb.sourceforge.net     ///
+//////////////////////////////////////////////////////////////
+class phpthumb_functions {
+// http://doc.spip.org/@GetPixelColor
+	function GetPixelColor(&$img, $x, $y) {
+		if (!is_resource($img)) {
+			return false;
+		}
+		return @ImageColorsForIndex($img, @ImageColorAt($img, $x, $y));
+	}
+// http://doc.spip.org/@LittleEndian2String
+	function LittleEndian2String($number, $minbytes=1) {
+		$intstring = '';
+		while ($number > 0) {
+			$intstring = $intstring.chr($number & 255);
+			$number >>= 8;
+		}
+		return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT);
+	}
+// http://doc.spip.org/@GD2ICOstring
+	function GD2ICOstring(&$gd_image_array) {
+		foreach ($gd_image_array as $key => $gd_image) {
+
+			$ImageWidths[$key]  = ImageSX($gd_image);
+			$ImageHeights[$key] = ImageSY($gd_image);
+			$bpp[$key]		  = ImageIsTrueColor($gd_image) ? 32 : 24;
+			$totalcolors[$key]  = ImageColorsTotal($gd_image);
+
+			$icXOR[$key] = '';
+			for ($y = $ImageHeights[$key] - 1; $y >= 0; $y--) {
+				for ($x = 0; $x < $ImageWidths[$key]; $x++) {
+					$argb = phpthumb_functions::GetPixelColor($gd_image, $x, $y);
+					$a = round(255 * ((127 - $argb['alpha']) / 127));
+					$r = $argb['red'];
+					$g = $argb['green'];
+					$b = $argb['blue'];
+
+					if ($bpp[$key] == 32) {
+						$icXOR[$key] .= chr($b).chr($g).chr($r).chr($a);
+					} elseif ($bpp[$key] == 24) {
+						$icXOR[$key] .= chr($b).chr($g).chr($r);
+					}
+
+					if ($a < 128) {
+						@$icANDmask[$key][$y] .= '1';
+					} else {
+						@$icANDmask[$key][$y] .= '0';
+					}
+				}
+				// mask bits are 32-bit aligned per scanline
+				while (strlen($icANDmask[$key][$y]) % 32) {
+					$icANDmask[$key][$y] .= '0';
+				}
+			}
+			$icAND[$key] = '';
+			foreach ($icANDmask[$key] as $y => $scanlinemaskbits) {
+				for ($i = 0; $i < strlen($scanlinemaskbits); $i += 8) {
+					$icAND[$key] .= chr(bindec(str_pad(substr($scanlinemaskbits, $i, 8), 8, '0', STR_PAD_LEFT)));
+				}
+			}
+
+		}
+
+		foreach ($gd_image_array as $key => $gd_image) {
+			$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;
+			// 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;
+		}
+
+
+		$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 .= "\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($dwImageOffset, 4);	  // dwImageOffset;   // Where in the file is this image?
+			$dwImageOffset += strlen($BitmapInfoHeader[$key]);
+			$dwImageOffset += strlen($icXOR[$key]);
+			$dwImageOffset += strlen($icAND[$key]);
+		}
+
+		foreach ($gd_image_array as $key => $gd_image) {
+			$icondata .= $BitmapInfoHeader[$key];
+			$icondata .= $icXOR[$key];
+			$icondata .= $icAND[$key];
+		}
+
+		return $icondata;
+	}
 
-	return $img;
 }
 
 ?>
\ No newline at end of file
diff --git a/ecrire/inc/filtres_images_etendus.php b/ecrire/inc/filtres_images_etendus.php
deleted file mode 100644
index e075c20005..0000000000
--- a/ecrire/inc/filtres_images_etendus.php
+++ /dev/null
@@ -1,2543 +0,0 @@
-<?php
-/***************************************************************************\
- *  SPIP, Systeme de publication pour l'internet                           *
- *                                                                         *
- *  Copyright (c) 2001-2008                                                *
- *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
- *                                                                         *
- *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
- *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
-\***************************************************************************/
-
-include_spip('inc/filtres_images');
-
-// Transforme l'image en PNG transparent
-// alpha = 0: aucune transparence
-// alpha = 127: completement transparent
-// http://doc.spip.org/@image_alpha
-function image_alpha($im, $alpha = 63)
-{
-	$fonction = array('image_alpha', func_get_args());
-	$image = image_valeurs_trans($im, "alpha-$alpha", "png",$fonction);
-	if (!$image) return("");
-	
-	$x_i = $image["largeur"];
-	$y_i = $image["hauteur"];
-	
-	$im = $image["fichier"];
-	$dest = $image["fichier_dest"];
-	
-	$creer = $image["creer"];
-	
-	if ($creer) {
-		// Creation de l'image en deux temps
-		// de facon a conserver les GIF transparents
-		$im = $image["fonction_imagecreatefrom"]($im);
-		imagepalettetotruecolor($im);
-		$im2 = imagecreatetruecolor($x_i, $y_i);
-		@imagealphablending($im2, false);
-		@imagesavealpha($im2,true);
-		$color_t = ImageColorAllocateAlpha( $im2, 255, 255, 255 , 127 );
-		imagefill ($im2, 0, 0, $color_t);
-		imagecopy($im2, $im, 0, 0, 0, 0, $x_i, $y_i);
-
-		$im_ = imagecreatetruecolor($x_i, $y_i);
-		imagealphablending ($im_, FALSE );
-		imagesavealpha ( $im_, TRUE );
-
-
-
-		for ($x = 0; $x < $x_i; $x++) {
-			for ($y = 0; $y < $y_i; $y++) {
-				$rgb = ImageColorAt($im2, $x, $y);
-				
-				if (function_exists('imagecolorallocatealpha')) {
-					$a = ($rgb >> 24) & 0xFF;
-					$r = ($rgb >> 16) & 0xFF;
-					$g = ($rgb >> 8) & 0xFF;
-					$b = $rgb & 0xFF;
-					
-					
-					$a_ = $alpha + $a - round($a*$alpha/127);
-					$rgb = imagecolorallocatealpha($im_, $r, $g, $b, $a_);
-				}
-				imagesetpixel ( $im_, $x, $y, $rgb );
-			}
-		}
-		image_gd_output($im_,$image);
-		imagedestroy($im_);
-		imagedestroy($im);
-		imagedestroy($im2);
-	}
-	
-
-	return image_ecrire_tag($image,array('src'=>$dest));
-	
-}
-
-// http://doc.spip.org/@image_recadre
-function image_recadre($im,$width,$height,$position='center', $background_color='white')
-{
-	$fonction = array('image_recadre', func_get_args());
-	$image = image_valeurs_trans($im, "recadre-$width-$height-$position-$background_color",false,$fonction);
-	
-	if (!$image) return("");
-	
-	$x_i = $image["largeur"];
-	$y_i = $image["hauteur"];
-	
-	if ($width==0) $width=$x_i;
-	if ($height==0) $height=$y_i;
-	
-	$offset_width = $x_i-$width;
-	$offset_height = $y_i-$height;
-	$position=strtolower($position);
-	if (strpos($position,'left')!==FALSE){
-		if (preg_match(';left=(\d{1}\d+);', $position, $left)){
-			$offset_width=$left[1];	
-		}
-		else{
-			$offset_width=0;
-		}
-	}
-	elseif (strpos($position,'right')!==FALSE)
-		$offset_width=$offset_width;
-	else
-		$offset_width=intval(ceil($offset_width/2));
-
-	if (strpos($position,'top')!==FALSE){
-		if (preg_match(';top=(\d{1}\d+);', $position, $top)){
-			$offset_height=$top[1];
-		}
-		else{
-			$offset_height=0;
-		}
-	}
-	elseif (strpos($position,'bottom')!==FALSE)
-		$offset_height=$offset_height;
-	else
-		$offset_height=intval(ceil($offset_height/2));
-	
-	$im = $image["fichier"];
-	$dest = $image["fichier_dest"];
-	
-	$creer = $image["creer"];
-	
-	if ($creer) {
-		$im = $image["fonction_imagecreatefrom"]($im);
-		imagepalettetotruecolor($im);
-		$im_ = imagecreatetruecolor($width, $height);
-		@imagealphablending($im_, false);
-		@imagesavealpha($im_,true);
-
-		if ($background_color=='transparent')
-			$color_t = imagecolorallocatealpha( $im_, 255, 255, 255 , 127 );
-		else {
-			$bg = couleur_hex_to_dec($background_color);
-			$color_t = imagecolorallocate( $im_, $bg['red'], $bg['green'], $bg['blue']);
-		}
-		imagefill ($im_, 0, 0, $color_t);
-		imagecopy($im_, $im, max(0,-$offset_width), max(0,-$offset_height), max(0,$offset_width), max(0,$offset_height), min($width,$x_i), min($height,$y_i));
-
-		image_gd_output($im_,$image);
-		imagedestroy($im_);
-		imagedestroy($im);
-	}
-	
-	return image_ecrire_tag($image,array('src'=>$dest,'width'=>$width,'height'=>$height));
-}
-
-// http://doc.spip.org/@image_flip_vertical
-function image_flip_vertical($im)
-{
-	$fonction = array('image_flip_vertical', func_get_args());
-	$image = image_valeurs_trans($im, "flip_v", false,$fonction);
-	if (!$image) return("");
-	
-	$x_i = $image["largeur"];
-	$y_i = $image["hauteur"];
-	
-	$im = $image["fichier"];
-	$dest = $image["fichier_dest"];
-	
-	$creer = $image["creer"];
-	
-	if ($creer) {
-		$im = $image["fonction_imagecreatefrom"]($im);
-		imagepalettetotruecolor($im);
-		$im_ = imagecreatetruecolor($x_i, $y_i);
-		@imagealphablending($im_, false);
-		@imagesavealpha($im_,true);
-	
-		$color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
-		imagefill ($im_, 0, 0, $color_t);
-
-		for ($x = 0; $x < $x_i; $x++) {
-			for ($y = 0; $y < $y_i; $y++) {
-				imagecopy($im_, $im, $x_i - $x - 1, $y, $x, $y, 1, 1);
-			}
-		}
-
-		image_gd_output($im_,$image);
-		imagedestroy($im_);
-		imagedestroy($im);
-	}
-	
-	return image_ecrire_tag($image,array('src'=>$dest));
-}
-
-// http://doc.spip.org/@image_flip_horizontal
-function image_flip_horizontal($im)
-{
-	$fonction = array('image_flip_horizontal', func_get_args());
-	$image = image_valeurs_trans($im, "flip_h",false,$fonction);
-	if (!$image) return("");
-	
-	$x_i = $image["largeur"];
-	$y_i = $image["hauteur"];
-	
-	$im = $image["fichier"];
-	$dest = $image["fichier_dest"];
-	
-	$creer = $image["creer"];
-	
-	if ($creer) {
-		$im = $image["fonction_imagecreatefrom"]($im);
-		imagepalettetotruecolor($im);
-		$im_ = imagecreatetruecolor($x_i, $y_i);
-		@imagealphablending($im_, false);
-		@imagesavealpha($im_,true);
-	
-		$color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
-		imagefill ($im_, 0, 0, $color_t);
-
-		for ($x = 0; $x < $x_i; $x++) {
-			for ($y = 0; $y < $y_i; $y++) {
-   				imagecopy($im_, $im, $x, $y_i - $y - 1, $x, $y, 1, 1);
-			}
-		}
-		image_gd_output($im_,$image);
-		imagedestroy($im_);
-		imagedestroy($im);
-	}
-	
-	return image_ecrire_tag($image,array('src'=>$dest));
-}
-
-// http://doc.spip.org/@image_masque
-function image_masque($im, $masque, $pos="") {
-	// Passer, en plus de l'image d'origine,
-	// une image de "masque": un fichier PNG24 transparent.
-	// Le decoupage se fera selon la transparence du "masque",
-	// et les couleurs seront eclaircies/foncees selon de couleur du masque.
-	// Pour ne pas modifier la couleur, le masque doit etre en gris 50%.
-	//
-	// Si l'image source est plus grande que le masque, alors cette image est reduite a la taille du masque.
-	// Sinon, c'est la taille de l'image source qui est utilisee.
-	//
-	// $pos est une variable libre, qui permet de passer left=..., right=..., bottom=..., top=...
-	// dans ce cas, le pasque est place a ces positions sur l'image d'origine,
-	// et evidemment cette image d'origine n'est pas redimensionnee
-	// 
-	// Positionnement horizontal: text-align=left, right, center
-	// Positionnement vertical : vertical-align: top, bottom, middle
-	// (les positionnements left, right, top, left sont relativement inutiles, mais coherence avec CSS)
-	//
-	// Choix du mode de fusion: mode=masque, normal, eclaircir, obscurcir, produit, difference
-	// masque: mode par defaut
-	// normal: place la nouvelle image par dessus l'ancienne
-	// eclaircir: place uniquement les points plus clairs
-	// obscurcir: place uniquement les points plus fonc'es
-	// produit: multiplie par le masque (points noirs rendent l'image noire, points blancs ne changent rien)
-	// difference: remplit avec l'ecart entre les couleurs d'origine et du masque
-
-	$mode = "masque";
-
-
-	$numargs = func_num_args();
-	$arg_list = func_get_args();
-	$texte = $arg_list[0];
-	for ($i = 1; $i < $numargs; $i++) {
-		if ( ($p = strpos($arg_list[$i],"=")) !==false) {
-			$nom_variable = substr($arg_list[$i], 0, $p);
-			$val_variable = substr($arg_list[$i], $p+1);
-			$variable["$nom_variable"] = $val_variable;
-			$defini["$nom_variable"] = 1;
-		}
-	}
-	if ($defini["mode"]) $mode = $variable["mode"];
-
-	$masque = find_in_path($masque);
-	$pos = md5(serialize($variable).@filemtime($masque));
-
-	$fonction = array('image_masque', func_get_args());
-	$image = image_valeurs_trans($im, "masque-$masque-$pos", "png",$fonction);
-	if (!$image) return("");
-
-	$x_i = $image["largeur"];
-	$y_i = $image["hauteur"];
-	
-	$im = $image["fichier"];
-	$dest = $image["fichier_dest"];
-	
-	$creer = $image["creer"];
-
-
-	if ($defini["right"] OR $defini["left"] OR $defini["bottom"] OR $defini["top"] OR $defini["text-align"] OR $defini["vertical-align"]) {
-		$placer = true;
-	}
-	else $placer = false;
-
-	if ($creer) {
-		
-		$mask = image_valeurs_trans($masque,"");
-		if (!is_array($mask)) return("");
-		$im_m = $mask["fichier"];
-		$x_m = $mask["largeur"];
-		$y_m = $mask["hauteur"];
-	
-		$im2 = $mask["fonction_imagecreatefrom"]($masque);
-		if ($mask["format_source"] == "gif" AND function_exists('ImageCopyResampled')) { 
-			$im2_ = imagecreatetruecolor($x_m, $y_m);
-			// Si un GIF est transparent, 
-			// fabriquer un PNG transparent  
-			// Conserver la transparence 
-			if (function_exists("imageAntiAlias")) imageAntiAlias($im2_,true); 
-			@imagealphablending($im2_, false); 
-			@imagesavealpha($im2_,true); 
-			@ImageCopyResampled($im2_, $im2, 0, 0, 0, 0, $x_m, $y_m, $x_m, $y_m);
-			imagedestroy($im2);
-			$im2 = $im2_;
-		}
-		
-		if ($placer) {
-			// On fabriquer une version "agrandie" du masque,
-			// aux dimensions de l'image source
-			// et on "installe" le masque dans cette image
-			// ainsi: aucun redimensionnement
-			
-			$dx = 0;
-			$dy = 0;
-			
-			if ($defini["right"]) {
-				$right = $variable["right"];
-				$dx = ($x_i - $x_m) - $right;
-			}
-			if ($defini["bottom"]) {
-				$bottom = $variable["bottom"];
-				$dy = ($y_i - $y_m) - $bottom;
-				}
-			if ($defini["top"]) {
-				$top = $variable["top"];
-				$dy = $top;
-			}
-			if ($defini["left"]) {
-				$left = $variable["left"];
-				$dx = $left;
-			}
-			if ($defini["text-align"]) {
-				$align = $variable["text-align"];
-				if ($align == "right") {
-					$right = 0;
-					$dx = ($x_i - $x_m);
-				} else if ($align == "left") {
-					$left = 0;
-					$dx = 0;
-				} else if ($align = "center") {
-					$dx = round( ($x_i - $x_m) / 2 ) ;
-				}
-			}
-			if ($defini["vertical-align"]) {
-				$valign = $variable["vertical-align"];
-				if ($valign == "bottom") {
-					$bottom = 0;
-					$dy = ($y_i - $y_m);
-				} else if ($valign == "top") {
-					$top = 0;
-					$dy = 0;
-				} else if ($valign = "middle") {
-					$dy = round( ($y_i - $y_m) / 2 ) ;
-				}
-			}
-			
-			
-			$im3 = imagecreatetruecolor($x_i, $y_i);
-			@imagealphablending($im3, false);
-			@imagesavealpha($im3,true);
-			if ($mode == "masque") $color_t = ImageColorAllocateAlpha( $im3, 128, 128, 128 , 0 );
-			else $color_t = ImageColorAllocateAlpha( $im3, 128, 128, 128 , 127 );
-			imagefill ($im3, 0, 0, $color_t);
-
-			
-
-			imagecopy ( $im3, $im2, $dx, $dy, 0, 0, $x_m, $y_m);	
-
-			imagedestroy($im2);
-			$im2 = imagecreatetruecolor($x_i, $y_i);
-			@imagealphablending($im2, false);
-			@imagesavealpha($im2,true);
-			
-			
-			
-			imagecopy ( $im2, $im3, 0, 0, 0, 0, $x_i, $y_i);			
-			imagedestroy($im3);
-			$x_m = $x_i;
-			$y_m = $y_i;
-		}
-		
-	
-		$rapport = $x_i / $x_m;
-		if (($y_i / $y_m) < $rapport ) {
-			$rapport = $y_i / $y_m;
-		}
-			
-		$x_d = ceil($x_i / $rapport);
-		$y_d = ceil($y_i / $rapport);
-		
-
-		if ($x_i < $x_m OR $y_i < $y_m) {
-			$x_dest = $x_i;
-			$y_dest = $y_i;
-			$x_dec = 0;
-			$y_dec = 0;
-		} else {
-			$x_dest = $x_m;
-			$y_dest = $y_m;
-			$x_dec = round(($x_d - $x_m) /2);
-			$y_dec = round(($y_d - $y_m) /2);
-		}
-
-
-		$nouveau = image_valeurs_trans(image_reduire($im, $x_d, $y_d),"");
-		if (!is_array($nouveau)) return("");
-		$im_n = $nouveau["fichier"];
-		
-	
-		$im = $nouveau["fonction_imagecreatefrom"]($im_n);
-		imagepalettetotruecolor($im);
-		if ($nouveau["format_source"] == "gif" AND function_exists('ImageCopyResampled')) { 
-			$im_ = imagecreatetruecolor($x_dest, $y_dest);
-			// Si un GIF est transparent, 
-			// fabriquer un PNG transparent  
-			// Conserver la transparence 
-			if (function_exists("imageAntiAlias")) imageAntiAlias($im_,true); 
-			@imagealphablending($im_, false); 
-			@imagesavealpha($im_,true); 
-			@ImageCopyResampled($im_, $im, 0, 0, 0, 0, $x_dest, $y_dest, $x_dest, $y_dest);
-			imagedestroy($im);
-			$im = $im_;
-		}
-		$im_ = imagecreatetruecolor($x_dest, $y_dest);
-		@imagealphablending($im_, false);
-		@imagesavealpha($im_,true);
-		$color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
-		imagefill ($im_, 0, 0, $color_t);
-
-
-		for ($x = 0; $x < $x_dest; $x++) {
-			for ($y=0; $y < $y_dest; $y++) {
-				$rgb = ImageColorAt($im2, $x, $y);
-				$a = ($rgb >> 24) & 0xFF;
-				$r = ($rgb >> 16) & 0xFF;
-				$g = ($rgb >> 8) & 0xFF;
-				$b = $rgb & 0xFF;
-				
-
-				$rgb2 = ImageColorAt($im, $x+$x_dec, $y+$y_dec);
-				$a2 = ($rgb2 >> 24) & 0xFF;
-				$r2 = ($rgb2 >> 16) & 0xFF;
-				$g2 = ($rgb2 >> 8) & 0xFF;
-				$b2 = $rgb2 & 0xFF;
-				
-				
-				
-				if ($mode == "normal") {
-					$v = (127 - $a) / 127;
-					if ($v == 1) {
-						$r_ = $r;
-						$g_ = $g;
-						$b_ = $b;
-					} else {
-						$v2 = (127 - $a2) / 127;
-						if ($v+$v2 == 0) {
-							$r_ = $r2;
-							$g_ = $g2;
-							$b_ = $b2;
-						} else if ($v2 ==0) {
-							$r_ = $r;
-							$g_ = $g;
-							$b_ = $b;
-						} else if ($v == 0) {
-							$r_ = $r2;
-							$g_ = $g2;
-							$b_ = $b2;
-						}else {
-							$r_ = $r + (($r2 - $r) * $v2 * (1 - $v));
-							$g_ = $g + (($g2 - $g) * $v2 * (1 - $v));
-							$b_ = $b + (($b2 - $b) * $v2 * (1 - $v));
-						}
-					}
-					$a_ = min($a,$a2);
-				} elseif ($mode == "produit" OR $mode == "difference") {					
-
-					if ($mode == "produit") {
-						$r = ($r/255) * $r2;
-						$g = ($g/255) * $g2;
-						$b = ($b/255) * $b2;
-					} else if ($mode == "difference") {
-						$r = abs($r-$r2);
-						$g = abs($g-$g2);
-						$b = abs($b-$b2);				
-					}
-
-					$r = max(0, min($r, 255));
-					$g = max(0, min($g, 255));
-					$b = max(0, min($b, 255));
-
-					$v = (127 - $a) / 127;
-					if ($v == 1) {
-						$r_ = $r;
-						$g_ = $g;
-						$b_ = $b;
-					} else {
-						$v2 = (127 - $a2) / 127;
-						if ($v+$v2 == 0) {
-							$r_ = $r2;
-							$g_ = $g2;
-							$b_ = $b2;
-						} else {
-							$r_ = $r + (($r2 - $r) * $v2 * (1 - $v));
-							$g_ = $g + (($g2 - $g) * $v2 * (1 - $v));
-							$b_ = $b + (($b2 - $b) * $v2 * (1 - $v));
-						}
-					}
-
-
-					$a_ = $a2;
-				} elseif ($mode == "eclaircir" OR $mode == "obscurcir") {
-					$v = (127 - $a) / 127;
-					if ($v == 1) {
-						$r_ = $r;
-						$g_ = $g;
-						$b_ = $b;
-					} else {
-						$v2 = (127 - $a2) / 127;
-						if ($v+$v2 == 0) {
-							$r_ = $r2;
-							$g_ = $g2;
-							$b_ = $b2;
-						} else {
-							$r_ = $r + (($r2 - $r) * $v2 * (1 - $v));
-							$g_ = $g + (($g2 - $g) * $v2 * (1 - $v));
-							$b_ = $b + (($b2 - $b) * $v2 * (1 - $v));
-						}
-					}
-					if ($mode == "eclaircir") {
-						$r_ = max ($r_, $r2);
-						$g_ = max ($g_, $g2);
-						$b_ = max ($b_, $b2);
-					} else {
-						$r_ = min ($r_, $r2);
-						$g_ = min ($g_, $g2);
-						$b_ = min ($b_, $b2);					
-					}
-					
-					$a_ = min($a,$a2);
-				} else {
-					$r_ = $r2 + 1 * ($r - 127);
-					$r_ = max(0, min($r_, 255));
-					$g_ = $g2 + 1 * ($g - 127);
-					$g_ = max(0, min($g_, 255));
-					$b_ = $b2 + 1 * ($b - 127);
-					$b_ = max(0, min($b_, 255));
-					
-					$a_ = $a + $a2 - round($a*$a2/127);
-				}
-
-				$color = ImageColorAllocateAlpha( $im_, $r_, $g_, $b_ , $a_ );
-				imagesetpixel ($im_, $x, $y, $color);			
-			}
-		}
-
-		image_gd_output($im_,$image);
-		imagedestroy($im_);
-		imagedestroy($im);
-		imagedestroy($im2);
-
-	}
-	$x_dest = largeur($dest);
-	$y_dest = hauteur($dest);
-	return image_ecrire_tag($image,array('src'=>$dest,'width'=>$x_dest,'height'=>$y_dest));
-}
-
-// Passage de l'image en noir et blanc
-// un noir & blanc "photo" n'est pas "neutre": les composantes de couleur sont
-// ponderees pour obtenir le niveau de gris;
-// on peut ici regler cette ponderation en "pour mille"
-// http://doc.spip.org/@image_nb
-function image_nb($im, $val_r = 299, $val_g = 587, $val_b = 114)
-{
-	$fonction = array('image_nb', func_get_args());
-	$image = image_valeurs_trans($im, "nb-$val_r-$val_g-$val_b",false,$fonction);
-	if (!$image) return("");
-	
-	$x_i = $image["largeur"];
-	$y_i = $image["hauteur"];
-	
-	$im = $image["fichier"];
-	$dest = $image["fichier_dest"];
-	
-	$creer = $image["creer"];
-	
-	// Methode precise
-	// resultat plus beau, mais tres lourd
-	// Et: indispensable pour preserver transparence!
-
-	if ($creer) {
-		// Creation de l'image en deux temps
-		// de facon a conserver les GIF transparents
-		$im = $image["fonction_imagecreatefrom"]($im);
-		imagepalettetotruecolor($im);
-		$im_ = imagecreatetruecolor($x_i, $y_i);
-		@imagealphablending($im_, false);
-		@imagesavealpha($im_,true);
-		$color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
-		imagefill ($im_, 0, 0, $color_t);
-		imagecopy($im_, $im, 0, 0, 0, 0, $x_i, $y_i);
-		
-		for ($x = 0; $x < $x_i; $x++) {
-			for ($y=0; $y < $y_i; $y++) {
-				$rgb = ImageColorAt($im_, $x, $y);
-				$a = ($rgb >> 24) & 0xFF;
-				$r = ($rgb >> 16) & 0xFF;
-				$g = ($rgb >> 8) & 0xFF;
-				$b = $rgb & 0xFF;
-
-				$c = round(($val_r * $r / 1000) + ($val_g * $g / 1000) + ($val_b * $b / 1000));
-				if ($c < 0) $c = 0;
-				if ($c > 254) $c = 254;
-				
-				
-				$color = ImageColorAllocateAlpha( $im_, $c, $c, $c , $a );
-				imagesetpixel ($im_, $x, $y, $color);			
-			}
-		}
-		image_gd_output($im_,$image);
-		imagedestroy($im_);
-		imagedestroy($im);
-	}
-
-	return image_ecrire_tag($image,array('src'=>$dest));
-}
-
-// http://doc.spip.org/@image_flou
-function image_flou($im,$niveau=3)
-{
-	// Il s'agit d'une modification du script blur qu'on trouve un peu partout:
-	// + la transparence est geree correctement
-	// + les dimensions de l'image sont augmentees pour flouter les bords
-	$coeffs = array (
-				array ( 1),
-				array ( 1, 1), 
-				array ( 1, 2, 1),
-				array ( 1, 3, 3, 1),
-				array ( 1, 4, 6, 4, 1),
-				array ( 1, 5, 10, 10, 5, 1),
-				array ( 1, 6, 15, 20, 15, 6, 1),
-				array ( 1, 7, 21, 35, 35, 21, 7, 1),
-				array ( 1, 8, 28, 56, 70, 56, 28, 8, 1),
-				array ( 1, 9, 36, 84, 126, 126, 84, 36, 9, 1),
-				array ( 1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1),
-				array ( 1, 11, 55, 165, 330, 462, 462, 330, 165, 55, 11, 1)
-				);
-	
-	$fonction = array('image_flou', func_get_args());
-	$image = image_valeurs_trans($im, "flou-$niveau", false,$fonction);
-	if (!$image) return("");
-	
-	$x_i = $image["largeur"];
-	$y_i = $image["hauteur"];
-	$sum = pow (2, $niveau);
-
-	$im = $image["fichier"];
-	$dest = $image["fichier_dest"];
-	
-	$creer = $image["creer"];
-	
-	// Methode precise
-	// resultat plus beau, mais tres lourd
-	// Et: indispensable pour preserver transparence!
-
-	if ($creer) {
-		// Creation de l'image en deux temps
-		// de facon a conserver les GIF transparents
-		$im = $image["fonction_imagecreatefrom"]($im);
-		imagepalettetotruecolor($im);
-		$temp1 = imagecreatetruecolor($x_i+$niveau, $y_i);
-		$temp2 = imagecreatetruecolor($x_i+$niveau, $y_i+$niveau);
-		
-		@imagealphablending($temp1, false);
-		@imagesavealpha($temp1,true);
-		@imagealphablending($temp2, false);
-		@imagesavealpha($temp2,true);
-
-		
-		for ($i = 0; $i < $x_i+$niveau; $i++) {
-			for ($j=0; $j < $y_i; $j++) {
-				$suma=0;
-				$sumr=0;
-				$sumg=0;
-				$sumb=0;
-				$sum = 0;
-				$sum_ = 0;
-				for ( $k=0 ; $k <= $niveau ; ++$k ) {
-					$color = imagecolorat($im, $i_ = ($i-$niveau)+$k , $j);
-
-					$a = ($color >> 24) & 0xFF;
-					$r = ($color >> 16) & 0xFF;
-					$g = ($color >> 8) & 0xFF;
-					$b = ($color) & 0xFF;
-					
-					if ($i_ < 0 OR $i_ >= $x_i) $a = 127;
-					
-					$coef = $coeffs[$niveau][$k];
-					$suma += $a*$coef;
-					$ac = ((127-$a) / 127);
-					
-					$ac = $ac*$ac;
-					
-					$sumr += $r * $coef * $ac;
-					$sumg += $g * $coef * $ac;
-					$sumb += $b * $coef * $ac;
-					$sum += $coef * $ac;
-					$sum_ += $coef;
-				}
-				if ($sum > 0) $color = ImageColorAllocateAlpha ($temp1, $sumr/$sum, $sumg/$sum, $sumb/$sum, $suma/$sum_);
-				else $color = ImageColorAllocateAlpha ($temp1, 255, 255, 255, 127);
-				imagesetpixel($temp1,$i,$j,$color);
-			}
-		}
-		imagedestroy($im);
-		for ($i = 0; $i < $x_i+$niveau; $i++) {
-			for ($j=0; $j < $y_i+$niveau; $j++) {
-				$suma=0;
-				$sumr=0;
-				$sumg=0;
-				$sumb=0;
-				$sum = 0;
-				$sum_ = 0;
-				for ( $k=0 ; $k <= $niveau ; ++$k ) {
-					$color = imagecolorat($temp1, $i, $j_ = $j-$niveau+$k);
-					$a = ($color >> 24) & 0xFF;
-					$r = ($color >> 16) & 0xFF;
-					$g = ($color >> 8) & 0xFF;
-					$b = ($color) & 0xFF;
-					if ($j_ < 0 OR $j_ >= $y_i) $a = 127;
-					
-					$suma += $a*$coeffs[$niveau][$k];
-					$ac = ((127-$a) / 127);
-										
-					$sumr += $r * $coeffs[$niveau][$k] * $ac;
-					$sumg += $g * $coeffs[$niveau][$k] * $ac;
-					$sumb += $b * $coeffs[$niveau][$k] * $ac;
-					$sum += $coeffs[$niveau][$k] * $ac;
-					$sum_ += $coeffs[$niveau][$k];
-					
-				}
-				if ($sum > 0) $color = ImageColorAllocateAlpha ($temp2, $sumr/$sum, $sumg/$sum, $sumb/$sum, $suma/$sum_);
-				else $color = ImageColorAllocateAlpha ($temp2, 255, 255, 255, 127);
-				imagesetpixel($temp2,$i,$j,$color);
-			}
-		}
-	
-		image_gd_output($temp2,$image);
-		imagedestroy($temp1);	
-		imagedestroy($temp2);	
-	}
-	
-	return image_ecrire_tag($image,array('src'=>$dest,'width'=>($x_i+$niveau),'height'=>($y_i+$niveau)));
-}
-
-// http://doc.spip.org/@image_RotateBicubic
-function image_RotateBicubic($src_img, $angle, $bicubic=0) {
-   
-   if (round($angle/90)*90 == $angle) {
-		$droit = true;
-   		if (round($angle/180)*180 == $angle) $rot = 180;
-   		else $rot = 90;
-   }
-   else $droit = false;
-   
-  // convert degrees to radians
-   $angle = $angle + 180;
-   $angle = deg2rad($angle);
-  
-
-
-   $src_x = imagesx($src_img);
-   $src_y = imagesy($src_img);
-   
-  
-   $center_x = floor(($src_x-1)/2);
-   $center_y = floor(($src_y-1)/2);
-
-   $cosangle = cos($angle);
-   $sinangle = sin($angle);
-
-	// calculer dimensions en simplifiant angles droits, ce qui evite "floutage"
-	// des rotations a angle droit
-	if (!$droit) {
-	   $corners=array(array(0,0), array($src_x,0), array($src_x,$src_y), array(0,$src_y));
-	
-	   foreach($corners as $key=>$value) {
-		 $value[0]-=$center_x;        //Translate coords to center for rotation
-		 $value[1]-=$center_y;
-		 $temp=array();
-		 $temp[0]=$value[0]*$cosangle+$value[1]*$sinangle;
-		 $temp[1]=$value[1]*$cosangle-$value[0]*$sinangle;
-		 $corners[$key]=$temp;    
-	   }
-	   
-	   $min_x=1000000000000000;
-	   $max_x=-1000000000000000;
-	   $min_y=1000000000000000;
-	   $max_y=-1000000000000000;
-	   
-	   foreach($corners as $key => $value) {
-		 if($value[0]<$min_x)
-		   $min_x=$value[0];
-		 if($value[0]>$max_x)
-		   $max_x=$value[0];
-	   
-		 if($value[1]<$min_y)
-		   $min_y=$value[1];
-		 if($value[1]>$max_y)
-		   $max_y=$value[1];
-	   }
-	
-	   $rotate_width=ceil($max_x-$min_x);
-	   $rotate_height=ceil($max_y-$min_y);
-   }
-   else {
-   	if ($rot == 180) {
-   		$rotate_height = $src_y;
-   		$rotate_width = $src_x;
-   	} else {
-   		$rotate_height = $src_x;
-   		$rotate_width = $src_y;
-   	}
-   	$bicubic = false;
-   }
-   
-   
-   $rotate=imagecreatetruecolor($rotate_width,$rotate_height);
-   imagealphablending($rotate, false);
-   imagesavealpha($rotate, true);
-
-   $cosangle = cos($angle);
-   $sinangle = sin($angle);
-   
-	// arrondir pour rotations angle droit (car cos et sin dans {-1,0,1})
-	if ($droit) {
-		$cosangle = round($cosangle);
-		$sinangle = round($sinangle);
-	}
-
-   $newcenter_x = ($rotate_width-1)/2;
-   $newcenter_y = ($rotate_height-1)/2;
-
-   
-   for ($y = 0; $y < $rotate_height; $y++) {
-     for ($x = 0; $x < $rotate_width; $x++) {
-   // rotate...
-       $old_x = ((($newcenter_x-$x) * $cosangle + ($newcenter_y-$y) * $sinangle))
-         + $center_x;
-       $old_y = ((($newcenter_y-$y) * $cosangle - ($newcenter_x-$x) * $sinangle))
-         + $center_y;  
-         
-         $old_x = ceil($old_x);
-         $old_y = ceil($old_y);
-         
-   if ( $old_x >= 0 && $old_x < $src_x
-         && $old_y >= 0 && $old_y < $src_y ) {
-     if ($bicubic == true) {
-       $xo = $old_x;
-       $x0 = floor($xo);
-       $x1 = ceil($xo);
-       $yo = $old_y;
-       $y0 = floor($yo);
-       $y1 = ceil($yo);
-       
-		// on prend chaque point, mais on pondere en fonction de la distance
-		$rgb = ImageColorAt($src_img, $x0, $y0); 
-		$a1 = ($rgb >> 24) & 0xFF;
-		$r1 = ($rgb >> 16) & 0xFF;
-		$g1 = ($rgb >> 8) & 0xFF;
-		$b1 = $rgb & 0xFF;
-		$d1 = image_distance_pixel($xo, $yo, $x0, $y0);
-
-		$rgb = ImageColorAt($src_img, $x1, $y0); 
-		$a2 = ($rgb >> 24) & 0xFF;
-		$r2 = ($rgb >> 16) & 0xFF;
-		$g2 = ($rgb >> 8) & 0xFF;
-		$b2 = $rgb & 0xFF;
-		$d2 = image_distance_pixel($xo, $yo, $x1, $y0);
-
-		$rgb = ImageColorAt($src_img,$x0, $y1); 
-		$a3 = ($rgb >> 24) & 0xFF;
-		$r3 = ($rgb >> 16) & 0xFF;
-		$g3 = ($rgb >> 8) & 0xFF;
-		$b3 = $rgb & 0xFF;
-		$d3 = image_distance_pixel($xo, $yo, $x0, $y1);
-
-		$rgb = ImageColorAt($src_img,$x1, $y1);
-		$a4 = ($rgb >> 24) & 0xFF;
-		$r4 = ($rgb >> 16) & 0xFF;
-		$g4 = ($rgb >> 8) & 0xFF;
-		$b4 = $rgb & 0xFF;
-		$d4 = image_distance_pixel($xo, $yo, $x1, $y1);
-
-		$ac1 = ((127-$a1) / 127);
-		$ac2 = ((127-$a2) / 127);
-		$ac3 = ((127-$a3) / 127);
-		$ac4 = ((127-$a4) / 127);
-		
-		// limiter impact des couleurs transparentes, 
-		// mais attention tout transp: division par 0
-		if ($ac1*$d1 + $ac2*$d2 + $ac3+$d3 + $ac4+$d4 > 0) {
-			if ($ac1 > 0) $d1 = $d1 * $ac1;
-			if ($ac2 > 0) $d2 = $d2 * $ac2;
-			if ($ac3 > 0) $d3 = $d3 * $ac3;
-			if ($ac4 > 0) $d4 = $d4 * $ac4;
-		}
-		
-		$tot  = $d1 + $d2 + $d3 + $d4;
-
-       $r = round((($d1*$r1)+($d2*$r2)+($d3*$r3)+($d4*$r4))/$tot);
-       $g = round((($d1*$g1+($d2*$g2)+$d3*$g3+$d4*$g4))/$tot);
-       $b = round((($d1*$b1+($d2*$b2)+$d3*$b3+$d4*$b4))/$tot);
-       $a = round((($d1*$a1+($d2*$a2)+$d3*$a3+$d4*$a4))/$tot);
-        $color = imagecolorallocatealpha($src_img, $r,$g,$b,$a);
-     } else {
-       $color = imagecolorat($src_img, round($old_x), round($old_y));
-     }
-   } else {
-         // this line sets the background colour
-     $color = imagecolorallocatealpha($src_img, 255, 255, 255, 127);
-   }
-   @imagesetpixel($rotate, $x, $y, $color);
-     }
-   }
-   return $rotate;
-}
-
-// permet de faire tourner une image d'un angle quelconque
-// la fonction "crop" n'est pas implementee...
-// http://doc.spip.org/@image_rotation
-function image_rotation($im, $angle, $crop=false)
-{
-	$fonction = array('image_rotation', func_get_args());
-	$image = image_valeurs_trans($im, "rot-$angle-$crop", "png", $fonction);
-	if (!$image) return("");
-	
-	$im = $image["fichier"];
-	$dest = $image["fichier_dest"];
-	
-	$creer = $image["creer"];
-	
-	if ($creer) {
-		$effectuer_gd = true;
-
-		if (function_exists('imagick_rotate')) {
-			$mask = imagick_getcanvas( "#ff0000", $x, $y );
-			$handle = imagick_readimage ($im);
-			if ($handle && imagick_isopaqueimage( $handle )) {
-				imagick_rotate( $handle, $angle);
-				imagick_writeimage( $handle, $dest);
-				$effectuer_gd = false;
-			}
-		}
-		elseif(is_callable(array('Imagick','rotateImage'))){
-			$imagick = new Imagick();
-			$imagick->readImage($im);
-			$imagick->rotateImage(new ImagickPixel('#ffffff'), $angle);
-			$imagick->writeImage($dest);
-			$effectuer_gd = false;
-		}
-		if ($effectuer_gd) {
-			// Creation de l'image en deux temps
-			// de facon a conserver les GIF transparents
-			$im = $image["fonction_imagecreatefrom"]($im);
-			imagepalettetotruecolor($im);
-			$im = image_RotateBicubic($im, $angle, true);
-			image_gd_output($im,$image);
-			imagedestroy($im);
-		}
-	}
-	list ($src_y,$src_x) = taille_image($dest);
-	return image_ecrire_tag($image,array('src'=>$dest,'width'=>$src_x,'height'=>$src_y));
-}
-
-// Permet d'appliquer un filtre php_imagick a une image
-// par exemple: [(#LOGO_ARTICLE||image_imagick{imagick_wave,20,60})]
-// liste des fonctions: http://www.linux-nantes.org/~fmonnier/doc/imagick/
-// http://doc.spip.org/@image_imagick
-function image_imagick () {
-	$tous = func_get_args();
-	$img = $tous[0];
-	$fonc = $tous[1];
-	$tous[0]="";
-	$tous_var = join($tous, "-");
-
-	$fonction = array('image_imagick', func_get_args());
-	$image = image_valeurs_trans($img, "$tous_var", "png",$fonction);
-	if (!$image) return("");
-	
-	$im = $image["fichier"];
-	$dest = $image["fichier_dest"];
-	
-	$creer = $image["creer"];
-	
-	if ($creer) {
-		if (function_exists($fonc)) {
-
-			$handle = imagick_readimage ($im);
-			$arr[0] = $handle;
-			for ($i=2; $i < count($tous); $i++) $arr[] = $tous[$i];
-			call_user_func_array($fonc, $arr);
-			// Creer image dans fichier temporaire, puis renommer vers "bon" fichier
-			// de facon a eviter time_out pendant creation de l'image definitive
-			$tmp = preg_replace(",[.]png$,i", "-tmp.png", $dest);
-			imagick_writeimage( $handle, $tmp);
-			rename($tmp, $dest);
-			ecrire_fichier($dest.".src",serialize($image));
-		} 
-	}
-	list ($src_y,$src_x) = taille_image($dest);
-	return image_ecrire_tag($image,array('src'=>$dest,'width'=>$src_x,'height'=>$src_y));
-
-}
-
-
-// $src_img - a GD image resource
-// $angle - degrees to rotate clockwise, in degrees
-// returns a GD image resource
-// script de php.net lourdement corrig'e
-// (le bicubic deconnait completement,
-// et j'ai ajoute la ponderation par la distance au pixel)
-
-// http://doc.spip.org/@image_distance_pixel
-function image_distance_pixel($xo, $yo, $x0, $y0) {
-	$vx = $xo - $x0;
-	$vy = $yo - $y0;
-	$d = 1 - (sqrt(($vx)*($vx) + ($vy)*($vy)) / sqrt(2));
-	return $d;
-}
-
-// http://doc.spip.org/@image_decal_couleur
-function image_decal_couleur($coul, $gamma) {
-	$coul = $coul + $gamma;
-	
-	if ($coul > 255) $coul = 255;
-	if ($coul < 0) $coul = 0;
-	return $coul;
-}
-// Permet de rendre une image
-// plus claire (gamma > 0)
-// ou plus foncee (gamma < 0)
-// http://doc.spip.org/@image_gamma
-function image_gamma($im, $gamma = 0)
-{
-	$fonction = array('image_gamma', func_get_args());
-	$image = image_valeurs_trans($im, "gamma-$gamma",false,$fonction);
-	if (!$image) return("");
-	
-	$x_i = $image["largeur"];
-	$y_i = $image["hauteur"];
-	
-	$im = $image["fichier"];
-	$dest = $image["fichier_dest"];
-	
-	$creer = $image["creer"];
-	
-	if ($creer) {
-		// Creation de l'image en deux temps
-		// de facon a conserver les GIF transparents
-		$im = $image["fonction_imagecreatefrom"]($im);
-		imagepalettetotruecolor($im);
-		$im_ = imagecreatetruecolor($x_i, $y_i);
-		@imagealphablending($im_, false);
-		@imagesavealpha($im_,true);
-		$color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
-		imagefill ($im_, 0, 0, $color_t);
-		imagecopy($im_, $im, 0, 0, 0, 0, $x_i, $y_i);
-	
-		for ($x = 0; $x < $x_i; $x++) {
-			for ($y=0; $y < $y_i; $y++) {
-				$rgb = ImageColorAt($im_, $x, $y);
-				$a = ($rgb >> 24) & 0xFF;
-				$r = ($rgb >> 16) & 0xFF;
-				$g = ($rgb >> 8) & 0xFF;
-				$b = $rgb & 0xFF;
-
-				$r = image_decal_couleur($r, $gamma);
-				$g = image_decal_couleur($g, $gamma);
-				$b = image_decal_couleur($b, $gamma);
-
-				$color = ImageColorAllocateAlpha( $im_, $r, $g, $b , $a );
-				imagesetpixel ($im_, $x, $y, $color);			
-			}
-		}
-		image_gd_output($im_,$image);
-	}
-	return image_ecrire_tag($image,array('src'=>$dest));
-}
-
-// Passe l'image en "sepia"
-// On peut fixer les valeurs RVB 
-// de la couleur "complementaire" pour forcer une dominante
-
-// http://doc.spip.org/@image_decal_couleur_127
-function image_decal_couleur_127 ($coul, $val) {
-	if ($coul < 127) $y = round((($coul - 127) / 127) * $val) + $val;
-	else if ($coul >= 127) $y = round((($coul - 127) / 128) * (255-$val)) + $val;
-	else $y= $coul;
-	
-	if ($y < 0) $y = 0;
-	if ($y > 255) $y = 255;
-	return $y;
-}
-//function image_sepia($im, $dr = 137, $dv = 111, $db = 94)
-// http://doc.spip.org/@image_sepia
-function image_sepia($im, $rgb = "896f5e")
-{
-	
-	if (!function_exists("imagecreatetruecolor")) return $im;
-	
-	$couleurs = couleur_hex_to_dec($rgb);
-	$dr= $couleurs["red"];
-	$dv= $couleurs["green"];
-	$db= $couleurs["blue"];
-		
-	$fonction = array('image_sepia', func_get_args());
-	$image = image_valeurs_trans($im, "sepia-$dr-$dv-$db",false,$fonction);
-	if (!$image) return("");
-	
-	$x_i = $image["largeur"];
-	$y_i = $image["hauteur"];
-	
-	$im = $image["fichier"];
-	$dest = $image["fichier_dest"];
-	
-	$creer = $image["creer"];
-	
-	if ($creer) {
-		// Creation de l'image en deux temps
-		// de facon a conserver les GIF transparents
-		$im = $image["fonction_imagecreatefrom"]($im);
-		imagepalettetotruecolor($im);
-		$im_ = imagecreatetruecolor($x_i, $y_i);
-		@imagealphablending($im_, false);
-		@imagesavealpha($im_,true);
-		$color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
-		imagefill ($im_, 0, 0, $color_t);
-		imagecopy($im_, $im, 0, 0, 0, 0, $x_i, $y_i);
-	
-		for ($x = 0; $x < $x_i; $x++) {
-			for ($y=0; $y < $y_i; $y++) {
-				$rgb = ImageColorAt($im_, $x, $y);
-				$a = ($rgb >> 24) & 0xFF;
-				$r = ($rgb >> 16) & 0xFF;
-				$g = ($rgb >> 8) & 0xFF;
-				$b = $rgb & 0xFF;
-
-				$r = round(.299 * $r + .587 * $g + .114 * $b);
-				$g = $r;
-				$b = $r;
-
-
-				$r = image_decal_couleur_127($r, $dr);
-				$g = image_decal_couleur_127($g, $dv);
-				$b = image_decal_couleur_127($b, $db);
-
-				$color = ImageColorAllocateAlpha( $im_, $r, $g, $b , $a );
-				imagesetpixel ($im_, $x, $y, $color);			
-			}
-		}
-		image_gd_output($im_,$image);
-		imagedestroy($im_);
-		imagedestroy($im);
-	}
-	
-	return image_ecrire_tag($image,array('src'=>$dest));
-}
-
-
-// Renforcer la nettete d'une image
-// http://doc.spip.org/@image_renforcement
-function image_renforcement($im, $k=0.5)
-{
-	$fonction = array('image_flou', func_get_args());
-	$image = image_valeurs_trans($im, "renforcement-$k",false,$fonction);
-	if (!$image) return("");
-	
-	$x_i = $image["largeur"];
-	$y_i = $image["hauteur"];
-	$im = $image["fichier"];
-	$dest = $image["fichier_dest"];
-	$creer = $image["creer"];
-	
-	if ($creer) {
-		$im = $image["fonction_imagecreatefrom"]($im);
-		imagepalettetotruecolor($im);
-		$im_ = imagecreatetruecolor($x_i, $y_i);
-		@imagealphablending($im_, false);
-		@imagesavealpha($im_,true);
-		$color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
-		imagefill ($im_, 0, 0, $color_t);
-
-		for ($x = 0; $x < $x_i; $x++) {
-			for ($y=0; $y < $y_i; $y++) {		
-
-                $rgb[1][0]=imagecolorat($im,$x,$y-1);
-                $rgb[0][1]=imagecolorat($im,$x-1,$y);
-                $rgb[1][1]=imagecolorat($im,$x,$y);
-                $rgb[2][1]=imagecolorat($im,$x+1,$y);
-                $rgb[1][2]=imagecolorat($im,$x,$y+1);
-                
-                
-                if ($x-1 < 0) $rgb[0][1] = $rgb[1][1];
-                if ($y-1 < 0) $rgb[1][0] = $rgb[1][1];
-                if ($x+1 == $x_i) $rgb[2][1] = $rgb[1][1];
-                if ($y+1 == $y_i) $rgb[1][2] = $rgb[1][1];
-
-                $a = ($rgb[0][0] >> 24) & 0xFF;
-                $r = -$k *(($rgb[1][0] >> 16) & 0xFF) +
-                         -$k *(($rgb[0][1] >> 16) & 0xFF) +
-                        (1+4*$k) *(($rgb[1][1] >> 16) & 0xFF) +
-                         -$k *(($rgb[2][1] >> 16) & 0xFF) +
-                         -$k *(($rgb[1][2] >> 16) & 0xFF) ;
-
-                $g = -$k *(($rgb[1][0] >> 8) & 0xFF) +
-                         -$k *(($rgb[0][1] >> 8) & 0xFF) +
-                         (1+4*$k) *(($rgb[1][1] >> 8) & 0xFF) +
-                         -$k *(($rgb[2][1] >> 8) & 0xFF) +
-                         -$k *(($rgb[1][2] >> 8) & 0xFF) ;
-
-                $b = -$k *($rgb[1][0] & 0xFF) +
-                         -$k *($rgb[0][1] & 0xFF) +
-                        (1+4*$k) *($rgb[1][1] & 0xFF) +
-                         -$k *($rgb[2][1] & 0xFF) +
-                         -$k *($rgb[1][2] & 0xFF) ;
-
-                $r=min(255,max(0,$r));
-                $g=min(255,max(0,$g));
-                $b=min(255,max(0,$b));
-
-
-		$color = ImageColorAllocateAlpha( $im_, $r, $g, $b , $a );
-		imagesetpixel ($im_, $x, $y, $color);			
-			}
-		}		
-		image_gd_output($im_,$image);
-	}
-
-	return image_ecrire_tag($image,array('src'=>$dest));
-}
-
-
-// 1/ Aplatir une image semi-transparente (supprimer couche alpha)
-// en remplissant la transparence avec couleur choisir $coul.
-// 2/ Forcer le format de sauvegarde (jpg, png, gif)
-// pour le format jpg, $qualite correspond au niveau de compression (defaut 85)
-// pour le format gif, $qualite correspond au nombre de couleurs dans la palette (defaut 128)
-// pour le format png, $qualite correspond au nombre de couleur dans la palette ou si 0 a une image truecolor (defaut truecolor)
-// attention, seul 128 est supporte en l'etat (production d'images avec palette reduite pas satisfaisante)
-// http://doc.spip.org/@image_aplatir
-// 3/ $transparence a "true" permet de conserver la transparence (utile pour conversion GIF)
-// http://doc.spip.org/@image_aplatir
-function image_aplatir($im, $format='jpg', $coul='000000', $qualite=NULL, $transparence=false)
-{
-	if ($qualite===NULL){
-		if ($format=='jpg') $qualite=_IMG_GD_QUALITE;
-		elseif ($format=='png') $qualite=0;
-		else $qualite=128;
-	}
-	$fonction = array('image_aplatir', func_get_args());
-	$image = image_valeurs_trans($im, "aplatir-$format-$coul-$qualite-$transparence", $format, $fonction);
-
-	if (!$image) return("");
-
-	include_spip('inc/filtres');
-	$couleurs = couleur_hex_to_dec($coul);
-	$dr= $couleurs["red"];
-	$dv= $couleurs["green"];
-	$db= $couleurs["blue"];
-
-	$x_i = $image["largeur"];
-	$y_i = $image["hauteur"];
-	
-	$im = $image["fichier"];
-	$dest = $image["fichier_dest"];
-	
-	$creer = $image["creer"];
-
-	if ($creer) {
-		$im = @$image["fonction_imagecreatefrom"]($im);
-		imagepalettetotruecolor($im);
-		$im_ = imagecreatetruecolor($x_i, $y_i);
-		if ($image["format_source"] == "gif" AND function_exists('ImageCopyResampled')) { 
-			// Si un GIF est transparent, 
-			// fabriquer un PNG transparent  
-			// Conserver la transparence 
-			@imagealphablending($im_, false); 
-			@imagesavealpha($im_,true); 
-			if (function_exists("imageAntiAlias")) imageAntiAlias($im_,true); 
-			@ImageCopyResampled($im_, $im, 0, 0, 0, 0, $x_i, $y_i, $x_i, $y_i);
-			imagedestroy($im);
-			$im = $im_;
-		}
-		
-		// allouer la couleur de fond
-		if ($transparence) {
-			@imagealphablending($im_, false); 
-			@imagesavealpha($im_,true); 
-			$color_t = imagecolorallocatealpha( $im_, $dr, $dv, $db, 127);
-		}
-		else $color_t = ImageColorAllocate( $im_, $dr, $dv, $db);
-		
-		imagefill ($im_, 0, 0, $color_t);
-
-		//??
-		//$dist = abs($trait);
-		
-		$transp_x = false;
-		
-		for ($x = 0; $x < $x_i; $x++) {
-			for ($y=0; $y < $y_i; $y++) {
-			
-				$rgb = ImageColorAt($im, $x, $y);
-				$a = ($rgb >> 24) & 0xFF;
-				$r = ($rgb >> 16) & 0xFF;
-				$g = ($rgb >> 8) & 0xFF;
-				$b = $rgb & 0xFF;
-
-				$a = (127-$a) / 127;
-				
-				if ($a == 1) { // Limiter calculs
-					$r = $r;
-					$g = $g;
-					$b = $b;
-				}
-				else if ($a == 0) { // Limiter calculs
-					$r = $dr;
-					$g = $dv;
-					$b = $db;
-					
-					$transp_x = $x; // Memoriser un point transparent
-					$transp_y = $y;
-					
-				} else {
-					$r = round($a * $r + $dr * (1-$a));
-					$g = round($a * $g + $dv * (1-$a));
-					$b = round($a * $b + $db * (1-$a));
-				}
-				$a = (1-$a) *127;
-				$color = ImageColorAllocateAlpha( $im_, $r, $g, $b, $a);
-				imagesetpixel ($im_, $x, $y, $color);	
-			}
-		}
-		// passer en palette si besoin
-		if ($format=='gif' OR ($format=='png' AND $qualite!==0)){
-			// creer l'image finale a palette (on recycle l'image initiale)			
-
-
-			@imagetruecolortopalette($im,true,$qualite);
-
-
-			//$im = imagecreate($x_i, $y_i);
-			// copier l'image true color vers la palette
-			imagecopy($im, $im_, 0, 0, 0, 0, $x_i, $y_i);
-			// matcher les couleurs au mieux par rapport a l'image initiale
-			// si la fonction est disponible (php>=4.3)
-			if (function_exists('imagecolormatch'))
-				@imagecolormatch($im_, $im);
-				
-			if ($format=='gif' && $transparence && $transp_x) {	
-				$color_t = ImagecolorAt( $im, $transp_x, $transp_y);
-				if ($format == "gif" && $transparence) @imagecolortransparent($im, $color_t);
-			}
-				
-				
-			// produire le resultat
-			image_gd_output($im, $image, $qualite);
-		}
-		else
-			image_gd_output($im_, $image, $qualite);
-		imagedestroy($im_);
-		imagedestroy($im);
-	}
-	return image_ecrire_tag($image,array('src'=>$dest));
-}
-
-
-// Enregistrer une image dans un format donne
-// (conserve la transparence gif, png, ico)
-// utilise [->@image_aplatir]
-// http://doc.spip.org/@image_format
-function image_format($img, $format='png') {
-	return image_aplatir($img, $format, 'cccccc', null, true);
-}
-
-
-
-// A partir d'une image,
-// recupere une couleur
-// renvoit sous la forme hexadecimale ("F26C4E" par exemple).
-// Par defaut, la couleur choisie se trouve un peu au-dessus du centre de l'image.
-// On peut forcer un point en fixant $x et $y, entre 0 et 20.
-// http://doc.spip.org/@image_couleur_extraire
-function image_couleur_extraire($img, $x=10, $y=6) {
-
-	$cache = image_valeurs_trans($img, "coul-$x-$y", "php");
-	if (!$cache) return "F26C4E";
-	
-	$fichier = $cache["fichier"];
-	$dest = $cache["fichier_dest"];
-	$terminaison = $cache["format_source"];
-	
-	$creer = $cache["creer"];
-	if ($creer) {
-		if (!$GLOBALS["couleur_extraite"]["$fichier-$x-$y"]) {	
-			if (file_exists($fichier)) {
-				list($width, $height) = getimagesize($fichier);
-			
-			
-				$newwidth = 20;
-				$newheight = 20;
-			
-				$thumb = imagecreate($newwidth, $newheight);
-
-				if (preg_match(",\.jpe?g$,i", $fichier)) $source = imagecreatefromjpeg($fichier);
-				if (preg_match(",\.gif$,i", $fichier)) $source = imagecreatefromgif($fichier);
-				if (preg_match(",\.png$,i", $fichier)) $source = imagecreatefrompng($fichier);
-				imagepalettetotruecolor($source);
-
-				imagecopyresized($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
-			
-				// get a color
-				$color_index = imagecolorat($thumb, $x, $y);
-				
-				// make it human readable
-				$color_tran = imagecolorsforindex($thumb, $color_index);
-				
-				$couleur = couleur_dec_to_hex($color_tran["red"], $color_tran["green"], $color_tran["blue"]);
-			}
-			else {
-				$couleur = "F26C4E";
-			}
-			$GLOBALS["couleur_extraite"]["$fichier-$x-$y"] = $couleur;
-
-			$handle = fopen($dest, 'w');
-			fwrite($handle, "<"."?php \$GLOBALS[\"couleur_extraite\"][\"".$fichier."-".$x."-".$y."\"] = \"".$couleur."\"; ?".">");
-			fclose($handle);
-		
-		}
-		// Mettre en cache le resultat
-		
-	} else {
-		include("$dest");
-	}
-	
-	
-	return $GLOBALS["couleur_extraite"]["$fichier-$x-$y"];
-}
-
-// http://doc.spip.org/@couleur_html_to_hex
-function couleur_html_to_hex($couleur){
-	$couleurs_html=array(
-		'aqua'=>'00FFFF','black'=>'000000','blue'=>'0000FF','fuchsia'=>'FF00FF','gray'=>'808080','green'=>'008000','lime'=>'00FF00','maroon'=>'800000',
-		'navy'=>'000080','olive'=>'808000','purple'=>'800080','red'=>'FF0000','silver'=>'C0C0C0','teal'=>'008080','white'=>'FFFFFF','yellow'=>'FFFF00');
-	if (isset($couleurs_html[$lc=strtolower($couleur)]))
-		return $couleurs_html[$lc];
-	return $couleur;
-}
-
-// http://doc.spip.org/@couleur_dec_to_hex
-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;
-	
-	return "$red$green$blue";
-}
-
-// http://doc.spip.org/@couleur_hex_to_dec
-function couleur_hex_to_dec($couleur) {
-	$couleur = couleur_html_to_hex($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;
-}
-
-// http://doc.spip.org/@couleur_multiple_de_trois
-function couleur_multiple_de_trois($val) {
-	$val = hexdec($val);
-	$val = round($val / 3) * 3;
-	$val = dechex($val);
-	return $val;
-	
-}
-
-// http://doc.spip.org/@couleur_web
-function couleur_web($couleur) {
-	$r = couleur_multiple_de_trois(substr($couleur, 0, 1));
-	$v = couleur_multiple_de_trois(substr($couleur, 2, 1));
-	$b = couleur_multiple_de_trois(substr($couleur, 4, 1));
-	
-	return "$r$r$v$v$b$b";
-}
-
-// http://doc.spip.org/@couleur_4096
-function couleur_4096($couleur) {
-	$r = (substr($couleur, 0, 1));
-	$v = (substr($couleur, 2, 1));
-	$b = (substr($couleur, 4, 1));
-	
-	return "$r$r$v$v$b$b";
-}
-
-
-// http://doc.spip.org/@couleur_extreme
-function couleur_extreme ($couleur, $limite=0.5) {
-	// force la couleur au noir ou au blanc le plus proche
-	// -> donc couleur foncee devient noire
-	//    et couleur claire devient blanche
-	// -> la limite est une valeur de 0 a 255, permettant de regler le point limite entre le passage noir ou blanc
-
-	$couleurs = couleur_hex_to_dec($couleur);
-	$red = $couleurs["red"];
-	$green = $couleurs["green"];
-	$blue = $couleurs["blue"];
-	
-	
-	/*	
-	$moyenne = round(($red+$green+$blue)/3);
-
-	if ($moyenne > $limite) $couleur_texte = "ffffff";
-	else $couleur_texte = "000000";
-	*/
-
-	$hsl = couleur_rgb2hsl ($red, $green, $blue);
-
-	if ($hsl["l"] > $limite) $couleur_texte = "ffffff";
-	else $couleur_texte = "000000";
-
-	return $couleur_texte;
-}
-
-// http://doc.spip.org/@couleur_inverser
-function couleur_inverser ($couleur) {
-	$couleurs = couleur_hex_to_dec($couleur);
-	$red = 255 - $couleurs["red"];
-	$green = 255 - $couleurs["green"];
-	$blue = 255 - $couleurs["blue"];
-
-	$couleur = couleur_dec_to_hex($red, $green, $blue);
-	
-	return $couleur;
-}
-
-// http://doc.spip.org/@couleur_eclaircir
-function couleur_eclaircir ($couleur) {
-	$couleurs = couleur_hex_to_dec($couleur);
-
-	$red = $couleurs["red"] + round((255 - $couleurs["red"])/2);
-	$green = $couleurs["green"] + round((255 - $couleurs["green"])/2);
-	$blue = $couleurs["blue"] + round((255 - $couleurs["blue"])/2);
-
-	$couleur = couleur_dec_to_hex($red, $green, $blue);
-	
-	return $couleur;
-
-}
-// http://doc.spip.org/@couleur_foncer
-function couleur_foncer ($couleur) {
-	$couleurs = couleur_hex_to_dec($couleur);
-
-	$red = $couleurs["red"] - round(($couleurs["red"])/2);
-	$green = $couleurs["green"] - round(($couleurs["green"])/2);
-	$blue = $couleurs["blue"] - round(($couleurs["blue"])/2);
-
-	$couleur = couleur_dec_to_hex($red, $green, $blue);
-	
-	return $couleur;
-}
-// http://doc.spip.org/@couleur_foncer_si_claire
-function couleur_foncer_si_claire ($couleur) {
-	// ne foncer que les couleurs claires
-	// utile pour ecrire sur fond blanc, 
-	// mais sans changer quand la couleur est deja foncee
-	$couleurs = couleur_hex_to_dec($couleur);
-	$red = $couleurs["red"];
-	$green = $couleurs["green"];
-	$blue = $couleurs["blue"];
-	
-	$moyenne = round(($red+$green+$blue)/3);
-	
-	if ($moyenne > 122) return couleur_foncer($couleur);
-	else return $couleur;
-}
-// http://doc.spip.org/@couleur_eclaircir_si_foncee
-function couleur_eclaircir_si_foncee ($couleur) {
-	$couleurs = couleur_hex_to_dec($couleur);
-	$red = $couleurs["red"];
-	$green = $couleurs["green"];
-	$blue = $couleurs["blue"];
-	
-	$moyenne = round(($red+$green+$blue)/3);
-	
-	if ($moyenne < 123) return couleur_eclaircir($couleur);
-	else return $couleur;
-}
-
-
-// http://doc.spip.org/@couleur_saturation
-function couleur_saturation($couleur, $val) {
-	if ($couleur == "ffffff") $couleur = "eeeeee";
-
-	$couleurs = couleur_hex_to_dec($couleur);
-	$r= 255 - $couleurs["red"];
-	$g= 255 - $couleurs["green"];
-	$b= 255 - $couleurs["blue"];
-
-	$max = max($r,$g,$b);
-
-	$r = 255 - $r / $max * 255 * $val;
-	$g = 255 - $g / $max * 255 * $val;
-	$b = 255 - $b / $max * 255 * $val;
-	
-	$couleur = couleur_dec_to_hex($r, $g, $b);
-	
-	return $couleur;
-		
-}
-
-
-
-// http://doc.spip.org/@couleur_rgb2hsv
-function couleur_rgb2hsv ($R,$G,$B) {
-	$var_R = ( $R / 255 ) ;                    //Where RGB values = 0 ÷ 255
-	$var_G = ( $G / 255 );
-	$var_B = ( $B / 255 );
-
-	$var_Min = min( $var_R, $var_G, $var_B ) ;   //Min. value of RGB
-	$var_Max = max( $var_R, $var_G, $var_B ) ;   //Max. value of RGB
-	$del_Max = $var_Max - $var_Min  ;           //Delta RGB value
-
-	$V = $var_Max;
-	$L = ( $var_Max + $var_Min ) / 2;
-	
-	if ( $del_Max == 0 )                     //This is a gray, no chroma...
-	{
-	   $H = 0 ;                            //HSL results = 0 ÷ 1
-	   $S = 0 ;
-	}
-	else                                    //Chromatic data...
-	{
-	   $S = $del_Max / $var_Max;
-	
-	   $del_R = ( ( ( $var_Max - $var_R ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
-	   $del_G = ( ( ( $var_Max - $var_G ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
-	   $del_B = ( ( ( $var_Max - $var_B ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
-	
-	   if      ( $var_R == $var_Max ) $H = $del_B - $del_G;
-	   else if ( $var_G == $var_Max ) $H = ( 1 / 3 ) + $del_R - $del_B;
-	   else if ( $var_B == $var_Max ) $H = ( 2 / 3 ) + $del_G - $del_R;
-	
-	   if ( $H < 0 )  $H =  $H + 1;
-	   if ( $H > 1 )  $H = $H - 1;
-	}
-				
-	$ret["h"] = $H;
-	$ret["s"] = $S;
-	$ret["v"] = $V;
-	
-	return $ret;
-}
-
-
-// http://doc.spip.org/@couleur_hsv2rgb
-function couleur_hsv2rgb ($H,$S,$V) {
-	
-	if ( $S == 0 )                       //HSV values = 0 ÷ 1
-	{
-	   $R = $V * 255;
-	   $G = $V * 255;
-	   $B = $V * 255;
-	}
-	else
-	{
-	   $var_h = $H * 6;
-	   if ( $var_h == 6 ) $var_h = 0 ;     //H must be < 1
-	   $var_i = floor( $var_h )  ;           //Or ... var_i = floor( var_h )
-	   $var_1 = $V * ( 1 - $S );
-	   $var_2 = $V * ( 1 - $S * ( $var_h - $var_i ) );
-	   $var_3 = $V * ( 1 - $S * ( 1 - ( $var_h - $var_i ) ) );
-	
-	
-	   if      ( $var_i == 0 ) { $var_r = $V     ; $var_g = $var_3 ; $var_b = $var_1 ; }
-	   else if ( $var_i == 1 ) { $var_r = $var_2 ; $var_g = $V     ; $var_b = $var_1 ; }
-	   else if ( $var_i == 2 ) { $var_r = $var_1 ; $var_g = $V     ; $var_b = $var_3 ; }
-	   else if ( $var_i == 3 ) { $var_r = $var_1 ; $var_g = $var_2 ; $var_b = $V ;     }
-	   else if ( $var_i == 4 ) { $var_r = $var_3 ; $var_g = $var_1 ; $var_b = $V ; }
-	   else                   { $var_r = $V     ; $var_g = $var_1 ; $var_b = $var_2; }
-	
-	   $R = $var_r * 255;                  //RGB results = 0 ÷ 255
-	   $G = $var_g * 255;
-	   $B = $var_b * 255;
-	}
-	$ret["r"] = floor($R);
-	$ret["g"] = floor($G);
-	$ret["b"] = floor($B);
-	
-	return $ret;
-}
-
-
-// http://doc.spip.org/@couleur_rgb2hsl
-function couleur_rgb2hsl ($R,$G,$B) {
-	$var_R = ( $R / 255 ) ;                    //Where RGB values = 0 ÷ 255
-	$var_G = ( $G / 255 );
-	$var_B = ( $B / 255 );
-
-	$var_Min = min( $var_R, $var_G, $var_B ) ;   //Min. value of RGB
-	$var_Max = max( $var_R, $var_G, $var_B ) ;   //Max. value of RGB
-	$del_Max = $var_Max - $var_Min  ;           //Delta RGB value
-
-	$L = ( $var_Max + $var_Min ) / 2;
-	
-	if ( $del_Max == 0 )                     //This is a gray, no chroma...
-	{
-	   $H = 0 ;                            //HSL results = 0 ÷ 1
-	   $S = 0 ;
-	}
-	else                                    //Chromatic data...
-	{
-		if ($L < 0.5 ) $S = $del_Max / ( $var_Max+ $var_Min);
-		else $S = $del_Max/ ( 2 - $var_Max - $var_Min);
-
-		$del_R = ( ( ( $var_Max- $var_R) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
-		$del_G = ( ( ( $var_Max- $var_G) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
-		$del_B = ( ( ( $var_Max- $var_B) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
-
-		if ( $var_R == $var_Max) $H= $del_B - $del_G;
-		else if ( $var_G == $var_Max) $H= ( 1 / 3 ) + $del_R - $del_B;
-		else if ( $var_B == $var_Max) $H= ( 2 / 3 ) + $del_G - $del_R;
-
-		if ( $H < 0 ) $H+= 1;
-		if ( $H > 1 ) $H-= 1;
-	}
-				
-	$ret["h"] = $H;
-	$ret["s"] = $S;
-	$ret["l"] = $L;
-	
-	return $ret;
-}
-
-
-// http://doc.spip.org/@hue_2_rgb
-function hue_2_rgb( $v1, $v2, $vH ) {
-   if ( $vH < 0 ) $vH += 1;
-   if ( $vH > 1 ) $vH -= 1;
-   if ( ( 6 * $vH ) < 1 ) return ( $v1 + ( $v2 - $v1 ) * 6 * $vH );
-   if ( ( 2 * $vH ) < 1 ) return ( $v2 );
-   if ( ( 3 * $vH ) < 2 ) return ( $v1 + ( $v2 - $v1 ) * ( ( 2 / 3 ) - $vH ) * 6 );
-   return ( $v1 );
-}
-
-// http://doc.spip.org/@couleur_hsl2rgb
-function couleur_hsl2rgb ($H,$S,$L) {
-	
-	if ( $S == 0 )                       //HSV values = 0 ÷ 1
-	{
-	   $R = $V * 255;
-	   $G = $V * 255;
-	   $B = $V * 255;
-	}
-	else
-	{
-		if ( $L < 0.5 ) $var_2 = $L * ( 1 + $S );
-		else            $var_2 = ( $L + $S ) - ( $S * $L );
-
-		$var_1 = 2 * $L - $var_2;
-
-		$R = 255 * hue_2_rgb( $var_1, $var_2, $H + ( 1 / 3 ) ) ;
-		$G = 255 * hue_2_rgb( $var_1, $var_2, $H );
-		$B = 255 * hue_2_rgb( $var_1, $var_2, $H - ( 1 / 3 ) );
-	}
-	$ret["r"] = floor($R);
-	$ret["g"] = floor($G);
-	$ret["b"] = floor($B);
-	
-	return $ret;
-}
-
-
-
-
-// Image typographique
-
-// Fonctions pour l'arabe
-
-
-// http://doc.spip.org/@rtl_mb_ord
-function rtl_mb_ord($char){
-
-	if (($c = ord($char)) < 216) return $c;
-	else return 256 * rtl_mb_ord(substr($char, 0, -1)) + ord(substr($char, -1));
-
-/*	return (strlen($char) < 2) ?
-		ord($char) : 256 * mb_ord(substr($char, 0, -1))
-			+ ord(substr($char, -1));
-			
-*/			
-  }
-
-
-
-// http://doc.spip.org/@rtl_reverse
-function rtl_reverse($mot, $rtl_global) {
-
-	$ponctuations = array("«","»", "“", "”", ",", ".", " ", ":", ";", "(", ")", "،", "؟", "?", "!", " ");
-	foreach($ponctuations as $ponct) {
-		$ponctuation[$ponct] = true;
-	}
-
-		
-
-	for ($i = 0; $i < spip_strlen($mot); $i++) {
-		$lettre = spip_substr($mot, $i, 1);
-		
-		
-		$code = rtl_mb_ord($lettre);
-//		echo "<li>$lettre - $code";
-
-		
-//			echo "<li>$code";
-		if (($code >= 54928 && $code <= 56767) ||  ($code >= 15707294 && $code <= 15711164)) {
-			$rtl = true;
-		}
-		else $rtl = false;
-		
-		if ($lettre == "٠" || $lettre == "١" || $lettre == "٢" || $lettre == "٣" || $lettre == "٤" || $lettre == "٥"
-				 || $lettre == "٦" || $lettre == "٧" || $lettre == "٨" || $lettre == "٩") $rtl = false;
-		
-		if ($ponctuation[$lettre]) {
-			$rtl = $rtl_global;
-			
-			if ($rtl) {
-				switch ($lettre) {
-					case "(": $lettre = ")"; break;
-					case ")": $lettre = "("; break;
-					case "«": $lettre = "»"; break;
-					case "»": $lettre = "«"; break;
-					case "“": $lettre = "”"; break;
-					case "”": $lettre = "“"; break;
-				}
-			}
-		}
-		
-		
-		if ($rtl) $res = $lettre.$res;
-		else $res = $res.$lettre;
-		
-	}
-	return $res;
-}
-
-
-
-// http://doc.spip.org/@rtl_visuel
-function rtl_visuel($texte, $rtl_global) {
-	// hebreu + arabe: 54928 => 56767
-	// hebreu + presentation A: 15707294 => 15710140
-	// arabe presentation: 15708336 => 15711164
-	
-//	echo hexdec("efb7bc");
-
-	// premiere passe pour determiner s'il y a du rtl
-	// de facon a placer ponctuation et mettre les mots dans l'ordre
-	
-
-
-
-	$arabic_letters = array(
-		array("ي", // lettre 0
-			"ﻱ",  // isolee 1
-			"ﻳ", // debut 2
-			"ﻴ", // milieu 3
-			"ﻲ"),
-		array("ب", // lettre 0
-			"ﺏ",  // isolee 1
-			"ﺑ", // debut 2
-			"ﺒ", // milieu 3
-			"ﺐ"),
-		array("ا", // lettre 0
-			"ا",  // isolee 1
-			"ﺍ", // debut 2
-			"ﺍ", // milieu 3
-			"ﺎ"),
-		array("إ", // lettre 0
-			"إ",  // isolee 1
-			"إ", // debut 2
-			"ﺈ", // milieu 3
-			"ﺈ"),
-		array("ل", // lettre 0
-			"ﻝ",  // isolee 1
-			"ﻟ", // debut 2
-			"ﻠ", // milieu 3
-			"ﻞ"),
-		array("خ", // lettre 0
-			"ﺥ",  // isolee 1
-			"ﺧ", // debut 2
-			"ﺨ", // milieu 3
-			"ﺦ"),
-		array("ج", // lettre 0
-			"ﺝ",  // isolee 1
-			"ﺟ", // debut 2
-			"ﺠ", // milieu 3
-			"ﺞ"),
-		array("س", // lettre 0
-			"ﺱ",  // isolee 1
-			"ﺳ", // debut 2
-			"ﺴ", // milieu 3
-			"ﺲ"),
-		array("ن", // lettre 0
-			"ﻥ",  // isolee 1
-			"ﻧ", // debut 2
-			"ﻨ", // milieu 3
-			"ﻦ"),
-		array("ش", // lettre 0
-			"ﺵ",  // isolee 1
-			"ﺷ", // debut 2
-			"ﺸ", // milieu 3
-			"ﺶ"),
-		array("ق", // lettre 0
-			"ﻕ",  // isolee 1
-			"ﻗ", // debut 2
-			"ﻘ", // milieu 3
-			"ﻖ"),
-		array("ح", // lettre 0
-			"ﺡ",  // isolee 1
-			"ﺣ", // debut 2
-			"ﺤ", // milieu 3
-			"ﺢ"),
-		array("م", // lettre 0
-			"ﻡ",  // isolee 1
-			"ﻣ", // debut 2
-			"ﻤ", // milieu 3
-			"ﻢ"),
-		array("ر", // lettre 0
-			"ر",  // isolee 1
-			"ﺭ", // debut 2
-			"ﺮ", // milieu 3
-			"ﺮ"),
-		array("ع", // lettre 0
-			"ع",  // isolee 1
-			"ﻋ", // debut 2
-			"ﻌ", // milieu 3
-			"ﻊ"),
-		array("و", // lettre 0
-			"و",  // isolee 1
-			"ﻭ", // debut 2
-			"ﻮ", // milieu 3
-			"ﻮ"),
-		array("ة", // lettre 0
-			"ة",  // isolee 1
-			"ة", // debut 2
-			"ﺔ", // milieu 3
-			"ﺔ"),
-		array("ف", // lettre 0
-			"ﻑ",  // isolee 1
-			"ﻓ", // debut 2
-			"ﻔ", // milieu 3
-			"ﻒ"),
-		array("ﻻ", // lettre 0
-			"ﻻ",  // isolee 1
-			"ﻻ", // debut 2
-			"ﻼ", // milieu 3
-			"ﻼ"),
-		array("ح", // lettre 0
-			"ﺡ",  // isolee 1
-			"ﺣ", // debut 2
-			"ﺤ", // milieu 3
-			"ﺢ"),
-		array("ت", // lettre 0
-			"ﺕ",  // isolee 1
-			"ﺗ", // debut 2
-			"ﺘ", // milieu 3
-			"ﺖ"),
-		array("ض", // lettre 0
-			"ﺽ",  // isolee 1
-			"ﺿ", // debut 2
-			"ﻀ", // milieu 3
-			"ﺾ"),
-		array("ك", // lettre 0
-			"ك",  // isolee 1
-			"ﻛ", // debut 2
-			"ﻜ", // milieu 3
-			"ﻚ"),
-		array("ه", // lettre 0
-			"ﻩ",  // isolee 1
-			"ﻫ", // debut 2
-			"ﻬ", // milieu 3
-			"ﻪ"),
-		array("ي", // lettre 0
-			"ي",  // isolee 1
-			"ﻳ", // debut 2
-			"ﻴ", // milieu 3
-			"ﻲ"),
-		array("ئ", // lettre 0
-			"ﺉ",  // isolee 1
-			"ﺋ", // debut 2
-			"ﺌ", // milieu 3
-			"ﺊ"),
-		array("ص", // lettre 0
-			"ﺹ",  // isolee 1
-			"ﺻ", // debut 2
-			"ﺼ", // milieu 3
-			"ﺺ"),
-		array("ث", // lettre 0
-			"ﺙ",  // isolee 1
-			"ﺛ", // debut 2
-			"ﺜ", // milieu 3
-			"ﺚ"),
-		array("ﻷ", // lettre 0
-			"ﻷ",  // isolee 1
-			"ﻷ", // debut 2
-			"ﻸ", // milieu 3
-			"ﻸ"),
-		array("د", // lettre 0
-			"ﺩ",  // isolee 1
-			"ﺩ", // debut 2
-			"ﺪ", // milieu 3
-			"ﺪ"),
-		array("ذ", // lettre 0
-			"ﺫ",  // isolee 1
-			"ﺫ", // debut 2
-			"ﺬ", // milieu 3
-			"ﺬ"),
-		array("ط", // lettre 0
-			"ﻁ",  // isolee 1
-			"ﻃ", // debut 2
-			"ﻄ", // milieu 3
-			"ﻂ"),
-		array("آ", // lettre 0
-			"آ",  // isolee 1
-			"آ", // debut 2
-			"ﺂ", // milieu 3
-			"ﺂ"),
-		array("أ", // lettre 0
-			"أ",  // isolee 1
-			"أ", // debut 2
-			"ﺄ", // milieu 3
-			"ﺄ"),
-		array("ؤ", // lettre 0
-			"ؤ",  // isolee 1
-			"ؤ", // debut 2
-			"ﺆ", // milieu 3
-			"ﺆ"),
-		array("ز", // lettre 0
-			"ز",  // isolee 1
-			"ز", // debut 2
-			"ﺰ", // milieu 3
-			"ﺰ"),
-		array("ظ", // lettre 0
-			"ظ",  // isolee 1
-			"ﻇ", // debut 2
-			"ﻈ", // milieu 3
-			"ﻆ"),
-		array("غ", // lettre 0
-			"غ",  // isolee 1
-			"ﻏ", // debut 2
-			"ﻐ", // milieu 3
-			"ﻎ"),
-		array("ى", // lettre 0
-			"ى",  // isolee 1
-			"ﯨ", // debut 2
-			"ﯩ", // milieu 3
-			"ﻰ"),
-		array("پ", // lettre 0
-			"پ",  // isolee 1
-			"ﭘ", // debut 2
-			"ﭙ", // milieu 3
-			"ﭗ"),
-		array("چ", // lettre 0
-			"چ",  // isolee 1
-			"ﭼ", // debut 2
-			"ﭽ", // milieu 3
-			"ﭻ")
-	);
-	
-	if(init_mb_string() AND mb_regex_encoding() !== "UTF-8") echo "Attention: dans php.ini, il faut indiquer:<br /><strong>mbstring.internal_encoding = UTF-8</strong>";
-	
-	
-	$texte = explode(" ", $texte);
-	
-	foreach ($texte as $mot) {
-		$res = "";
-
-
-
-		// Inserer des indicateurs de debut/fin
-		$mot = "^".$mot."^";
-
-		$mot = preg_replace(",&nbsp;,u", " ", $mot);
-		$mot = preg_replace(",&#171;,u", "«", $mot);
-		$mot = preg_replace(",&#187;,u", "»", $mot);
-
-
-
-
-		// ponctuations
-		$ponctuations = array("«","»", "“", "”", ",", ".", " ", ":", ";", "(", ")", "،", "؟", "?", "!"," ");
-		foreach($ponctuations as $ponct) {
-			$mot = str_replace("$ponct", "^$ponct^", $mot);
-		}
-
-		// lettres forcant coupure
-		$mot = preg_replace(",ا,u", "ا^", $mot);
-		$mot = preg_replace(",د,u", "د^", $mot);
-		$mot = preg_replace(",أ,u", "أ^", $mot);
-		$mot = preg_replace(",إ,u", "إ^", $mot);
-		$mot = preg_replace(",أ,u", "أ^", $mot);
-		$mot = preg_replace(",ر,u", "ر^", $mot);
-		$mot = preg_replace(",ذ,u", "ذ^", $mot);
-		$mot = preg_replace(",ز,u", "ز^", $mot);
-		$mot = preg_replace(",و,u", "و^", $mot);
-		$mot = preg_replace(",و,u", "و^", $mot);
-		$mot = preg_replace(",ؤ,u", "ؤ^", $mot);
-		$mot = preg_replace(",ة,u", "ة^", $mot);
-		//		$mot = preg_replace(",ل,u", "^ل", $mot);
-		//		$mot = preg_replace(",,", "^", $mot);
-
-
-		$mot = preg_replace(",٠,u", "^٠^", $mot);
-		$mot = preg_replace(",١,u", "^١^", $mot);
-		$mot = preg_replace(",٢,u", "^٢^", $mot);
-		$mot = preg_replace(",٣,u", "^٣^", $mot);
-		$mot = preg_replace(",٤,u", "^٤^", $mot);
-		$mot = preg_replace(",٥,u", "^٥^", $mot);
-		$mot = preg_replace(",٦,u", "^٦^", $mot);
-		$mot = preg_replace(",٧,u", "^٧^", $mot);
-		$mot = preg_replace(",٨,u", "^٨^", $mot);
-		$mot = preg_replace(",٩,u", "^٩^", $mot);
-
-
-		// Ligatures
-		$mot = preg_replace(",لا,u", "ﻻ", $mot);
-		$mot = preg_replace(",لأ,u", "ﻷ", $mot);
-		
-		
-		foreach ($arabic_letters as $a_l) {
-			$mot = preg_replace(",([^\^])".$a_l[0]."([^\^]),u", "\\1".$a_l[3]."\\2", $mot);
-			$mot = preg_replace(",\^".$a_l[0]."([^\^]),u", "^".$a_l[2]."\\1", $mot);
-			$mot = preg_replace(",([^\^])".$a_l[0]."\^,u", "\\1".$a_l[4]."^", $mot);
-			// il semble qu'il ne soit pas necessaire de remplacer
-			// la lettre isolee
-			//			$mot = preg_replace(",\^".$a_l[0]."\^,u", "^".$a_l[1]."^", $mot);
-		}
-		
-		
-
-		$mot = preg_replace(",\^,u", "", $mot);
-		
-		$res = $mot;
-		$res = rtl_reverse($mot, $rtl_global);
-
-		/*
-		$rtl = false;		
-		for ($i = 0; $i < spip_strlen($mot); $i++) {
-			$lettre = spip_substr($mot, $i, 1);
-			$code = rtl_mb_ord($lettre);
-			if (($code >= 54928 && $code <= 56767) ||  ($code >= 15708336 && $code <= 15711164)) $rtl = true;
-		}
-		*/
-		
-		
-		if ($rtl_global) $retour = $res . " " . $retour;
-		else $retour = $retour. " ".$res;
-	}
-	
-	
-	return $retour;
-}
-
-
-
-
-// http://doc.spip.org/@printWordWrapped
-function printWordWrapped($image, $top, $left, $maxWidth, $font, $couleur, $text, $textSize, $align="left", $hauteur_ligne = 0) {
-	static $memps = array();
-
-	// imageftbbox exige un float, et settype aime le double pour php < 4.2.0
-	settype($textSize, 'double');
-
-	// calculer les couleurs ici, car fonctionnement different selon TTF ou PS
-	$black = imagecolorallocatealpha($image, hexdec("0x{".substr($couleur, 0,2)."}"), hexdec("0x{".substr($couleur, 2,2)."}"), hexdec("0x{".substr($couleur, 4,2)."}"), 0);
-	$grey2 = imagecolorallocatealpha($image, hexdec("0x{".substr($couleur, 0,2)."}"), hexdec("0x{".substr($couleur, 2,2)."}"), hexdec("0x{".substr($couleur, 4,2)."}"), 127);
-
-	// Gaffe, T1Lib ne fonctionne carrement pas bien des qu'on sort de ASCII
-	// C'est dommage, parce que la rasterisation des caracteres est autrement plus jolie qu'avec TTF.
-	// A garder sous le coude en attendant que ca ne soit plus une grosse bouse.
-	// Si police Postscript et que fonction existe...
-	if (
-	false AND
-	strtolower(substr($font,-4)) == ".pfb"
-	AND function_exists("imagepstext")) {
-		// Traitement specifique pour polices PostScript (experimental)
-		$textSizePs = round(1.32 * $textSize);
-		if (!$fontps = $memps["$font"]) {
-			$fontps = imagepsloadfont($font);
-			// Est-ce qu'il faut reencoder? Pas testable proprement, alors... 
-			// imagepsencodefont($fontps,find_in_path('polices/standard.enc'));
-			$memps["$font"] = $fontps;
-		}
-	}
-
-	$rtl_global = false;
-	for ($i = 0; $i < spip_strlen($text); $i++) {
-		$lettre = spip_substr($text, $i, 1);
-		$code = rtl_mb_ord($lettre);
-		if (($code >= 54928 && $code <= 56767) ||  ($code >= 15707294 && $code <= 15711164)) {
-			$rtl_global = true;
-		}
-	}
-
-
-	// split the text into an array of single words
-	$words = explode(' ', $text);
-
-	// les espaces
-	foreach($words as $k=>$v)
-		$words[$k] = str_replace(array('~'), array(' '), $v);
-
-
-	if ($hauteur_ligne == 0) $lineHeight = floor($textSize * 1.3);
-	else $lineHeight = $hauteur_ligne;
-
-	$dimensions_espace = imageftbbox($textSize, 0, $font, ' ', array());
-	$largeur_espace = $dimensions_espace[2] - $dimensions_espace[0];
-	$retour["espace"] = $largeur_espace;
-
-
-	$line = '';
-	while (count($words) > 0) {
-		
-		$mot = $words[0];
-		
-		if ($rtl_global) $mot = rtl_visuel($mot,$rtl_global);
-	
-		$dimensions = imageftbbox($textSize, 0, $font, $line.' '.$mot, array());
-		$lineWidth = $dimensions[2] - $dimensions[0]; // get the length of this line, if the word is to be included
-		if ($lineWidth > $maxWidth) { // if this makes the text wider that anticipated
-			$lines[] = $line; // add the line to the others
-			$line = ''; // empty it (the word will be added outside the loop)
-		}
-		$line .= ' '.$words[0]; // add the word to the current sentence
-		$words = array_slice($words, 1); // remove the word from the array
-	}
-	if ($line != '') { $lines[] = $line; } // add the last line to the others, if it isn't empty
-	$height = count($lines) * $lineHeight; // the height of all the lines total
-	// do the actual printing
-	$i = 0;
-
-	// Deux passes pour recuperer, d'abord, largeur_ligne
-	// necessaire pour alignement right et center
-	foreach ($lines as $line) {
-		if ($rtl_global) $line = rtl_visuel($line, $rtl_global);
-		
-		$dimensions = imageftbbox($textSize, 0, $font, $line, array());
-		$largeur_ligne = $dimensions[2] - $dimensions[0];
-		if ($largeur_ligne > $largeur_max) $largeur_max = $largeur_ligne;
-	}
-
-	foreach ($lines as $i => $line) {
-		if ($rtl_global) $line = rtl_visuel($line, $rtl_global);
-
-		$dimensions = imageftbbox($textSize, 0, $font, $line, array());
-		$largeur_ligne = $dimensions[2] - $dimensions[0];
-		if ($align == "right") $left_pos = $largeur_max - $largeur_ligne;
-		else if ($align == "center") $left_pos = floor(($largeur_max - $largeur_ligne)/2);
-		else $left_pos = 0;
-		
-		
-		if ($fontps) {
-			$line = trim($line);
-			imagepstext ($image, "$line", $fontps, $textSizePs, $black, $grey2, $left + $left_pos, $top + $lineHeight * $i, 0, 0, 0, 16);
-		}
-		else imagefttext($image, $textSize, 0, $left + $left_pos, $top + $lineHeight * $i, $black, $font, trim($line), array());
-	}
-	$retour["height"] = $height;# + round(0.3 * $hauteur_ligne);
-	$retour["width"] = $largeur_max;
-                 
-	return $retour;
-}
-//array imagefttext ( resource image, float size, float angle, int x, int y, int col, string font_file, string text [, array extrainfo] )
-//array imagettftext ( resource image, float size, float angle, int x, int y, int color, string fontfile, string text )
-
-// http://doc.spip.org/@produire_image_typo
-function produire_image_typo() {
-	/*
-	arguments autorises:
-	
-	$texte : le texte a transformer; attention: c'est toujours le premier argument, et c'est automatique dans les filtres
-	$couleur : la couleur du texte dans l'image - pas de dieze
-	$police: nom du fichier de la police (inclure terminaison)
-	$largeur: la largeur maximale de l'image ; attention, l'image retournee a une largeur inferieure, selon les limites reelles du texte
-	$hauteur_ligne: la hauteur de chaque ligne de texte si texte sur plusieurs lignes
-	(equivalent a "line-height")
-	$padding: forcer de l'espace autour du placement du texte; necessaire pour polices a la con qui "depassent" beaucoup de leur boite 
-	$align: alignement left, right, center
-	*/
-
-
-
-	// Recuperer les differents arguments
-	$numargs = func_num_args();
-	$arg_list = func_get_args();
-	$texte = $arg_list[0];
-	for ($i = 1; $i < $numargs; $i++) {
-		if (($p = strpos($arg_list[$i], "="))!==FALSE) {
-			$nom_variable = substr($arg_list[$i], 0, $p);
-			$val_variable = substr($arg_list[$i], $p+1);
-		
-			$variable["$nom_variable"] = $val_variable;
-		}
-		
-	}
-
-	// Construire requete et nom fichier
-	$text = str_replace("&nbsp;", "~", $texte);	
-	$text = preg_replace(",(\r|\n)+,ms", " ", $text);
-	include_spip('inc/charsets');
-	$text = html2unicode(strip_tags($text));
-	if (strlen($text) == 0) return "";
-
-	$taille = $variable["taille"];
-	if ($taille < 1) $taille = 16;
-
-	$couleur = couleur_html_to_hex($variable["couleur"]);
-	if (strlen($couleur) < 6) $couleur = "000000";
-
-	$alt = $texte;
-		
-	$align = $variable["align"];
-	if (!$variable["align"]) $align="left";
-	 
-	$police = $variable["police"];
-	if (strlen($police) < 2) $police = "dustismo.ttf";
-
-	$largeur = $variable["largeur"];
-	if ($largeur < 5) $largeur = 600;
-
-	if ($variable["hauteur_ligne"] > 0) $hauteur_ligne = $variable["hauteur_ligne"];
-	else $hauteur_ligne = 0;
-	if ($variable["padding"] > 0) $padding = $variable["padding"];
-	else $padding = 0;
-	
-
-
-	$string = "$text-$taille-$couleur-$align-$police-$largeur-$hauteur_ligne-$padding";
-	$query = md5($string);
-	$dossier = sous_repertoire(_DIR_VAR, 'cache-texte');
-	$fichier = "$dossier$query.png";
-
-	$flag_gd_typo = function_exists("imageftbbox")
-		&& function_exists('imageCreateTrueColor');
-
-	
-	if (file_exists($fichier))
-		$image = $fichier;
-	else if (!$flag_gd_typo)
-		return $texte;
-	else {
-		$font = find_in_path('polices/'.$police);
-		if (!$font) {
-			spip_log(_T('fichier_introuvable', array('fichier' => $police)));
-			$font = find_in_path('polices/'."dustismo.ttf");
-		}
-
-		$imgbidon = imageCreateTrueColor($largeur, 45);
-		$retour = printWordWrapped($imgbidon, $taille+5, 0, $largeur, $font, $couleur, $text, $taille, 'left', $hauteur_ligne);
-		$hauteur = $retour["height"];
-		$largeur_reelle = $retour["width"];
-		$espace = $retour["espace"];
-		imagedestroy($imgbidon);
-
-		$im = imageCreateTrueColor($largeur_reelle-$espace+(2*$padding), $hauteur+5+(2*$padding));
-		imagealphablending ($im, FALSE );
-		imagesavealpha ( $im, TRUE );
-		
-		// Creation de quelques couleurs
-		
-		$grey2 = imagecolorallocatealpha($im, hexdec("0x{".substr($couleur, 0,2)."}"), hexdec("0x{".substr($couleur, 2,2)."}"), hexdec("0x{".substr($couleur, 4,2)."}"), 127);
-		ImageFilledRectangle ($im,0,0,$largeur_reelle+(2*$padding),$hauteur+5+(2*$padding),$grey2);
-		
-		// Le texte a dessiner
-		printWordWrapped($im, $taille+5+$padding, $padding, $largeur, $font, $couleur, $text, $taille, $align, $hauteur_ligne);
-		
-		
-		// Utiliser imagepng() donnera un texte plus claire,
-		// compare a l'utilisation de la fonction imagejpeg()
-		imagepng($im, $fichier);
-		imagedestroy($im);
-		
-		$image = $fichier;
-	}
-
-
-	$dimensions = getimagesize($image);
-	$largeur = $dimensions[0];
-	$hauteur = $dimensions[1];
-	return inserer_attribut("<img src='$image' width='$largeur' height='$hauteur' style='width:".$largeur."px;height:".$hauteur."px;' />", 'alt', $alt);
-}
-
-
-
-//
-// Produire des fichiers au format .ico
-// avec du code recupere de :
-//
-//////////////////////////////////////////////////////////////
-///  phpThumb() by James Heinrich <info@silisoftware.com>   //
-//        available at http://phpthumb.sourceforge.net     ///
-//////////////////////////////////////////////////////////////
-class phpthumb_functions {
-// http://doc.spip.org/@GetPixelColor
-	function GetPixelColor(&$img, $x, $y) {
-		if (!is_resource($img)) {
-			return false;
-		}
-		return @ImageColorsForIndex($img, @ImageColorAt($img, $x, $y));
-	}
-// http://doc.spip.org/@LittleEndian2String
-	function LittleEndian2String($number, $minbytes=1) {
-		$intstring = '';
-		while ($number > 0) {
-			$intstring = $intstring.chr($number & 255);
-			$number >>= 8;
-		}
-		return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT);
-	}
-// http://doc.spip.org/@GD2ICOstring
-	function GD2ICOstring(&$gd_image_array) {
-		foreach ($gd_image_array as $key => $gd_image) {
-
-			$ImageWidths[$key]  = ImageSX($gd_image);
-			$ImageHeights[$key] = ImageSY($gd_image);
-			$bpp[$key]		  = ImageIsTrueColor($gd_image) ? 32 : 24;
-			$totalcolors[$key]  = ImageColorsTotal($gd_image);
-
-			$icXOR[$key] = '';
-			for ($y = $ImageHeights[$key] - 1; $y >= 0; $y--) {
-				for ($x = 0; $x < $ImageWidths[$key]; $x++) {
-					$argb = phpthumb_functions::GetPixelColor($gd_image, $x, $y);
-					$a = round(255 * ((127 - $argb['alpha']) / 127));
-					$r = $argb['red'];
-					$g = $argb['green'];
-					$b = $argb['blue'];
-
-					if ($bpp[$key] == 32) {
-						$icXOR[$key] .= chr($b).chr($g).chr($r).chr($a);
-					} elseif ($bpp[$key] == 24) {
-						$icXOR[$key] .= chr($b).chr($g).chr($r);
-					}
-
-					if ($a < 128) {
-						@$icANDmask[$key][$y] .= '1';
-					} else {
-						@$icANDmask[$key][$y] .= '0';
-					}
-				}
-				// mask bits are 32-bit aligned per scanline
-				while (strlen($icANDmask[$key][$y]) % 32) {
-					$icANDmask[$key][$y] .= '0';
-				}
-			}
-			$icAND[$key] = '';
-			foreach ($icANDmask[$key] as $y => $scanlinemaskbits) {
-				for ($i = 0; $i < strlen($scanlinemaskbits); $i += 8) {
-					$icAND[$key] .= chr(bindec(str_pad(substr($scanlinemaskbits, $i, 8), 8, '0', STR_PAD_LEFT)));
-				}
-			}
-
-		}
-
-		foreach ($gd_image_array as $key => $gd_image) {
-			$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;
-			// 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;
-		}
-
-
-		$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 .= "\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($dwImageOffset, 4);	  // dwImageOffset;   // Where in the file is this image?
-			$dwImageOffset += strlen($BitmapInfoHeader[$key]);
-			$dwImageOffset += strlen($icXOR[$key]);
-			$dwImageOffset += strlen($icAND[$key]);
-		}
-
-		foreach ($gd_image_array as $key => $gd_image) {
-			$icondata .= $BitmapInfoHeader[$key];
-			$icondata .= $icXOR[$key];
-			$icondata .= $icAND[$key];
-		}
-
-		return $icondata;
-	}
-
-}
-
-?>
\ No newline at end of file
diff --git a/ecrire/inc/filtres_images_mini.php b/ecrire/inc/filtres_images_mini.php
new file mode 100644
index 0000000000..a05e31eb53
--- /dev/null
+++ b/ecrire/inc/filtres_images_mini.php
@@ -0,0 +1,825 @@
+<?php
+
+/***************************************************************************\
+ *  SPIP, Systeme de publication pour l'internet                           *
+ *                                                                         *
+ *  Copyright (c) 2001-2008                                                *
+ *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
+ *                                                                         *
+ *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
+ *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
+\***************************************************************************/
+
+
+if (!defined("_ECRIRE_INC_VERSION")) return;
+include_spip('inc/filtres'); // par precaution
+
+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;
+}
+
+// http://doc.spip.org/@cherche_image_nommee
+function cherche_image_nommee($nom, $formats = array ('gif', 'jpg', 'png')) {
+
+	if (strncmp(_DIR_IMG, $nom,$n=strlen(_DIR_IMG))==0) {
+		$nom = substr($nom,$n);
+	} else 	if (strncmp(_DIR_IMG_PACK, $nom,$n=strlen(_DIR_IMG_PACK))==0) {
+		$nom = substr($nom,$n);
+	} else if (strncmp(_DIR_IMG_ICONE_DIST, $nom,$n=strlen(_DIR_IMG_ICONES_DIST))==0) {
+		$nom = substr($nom,$n);
+	}
+	$pos = strrpos($nom, "/");
+	if ($pos > 0) {
+		$chemin = substr($nom, 0, $pos+1);
+		$nom = substr($nom, $pos+1);
+	} else {
+		$chemin = "";
+	}
+
+	reset($formats);
+	while (list(, $format) = each($formats)) {
+		if (@file_exists(_DIR_IMG . "$chemin$nom.$format")){ 
+			return array((_DIR_IMG . $chemin), $nom, $format);
+		} else if (@file_exists(_DIR_IMG_PACK . "$chemin$nom.$format")){ 
+			return array((_DIR_IMG_PACK . $chemin), $nom, $format);
+		} else if (@file_exists(_DIR_IMG_ICONES_DIST . "$chemin$nom.$format")){ 
+			return array((_DIR_IMG_ICONES_DIST . $chemin), $nom, $format);
+		}
+	}
+}
+
+// Fonctions de traitement d'image
+// uniquement pour GD2
+// http://doc.spip.org/@image_valeurs_trans
+function image_valeurs_trans($img, $effet, $forcer_format = false, $fonction_creation = NULL) {
+	static $images_recalcul = array();
+	if (strlen($img)==0) return false;
+	
+	$source = trim(extraire_attribut($img, 'src'));
+	if (strlen($source) < 1){
+		$source = $img;
+		$img = "<img src='$source' />";
+	}
+
+	// les protocoles web prennent au moins 3 lettres
+	if (preg_match(';^(\w{3,7}://);', $source)){
+		include_spip('inc/distant');
+		$fichier = _DIR_RACINE . copie_locale($source);
+		if (!$fichier) return "";
+	}	else {
+		// enlever le timestamp eventuel
+		$source=preg_replace(',[?][0-9]+$,','',$source);
+		$fichier = $source;
+	}
+
+	$terminaison_dest = "";
+	if (preg_match(",^(?>.*)(?<=\.(gif|jpg|png)),", $fichier, $regs)) {
+		$terminaison = $regs[1];
+		$terminaison_dest = $terminaison;
+		
+		if ($terminaison == "gif") $terminaison_dest = "png";
+	}
+	if ($forcer_format!==false) $terminaison_dest = $forcer_format;
+
+	if (!$terminaison_dest) return false;
+
+	$term_fonction = $terminaison;
+	if ($term_fonction == "jpg") $term_fonction = "jpeg";
+
+	$nom_fichier = substr($fichier, 0, strlen($fichier) - 4);
+	$fichier_dest = $nom_fichier;
+	
+	if (@file_exists($f = $fichier)){
+		list ($ret["hauteur"],$ret["largeur"]) = taille_image($img);
+		$date_src = @filemtime($f);
+	}
+	elseif (@file_exists($f = "$fichier.src")
+		AND lire_fichier($f,$valeurs)
+		AND $valeurs=unserialize($valeurs)) {
+		$ret["hauteur"] = $valeurs["hauteur_dest"];
+		$ret["largeur"] = $valeurs["largeur_dest"];
+		$date_src = $valeurs["date"];
+	}
+
+	// pas de fichier source par la
+	if (!($ret["hauteur"] OR $ret["largeur"]))
+		return false;
+	
+	// cas general :
+	// on a un dossier cache commun et un nom de fichier qui varie avec l'effet
+	// cas particulier de reduire :
+	// un cache par dimension, et le nom de fichier est conserve, suffixe par la dimension aussi
+	$cache = "cache-gd2";
+	if (substr($effet,0,7)=='reduire') {
+		list(,$maxWidth,$maxHeight) = explode('-',$effet);
+		list ($destWidth,$destHeight) = image_ratio($ret['largeur'], $ret['hauteur'], $maxWidth, $maxHeight);
+		$ret['largeur_dest'] = $destWidth;
+		$ret['hauteur_dest'] = $destHeight;
+		$effet = "L{$destWidth}xH$destHeight";
+		$cache = "cache-vignettes";
+		$fichier_dest = basename($fichier_dest);
+		if (($ret['largeur']<=$maxWidth)&&($ret['hauteur']<=$maxHeight)){
+			// on garde la terminaison initiale car image simplement copiee
+			// et on postfixe son nom avec un md5 du path
+			$terminaison_dest = $terminaison;
+			$fichier_dest .= '-'.substr(md5("$fichier"),0,5);
+		}
+		else
+			$fichier_dest .= '-'.substr(md5("$fichier-$effet"),0,5);
+		$cache = sous_repertoire(_DIR_VAR, $cache);
+		$cache = sous_repertoire($cache, $effet);
+		# cherche un cache existant
+		/*foreach (array('gif','jpg','png') as $fmt)
+			if (@file_exists($cache . $fichier_dest . '.' . $fmt)) {
+				$terminaison_dest = $fmt;
+			}*/
+	}
+	else 	{
+		$fichier_dest = md5("$fichier-$effet");
+		$cache = sous_repertoire(_DIR_VAR, $cache);
+	}
+	
+	$fichier_dest = $cache . $fichier_dest . "." .$terminaison_dest;
+	
+	$GLOBALS["images_calculees"][] =  $fichier_dest;
+	
+	$creer = true;
+	// si recalcul des images demande, recalculer chaque image une fois
+	if (isset($GLOBALS['var_images']) && $GLOBALS['var_images'] && !isset($images_recalcul[$fichier_dest])){
+		$images_recalcul[$fichier_dest] = true;
+	}
+	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)
+				$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
+			reconstruire_image_intermediaire($fichier);
+		}
+	}
+	// todo: si une image png est nommee .jpg, le reconnaitre avec le bon $f
+	$f = "imagecreatefrom".$term_fonction;
+	if (!function_exists($f)) return false;
+	$ret["fonction_imagecreatefrom"] = $f;
+	$ret["fichier"] = $fichier;
+	$ret["fonction_image"] = "image_image".$terminaison_dest;
+	$ret["fichier_dest"] = $fichier_dest;
+	$ret["format_source"] = $terminaison;
+	$ret["format_dest"] = $terminaison_dest;
+	$ret["date_src"] = $date_src;
+	$ret["creer"] = $creer;
+	$ret["class"] = extraire_attribut($img, 'class');
+	$ret["alt"] = extraire_attribut($img, 'alt');
+	$ret["style"] = extraire_attribut($img, 'style');
+	$ret["tag"] = $img;
+	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
+		# ca evite d'essayer de le creer au prochain hit si il n'est pas la
+		#ecrire_fichier($ret['fichier_dest'].'.src',serialize($ret),true);
+	}
+	return $ret;
+}
+
+// http://doc.spip.org/@image_imagepng
+function image_imagepng($img,$fichier) {
+	$tmp = $fichier.".tmp";
+	$ret = imagepng($img,$tmp);
+	
+	$taille_test = getimagesize($tmp);
+	if ($taille_test[0] < 1) return false;
+
+	spip_unlink($fichier); // le fichier peut deja exister
+	@rename($tmp, $fichier);
+	return $ret;
+}
+
+// http://doc.spip.org/@image_imagegif
+function image_imagegif($img,$fichier) {
+	$tmp = $fichier.".tmp";
+	$ret = imagegif($img,$tmp);
+
+	$taille_test = getimagesize($tmp);
+	if ($taille_test[0] < 1) return false;
+
+
+	spip_unlink($fichier); // le fichier peut deja exister
+	@rename($tmp, $fichier);
+	return $ret;
+}
+// http://doc.spip.org/@image_imagejpg
+function image_imagejpg($img,$fichier,$qualite=_IMG_GD_QUALITE) {
+	$tmp = $fichier.".tmp";
+	$ret = imagejpeg($img,$tmp, $qualite);
+
+	$taille_test = getimagesize($tmp);
+	if ($taille_test[0] < 1) return false;
+
+	spip_unlink($fichier); // le fichier peut deja exister
+	@rename($tmp, $fichier);
+	return $ret;
+}
+// http://doc.spip.org/@image_imageico
+function image_imageico($img, $fichier) {
+	$gd_image_array = array($img);
+
+	return ecrire_fichier($fichier, phpthumb_functions::GD2ICOstring($gd_image_array));
+}
+
+// $qualite est utilise pour la qualite de compression des jpeg
+// http://doc.spip.org/@image_gd_output
+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 = 
+		!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'));
+	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'])){
+			$valeurs['date'] = @filemtime($valeurs['fichier_dest']); // pour la retrouver apres disparition
+			ecrire_fichier($valeurs['fichier_dest'].'.src',serialize($valeurs),true);
+		}
+	return $ret;
+}
+
+// http://doc.spip.org/@reconstruire_image_intermediaire
+function reconstruire_image_intermediaire($fichier_manquant){
+	$reconstruire = array();
+	$fichier = $fichier_manquant;
+	while (
+		!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)){
+		$r = array_pop($reconstruire);
+		$fonction = $r[0];
+		$args = $r[1];
+		call_user_func_array($fonction, $args);
+	}
+	// cette image intermediaire est commune a plusieurs series de filtre, il faut la conserver
+	// mais l'on peut nettoyer les miettes de sa creation
+	ramasse_miettes($fichier_manquant);
+}
+
+// http://doc.spip.org/@ramasse_miettes
+function ramasse_miettes($fichier){
+	if (!lire_fichier($src = "$fichier.src",$source) 
+		OR !$valeurs=unserialize($source)) return;
+	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
+		) {
+		# on efface le fichier
+		spip_unlink($fichier);
+		# mais laisse le .src qui permet de savoir comment reconstruire l'image si besoin
+		#spip_unlink($src);
+	}
+}
+
+// http://doc.spip.org/@image_graver
+function image_graver($img){
+	$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
+	if (!file_exists($fichier)) 
+		reconstruire_image_intermediaire($fichier);
+	ramasse_miettes($fichier);
+	return $img; // on ne change rien
+}
+
+// Transforme une image a palette indexee (256 couleurs max) en "vraies" couleurs RGB
+// http://doc.spip.org/@imagepalettetotruecolor
+ function imagepalettetotruecolor(&$img) {
+	if (!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);
+		}
+
+		$img = $img1;
+	}
+}
+
+// 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');
+	// 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);
+	// 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);
+	$style = "height:".$height."px;width:".$width."px;".$style;
+	// attributs deprecies. Transformer en CSS
+	if ($espace = extraire_attribut($tag, 'hspace')){
+		$style = "margin:${espace}px;".$style;
+		$tag = inserer_attribut($tag,'hspace','');
+	}
+	$tag = inserer_attribut($tag,'style',$style);
+	return $tag;
+}
+
+// function d'ecriture du tag img en sortie des filtre image
+// reprend le tag initial et surcharge les tags modifies
+// http://doc.spip.org/@image_ecrire_tag
+function image_ecrire_tag($valeurs,$surcharge){
+	$tag = 	str_replace(">","/>",str_replace("/>",">",$valeurs['tag'])); // fermer les tags img pas bien fermes;
+	
+	// le style
+	$style = $valeurs['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'])){
+		$width = $surcharge['width'];
+		unset($surcharge['width']);
+	}
+	$height = $valeurs['hauteur'];
+	if (isset($surcharge['height'])){
+		$height = $surcharge['height'];
+		unset($surcharge['height']);
+	}
+
+	$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 = $surcharge['src'];
+		unset($surcharge['src']);
+	}
+
+	$class = $valeurs['class'];
+	if (isset($surcharge['class'])){
+		$class = $surcharge['class'];
+		unset($surcharge['class']);
+	}
+	if(strlen($class))
+		$tag = inserer_attribut($tag,'class',$class);
+
+	if (count($surcharge))
+		foreach($surcharge as $attribut=>$valeur)
+			$tag = inserer_attribut($tag,$attribut,$valeur);
+
+	return $tag;
+}
+
+// selectionner les images qui vont subir une transformation sur un critere de taille
+// ls images exclues sont marquees d'une class no_image_filtrer qui bloque les filtres suivants
+// dans la fonction image_filtrer
+// http://doc.spip.org/@image_select
+function image_select($img,$width_min=0, $height_min=0, $width_max=10000, $height_max=1000){
+	if (!$img) return $img;
+	list ($h,$l) = taille_image($img);
+	$select = true;
+	if ($l<$width_min OR $l>$width_max OR $h<$height_min OR $h>$height_max)
+		$select = false;
+
+	$class = extraire_attribut($img,'class');
+	$p = strpos($class,'no_image_filtrer');
+	if (($select==false) AND ($p===FALSE)){
+		$class .= " no_image_filtrer";
+		$img = inserer_attribut($img,'class',$class);
+	}
+	if (($select==true) AND ($p!==FALSE)){
+		$class = preg_replace(",\s*no_image_filtrer,","",$class);
+		$img = inserer_attribut($img,'class',$class);
+	}
+	return $img;
+}
+
+// http://doc.spip.org/@image_creer_vignette
+function image_creer_vignette($valeurs, $maxWidth, $maxHeight, $process='AUTO', $force=false, $test_cache_only = 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"]);
+	
+	$format_sortie = $valeurs['format_dest'];
+	
+	// liste des formats qu'on sait lire
+	$img = isset($GLOBALS['meta']['formats_graphiques'])
+	  ? (strpos($GLOBALS['meta']['formats_graphiques'], $format)!==false)
+	  : false;
+
+	// si le doc n'est pas une image, refuser
+	if (!$force AND !$img) return;
+	$destination = "$destdir/$destfile";
+
+	// chercher un cache
+	$vignette = '';
+	if ($test_cache_only AND !$vignette) return;
+
+	// utiliser le cache ?
+	if (!$test_cache_only)
+	if ($force OR !$vignette OR (@filemtime($vignette) < @filemtime($image))) {
+
+		$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
+		else if ($process == 'convert') {
+			define('_CONVERT_COMMAND', 'convert');
+			define ('_RESIZE_COMMAND', _CONVERT_COMMAND.' -quality 85 -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') {
+			$vignette = "$destination.".$format_sortie;
+			$handle = imagick_readimage($image);
+			imagick_resize($handle, $destWidth, $destHeight, IMAGICK_FILTER_LANCZOS, 0.75);
+			imagick_write($handle, $vignette);
+			if (!@file_exists($vignette)) {
+				spip_log("echec imagick 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") {
+				$giftopnm_command = str_replace("pnmscale", "giftopnm", _PNMSCALE_COMMAND);
+				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;
+				}
+			}
+		}
+		// 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;
+			}
+
+			$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"; 
+				}
+				if ($destFormat == "png") { 
+					// Conserver la transparence 
+					if (function_exists("imageAntiAlias")) imageAntiAlias($destImage,true); 
+					@imagealphablending($destImage, false); 
+					@imagesavealpha($destImage,true); 
+				}
+				$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);
+
+			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;
+	
+	$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) {
+		$destWidth = $srcWidth;
+		$destHeight = $srcHeight;
+	} else if ($ratioWidth < $ratioHeight) {
+		$destWidth = $srcWidth/$ratioHeight;
+		$destHeight = $maxHeight;
+	}
+	else {
+		$destWidth = $maxWidth;
+		$destHeight = $srcHeight/$ratioWidth;
+	}
+	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;
+
+	if ($ratioWidth <=1 AND $ratioHeight <=1) {
+		$destWidth = $srcWidth;
+		$destHeight = $srcHeight;
+	} else if ($ratioWidth > $ratioHeight) {
+		$destWidth = $srcWidth/$ratioHeight;
+		$destHeight = $maxHeight;
+	}
+	else {
+		$destWidth = $maxWidth;
+		$destHeight = $srcHeight/$ratioWidth;
+	}
+	return array (floor($destWidth), floor($destHeight),
+		min($ratioWidth,$ratioHeight));
+}
+
+// http://doc.spip.org/@image_passe_partout
+function image_passe_partout($img,$taille_x = -1, $taille_y = -1,$force = false,$cherche_image=false,$process='AUTO'){
+	if (!$img) return '';
+	list ($hauteur,$largeur) = taille_image($img);
+	if ($taille_x == -1)
+		$taille_x = isset($GLOBALS['meta']['taille_preview'])?$GLOBALS['meta']['taille_preview']:150;
+	if ($taille_y == -1)
+		$taille_y = $taille_x;
+
+	if ($taille_x == 0 AND $taille_y > 0)
+		$taille_x = 1; # {0,300} -> c'est 300 qui compte
+	elseif ($taille_x > 0 AND $taille_y == 0)
+		$taille_y = 1; # {300,0} -> c'est 300 qui compte
+	elseif ($taille_x == 0 AND $taille_y == 0)
+		return '';
+	
+	list($destWidth,$destHeight,$ratio) = ratio_passe_partout($largeur,$hauteur,$taille_x,$taille_y);
+	$fonction = array('image_passe_partout', func_get_args());
+	return process_image_reduire($fonction,$img,$destWidth,$destHeight,$force,$cherche_image,$process);
+}
+
+// http://doc.spip.org/@image_reduire
+function image_reduire($img, $taille = -1, $taille_y = -1, $force=false, $cherche_image=false, $process='AUTO') {
+	// Determiner la taille x,y maxi
+	// prendre le reglage de previsu par defaut
+	if ($taille == -1)
+		$taille = isset($GLOBALS['meta']['taille_preview'])?$GLOBALS['meta']['taille_preview']:150;
+	if ($taille_y == -1)
+		$taille_y = $taille;
+
+	if ($taille == 0 AND $taille_y > 0)
+		$taille = 100000; # {0,300} -> c'est 300 qui compte
+	elseif ($taille > 0 AND $taille_y == 0)
+		$taille_y = 100000; # {300,0} -> c'est 300 qui compte
+	elseif ($taille == 0 AND $taille_y == 0)
+		return '';
+
+	$fonction = array('image_reduire', func_get_args());
+	return process_image_reduire($fonction,$img,$taille,$taille_y,$force,$cherche_image,$process);
+}
+
+// http://doc.spip.org/@process_image_reduire
+function process_image_reduire($fonction,$img,$taille,$taille_y,$force,$cherche_image,$process){
+	$image = false;
+	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);
+		// 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');
+			// 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
+			# bug : gd_formats contient la liste des fichiers qu'on sait *lire*,
+			# pas *ecrire*
+			$format_sortie = "";
+			foreach ($formats_sortie as $fmt) {
+				if (in_array($fmt, $gd_formats)) {
+					if ($fmt <> "gif" OR function_exists('ImageGif'))
+						$format_sortie = $fmt;
+					break;
+				}
+			}
+			$image = false;
+		}
+	}
+
+	if (!$image)
+		$image = image_valeurs_trans($img, "reduire-{$taille}-{$taille_y}",$format_sortie,$fonction);
+
+	if (!$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);
+		}
+		// la on n'a pas d'infos sur l'image source... on refile le truc a css
+		// sous la forme style='max-width: NNpx;'
+		return inserer_attribut($img, 'style',
+			"max-width: ${taille}px; max-height: ${taille_y}px");
+	}
+
+	// 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']){
+			@copy($image['fichier'], $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 ($cherche_image){
+		$cherche = cherche_image_nommee(substr($image['fichier'],0,-4), array($image["format_source"]));
+		if (!$cherche) return $img;
+		//list($chemin,$nom,$format) = $cherche;
+	}
+	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);
+
+		if ($preview && $preview['fichier']) {
+			$logo = $preview['fichier'];
+			$destWidth = $preview['width'];
+			$destHeight = $preview['height'];
+			$date = $preview['date'];
+		}
+		// dans l'espace prive mettre un timestamp sur l'adresse 
+		// 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='.$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;
+}
+
+// Reduire une image d'un certain facteur
+// http://doc.spip.org/@image_reduire_par
+function image_reduire_par ($img, $val=1, $force=false) {
+	list ($hauteur,$largeur) = taille_image($img);
+
+	$l = round($largeur/$val);
+	$h = round($hauteur/$val);
+	
+	if ($l > $h) $h = 0;
+	else $l = 0;
+	
+	$img = image_reduire($img, $l, $h, $force);
+
+	return $img;
+}
+
+?>
\ No newline at end of file
diff --git a/ecrire/inc/formater_article.php b/ecrire/inc/formater_article.php
index 69cfbd33dc..7248ba2946 100644
--- a/ecrire/inc/formater_article.php
+++ b/ecrire/inc/formater_article.php
@@ -45,7 +45,7 @@ function inc_formater_article_dist($row, $own='')
 	if ($chercher_logo) {
 		if ($logo = $chercher_logo($id_article, 'id_article', 'on')) {
 			list($fid, $dir, $nom, $format) = $logo;
-			include_spip('inc/filtres_images');
+			include_spip('inc/filtres_images_mini');
 			$logo = image_reduire("<img src='$fid' alt='' />", 26, 20);
 		}
 	} else $logo ='';
diff --git a/ecrire/inc/forum.php b/ecrire/inc/forum.php
index 5579948702..8a7b69248b 100644
--- a/ecrire/inc/forum.php
+++ b/ecrire/inc/forum.php
@@ -480,7 +480,7 @@ function afficher_forum_thread($row, $controle_id_article, $compteur_forum, $nb_
 			$chercher_logo = charger_fonction('chercher_logo', 'inc');
 			if ($logo = $chercher_logo($id_auteur, 'id_auteur', 'on')) {
 				list($fid, $dir, $nom, $format) = $logo;
-				include_spip('inc/filtres_images');
+				include_spip('inc/filtres_images_mini');
 				$logo = image_reduire("<img src='$fid' alt='' />", 48, 48);
 				if ($logo)
 					$titre_boite = "\n<div style='$voir_logo'>$logo</div>$titre_boite" ;
diff --git a/ecrire/inc/iconifier.php b/ecrire/inc/iconifier.php
index f07d9b3bc2..35430a290d 100644
--- a/ecrire/inc/iconifier.php
+++ b/ecrire/inc/iconifier.php
@@ -148,7 +148,7 @@ function indiquer_logo($titre, $id_objet, $mode, $id, $script, $iframe_script) {
 function decrire_logo($id_objet, $mode, $id, $width, $height, $img, $titre="", $script="", $flag_modif=true) {
 
 	list($fid, $dir, $nom, $format) = $img;
-	include_spip('inc/filtres_images');
+	include_spip('inc/filtres_images_mini');
 	$res = image_reduire("<img src='$fid' alt='' class='miniature_logo' />", $width, $height);
 
 	if ($res)
diff --git a/ecrire/inc/informer.php b/ecrire/inc/informer.php
index 3081d468c2..752ed02a71 100644
--- a/ecrire/inc/informer.php
+++ b/ecrire/inc/informer.php
@@ -37,7 +37,7 @@ function inc_informer_dist($id, $col, $exclus, $rac, $type, $do='aff')
 		$chercher_logo = charger_fonction('chercher_logo', 'inc');
 		if ($res = $chercher_logo($id, 'id_rubrique', 'on'))  {
 			list($fid, $dir, $nom, $format) = $res;
-			include_spip('inc/filtres_images');
+			include_spip('inc/filtres_images_mini');
 			$res = image_reduire("<img src='$fid' alt='' />", 100, 48);
 			if ($res)
 				$res =  "<div style='float: $spip_lang_right; margin-$spip_lang_right: -5px; margin-top: -5px;'>$res</div>";
diff --git a/ecrire/inc/informer_auteur.php b/ecrire/inc/informer_auteur.php
index 67365f9488..c675cafacd 100644
--- a/ecrire/inc/informer_auteur.php
+++ b/ecrire/inc/informer_auteur.php
@@ -44,7 +44,7 @@ function inc_informer_auteur_dist($id)
 		$chercher_logo = charger_fonction('chercher_logo', 'inc');
 		if ($res = $chercher_logo($id, 'id_auteur', 'on'))  {
 			list($fid, $dir, $n, $format) = $res;
-			include_spip('inc/filtres_images');
+			include_spip('inc/filtres_images_mini');
 			$res = image_reduire("<img src='$fid' alt='' />", 100, 48);
 			if ($res)
 				$res =  "<div style='float: $spip_lang_right; margin-$spip_lang_right: -5px; margin-top: -5px;'>$res</div>";
diff --git a/ecrire/inc/plugin.php b/ecrire/inc/plugin.php
index 642099aa36..e0bf77c380 100644
--- a/ecrire/inc/plugin.php
+++ b/ecrire/inc/plugin.php
@@ -886,7 +886,7 @@ function affiche_bloc_plugin($plug_file, $info) {
 	$s .= "<div class='detailplugin verdana2'>";
 
 	if (isset($info['icon'])) {
-		include_spip("inc/filtres_images");
+		include_spip("inc/filtres_images_mini");
 		$s.= "<div  style='float:$spip_lang_right;'>".image_reduire(_DIR_PLUGINS.$plug_file.'/'.trim($info['icon']), 64)."</div>";
 
 	}
diff --git a/ecrire/inc/presenter_enfants.php b/ecrire/inc/presenter_enfants.php
index 178e6ccfa9..b2633908f8 100644
--- a/ecrire/inc/presenter_enfants.php
+++ b/ecrire/inc/presenter_enfants.php
@@ -44,7 +44,7 @@ function enfant_rub($collection){
 			if ($voir_logo) {
 				if ($logo = $chercher_logo($id_rubrique, 'id_rubrique', 'on')) {
 					list($fid, $dir, $nom, $format) = $logo;
-					include_spip('inc/filtres_images');
+					include_spip('inc/filtres_images_mini');
 					$logo = image_reduire("<img src='$fid' alt='' />", 48, 36);
 					if ($logo)
 						$logo =  "\n<div style='$voir_logo'>$logo</div>";
diff --git a/prive/formulaires/login.php b/prive/formulaires/login.php
index 2531c07dc5..ab62763a4d 100644
--- a/prive/formulaires/login.php
+++ b/prive/formulaires/login.php
@@ -80,7 +80,7 @@ function formulaires_login_charger_dist($cible="",$login="",$prive=null){
 		include_spip('inc/autoriser');
 		$loge = autoriser('ecrire');
 	} else {
-		$loge = ($visiteur_session['auth'] != '');
+		$loge = ($GLOBALS['visiteur_session']['auth'] != '');
 	}
 
 	if ($auteur AND $loge) {
-- 
GitLab