2 /***************************************************************************\
3 * SPIP, Systeme de publication pour l'internet *
5 * Copyright (c) 2001-2014 *
6 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
8 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
9 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
10 \***************************************************************************/
13 * Toutes les fonctions image_xx de ce fichier :
14 * - prennent une image en entree
15 * - fournissent une image en sortie
16 * - sont chainables les unes derrieres les autres dans toutes les combinaisons possibles
19 if (!defined('_ECRIRE_INC_VERSION')) return;
21 // librairie de base du core
22 include_spip('inc/filtres_images_mini');
24 // 1/ Aplatir une image semi-transparente (supprimer couche alpha)
25 // en remplissant la transparence avec couleur choisir $coul.
26 // 2/ Forcer le format de sauvegarde (jpg, png, gif)
27 // pour le format jpg, $qualite correspond au niveau de compression (defaut 85)
28 // pour le format gif, $qualite correspond au nombre de couleurs dans la palette (defaut 128)
29 // pour le format png, $qualite correspond au nombre de couleur dans la palette ou si 0 a une image truecolor (defaut truecolor)
30 // attention, seul 128 est supporte en l'etat (production d'images avec palette reduite pas satisfaisante)
31 // http://doc.spip.org/@image_aplatir
32 // 3/ $transparence a "true" permet de conserver la transparence (utile pour conversion GIF)
33 // http://doc.spip.org/@image_aplatir
34 function image_aplatir($im, $format='jpg', $coul='000000', $qualite=NULL, $transparence=false)
37 if ($format=='jpg') $qualite=_IMG_GD_QUALITE
;
38 elseif ($format=='png') $qualite=0;
41 $fonction = array('image_aplatir', func_get_args());
42 $image = _image_valeurs_trans($im, "aplatir-$format-$coul-$qualite-$transparence", $format, $fonction);
44 if (!$image) return("");
46 include_spip('inc/filtres');
47 $couleurs = _couleur_hex_to_dec($coul);
48 $dr= $couleurs["red"];
49 $dv= $couleurs["green"];
50 $db= $couleurs["blue"];
52 $x_i = $image["largeur"];
53 $y_i = $image["hauteur"];
55 $im = $image["fichier"];
56 $dest = $image["fichier_dest"];
58 $creer = $image["creer"];
61 $im = @$image["fonction_imagecreatefrom"]($im);
62 imagepalettetotruecolor($im);
63 $im_ = imagecreatetruecolor($x_i, $y_i);
64 if ($image["format_source"] == "gif" AND function_exists('ImageCopyResampled')) {
65 // Si un GIF est transparent,
66 // fabriquer un PNG transparent
67 // Conserver la transparence
68 @imagealphablending
($im_, false);
69 @imagesavealpha
($im_,true);
70 if (function_exists("imageAntiAlias")) imageAntiAlias($im_,true);
71 @ImageCopyResampled
($im_, $im, 0, 0, 0, 0, $x_i, $y_i, $x_i, $y_i);
76 // allouer la couleur de fond
78 @imagealphablending
($im_, false);
79 @imagesavealpha
($im_,true);
80 $color_t = imagecolorallocatealpha( $im_, $dr, $dv, $db, 127);
82 else $color_t = ImageColorAllocate( $im_, $dr, $dv, $db);
84 imagefill ($im_, 0, 0, $color_t);
87 //$dist = abs($trait);
91 for ($x = 0; $x < $x_i; $x++
) {
92 for ($y=0; $y < $y_i; $y++
) {
94 $rgb = ImageColorAt($im, $x, $y);
95 $a = ($rgb >> 24) & 0xFF;
96 $r = ($rgb >> 16) & 0xFF;
97 $g = ($rgb >> 8) & 0xFF;
102 if ($a == 1) { // Limiter calculs
107 else if ($a == 0) { // Limiter calculs
112 $transp_x = $x; // Memoriser un point transparent
116 $r = round($a * $r +
$dr * (1-$a));
117 $g = round($a * $g +
$dv * (1-$a));
118 $b = round($a * $b +
$db * (1-$a));
121 $color = ImageColorAllocateAlpha( $im_, $r, $g, $b, $a);
122 imagesetpixel ($im_, $x, $y, $color);
125 // passer en palette si besoin
126 if ($format=='gif' OR ($format=='png' AND $qualite!==0)){
127 // creer l'image finale a palette (on recycle l'image initiale)
130 @imagetruecolortopalette
($im,true,$qualite);
133 //$im = imagecreate($x_i, $y_i);
134 // copier l'image true color vers la palette
135 imagecopy($im, $im_, 0, 0, 0, 0, $x_i, $y_i);
136 // matcher les couleurs au mieux par rapport a l'image initiale
137 // si la fonction est disponible (php>=4.3)
138 if (function_exists('imagecolormatch'))
139 @imagecolormatch
($im_, $im);
141 if ($format=='gif' && $transparence && $transp_x) {
142 $color_t = ImagecolorAt( $im, $transp_x, $transp_y);
143 if ($format == "gif" && $transparence) @imagecolortransparent
($im, $color_t);
147 // produire le resultat
148 _image_gd_output($im, $image, $qualite);
151 _image_gd_output($im_, $image, $qualite);
155 return _image_ecrire_tag($image,array('src'=>$dest));
159 // Enregistrer une image dans un format donne
160 // (conserve la transparence gif, png, ico)
161 // utilise [->@image_aplatir]
162 // http://doc.spip.org/@image_format
163 function image_format($img, $format='png') {
165 if ($format=='png8') {$format='png';$qualite=128;}
166 return image_aplatir($img, $format, 'cccccc', $qualite, true);
170 // Transforme l'image en PNG transparent
171 // alpha = 0: aucune transparence
172 // alpha = 127: completement transparent
173 // http://doc.spip.org/@image_alpha
174 function image_alpha($im, $alpha = 63)
176 $fonction = array('image_alpha', func_get_args());
177 $image = _image_valeurs_trans($im, "alpha-$alpha", "png",$fonction);
178 if (!$image) return("");
180 $x_i = $image["largeur"];
181 $y_i = $image["hauteur"];
183 $im = $image["fichier"];
184 $dest = $image["fichier_dest"];
186 $creer = $image["creer"];
189 // Creation de l'image en deux temps
190 // de facon a conserver les GIF transparents
191 $im = $image["fonction_imagecreatefrom"]($im);
192 imagepalettetotruecolor($im);
193 $im2 = imagecreatetruecolor($x_i, $y_i);
194 @imagealphablending
($im2, false);
195 @imagesavealpha
($im2,true);
196 $color_t = ImageColorAllocateAlpha( $im2, 255, 255, 255 , 127 );
197 imagefill ($im2, 0, 0, $color_t);
198 imagecopy($im2, $im, 0, 0, 0, 0, $x_i, $y_i);
200 $im_ = imagecreatetruecolor($x_i, $y_i);
201 imagealphablending ($im_, FALSE );
202 imagesavealpha ( $im_, TRUE );
206 for ($x = 0; $x < $x_i; $x++
) {
207 for ($y = 0; $y < $y_i; $y++
) {
208 $rgb = ImageColorAt($im2, $x, $y);
210 if (function_exists('imagecolorallocatealpha')) {
211 $a = ($rgb >> 24) & 0xFF;
212 $r = ($rgb >> 16) & 0xFF;
213 $g = ($rgb >> 8) & 0xFF;
217 $a_ = $alpha +
$a - round($a*$alpha/127);
218 $rgb = imagecolorallocatealpha($im_, $r, $g, $b, $a_);
220 imagesetpixel ( $im_, $x, $y, $rgb );
223 _image_gd_output($im_,$image);
230 return _image_ecrire_tag($image,array('src'=>$dest));
234 // http://doc.spip.org/@image_recadre
235 function image_recadre($im,$width,$height,$position='center', $background_color='white')
237 $fonction = array('image_recadre', func_get_args());
238 $image = _image_valeurs_trans($im, "recadre-$width-$height-$position-$background_color",false,$fonction);
240 if (!$image) return("");
242 $x_i = $image["largeur"];
243 $y_i = $image["hauteur"];
245 if (_IMG_GD_MAX_PIXELS
&& $x_i*$y_i>_IMG_GD_MAX_PIXELS
){
246 spip_log("image_recadre impossible sur $im : ".$srcWidth*$srcHeight."pixels");
247 // on se rabat sur une reduction CSS
248 return _image_tag_changer_taille($im,$width,$height);
251 if ($width==0) $width=$x_i;
252 if ($height==0) $height=$y_i;
254 $offset_width = $x_i-$width;
255 $offset_height = $y_i-$height;
256 $position=strtolower($position);
257 if (strpos($position,'left')!==FALSE){
258 if (preg_match(';left=(\d{1}\d+);', $position, $left)){
259 $offset_width=$left[1];
265 elseif (strpos($position,'right')!==FALSE)
266 $offset_width=$offset_width;
268 $offset_width=intval(ceil($offset_width/2));
270 if (strpos($position,'top')!==FALSE){
271 if (preg_match(';top=(\d{1}\d+);', $position, $top)){
272 $offset_height=$top[1];
278 elseif (strpos($position,'bottom')!==FALSE)
279 $offset_height=$offset_height;
281 $offset_height=intval(ceil($offset_height/2));
283 $im = $image["fichier"];
284 $dest = $image["fichier_dest"];
286 $creer = $image["creer"];
289 $im = $image["fonction_imagecreatefrom"]($im);
290 imagepalettetotruecolor($im);
291 $im_ = imagecreatetruecolor($width, $height);
292 @imagealphablending
($im_, false);
293 @imagesavealpha
($im_,true);
295 if ($background_color=='transparent')
296 $color_t = imagecolorallocatealpha( $im_, 255, 255, 255 , 127 );
298 $bg = _couleur_hex_to_dec($background_color);
299 $color_t = imagecolorallocate( $im_, $bg['red'], $bg['green'], $bg['blue']);
301 imagefill ($im_, 0, 0, $color_t);
302 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));
304 _image_gd_output($im_,$image);
309 return _image_ecrire_tag($image,array('src'=>$dest,'width'=>$width,'height'=>$height));
314 * Recadrer une image dans le rectangle le plus petit possible sans perte
315 * de pixels non transparent
320 function image_recadre_mini($im)
322 $fonction = array('image_recadre_mini', func_get_args());
323 $image = _image_valeurs_trans($im, "recadre_mini",false,$fonction);
325 if (!$image) return("");
327 $width = $image["largeur"];
328 $height = $image["hauteur"];
330 $im = $image["fichier"];
331 $dest = $image["fichier_dest"];
333 $creer = $image["creer"];
335 $im = $image["fonction_imagecreatefrom"]($im);
336 imagepalettetotruecolor($im);
338 // trouver le rectangle mini qui contient des infos de couleur
339 // recherche optimisee qui ne balaye que par zone
344 while ($yy<=$height/2 AND $max_y<=$min_y){
346 for ($xx = 0; $xx < $width; $xx++
) {
347 $color_index = imagecolorat($im, $xx, $yy);
348 $color_tran = imagecolorsforindex($im, $color_index);
349 if ($color_tran['alpha']!==127){
350 $min_y = min($yy,$min_y);
351 $max_y = max($height-1-$yy,$max_y);
355 if($height-1-$yy>$max_y)
356 for ($xx = 0; $xx < $width; $xx++
) {
357 $color_index = imagecolorat($im, $xx, $height-1-$yy);
358 $color_tran = imagecolorsforindex($im, $color_index);
359 if ($color_tran['alpha']!==127){
360 $min_y = min($yy,$min_y);
361 $max_y = max($height-1-$yy,$max_y);
367 $min_y = min($max_y,$min_y); // tout a 0 aucun pixel trouve
370 while ($xx<=$width/2 AND $max_x<=$min_x){
372 for ($yy = $min_y; $yy < $max_y; $yy++
) {
373 $color_index = imagecolorat($im, $xx, $yy);
374 $color_tran = imagecolorsforindex($im, $color_index);
375 if ($color_tran['alpha']!==127){
376 $min_x = min($xx,$min_x);
377 $max_x = max($xx,$max_x);
378 break; // inutile de continuer sur cette colonne
381 if ($width-1-$xx>$max_x)
382 for ($yy = $min_y; $yy < $max_y; $yy++
) {
383 $color_index = imagecolorat($im, $width-1-$xx, $yy);
384 $color_tran = imagecolorsforindex($im, $color_index);
385 if ($color_tran['alpha']!==127){
386 $min_x = min($width-1-$xx,$min_x);
387 $max_x = max($width-1-$xx,$max_x);
388 break; // inutile de continuer sur cette colonne
393 $min_x = min($max_x,$min_x); // tout a 0 aucun pixel trouve
395 $width = $max_x-$min_x+
1;
396 $height = $max_y-$min_y+
1;
398 $im_ = imagecreatetruecolor($width, $height);
399 @imagealphablending
($im_, false);
400 @imagesavealpha
($im_,true);
402 $color_t = imagecolorallocatealpha( $im_, 255, 255, 255 , 127 );
403 imagefill ($im_, 0, 0, $color_t);
404 imagecopy($im_, $im, 0, 0, $min_x, $min_y, $width, $height);
406 _image_gd_output($im_,$image);
411 list ($height,$width) = taille_image($image['fichier_dest']);
414 return _image_ecrire_tag($image,array('src'=>$dest,'width'=>$width,'height'=>$height));
418 // http://doc.spip.org/@image_flip_vertical
419 function image_flip_vertical($im)
421 $fonction = array('image_flip_vertical', func_get_args());
422 $image = _image_valeurs_trans($im, "flip_v", false,$fonction);
423 if (!$image) return("");
425 $x_i = $image["largeur"];
426 $y_i = $image["hauteur"];
428 $im = $image["fichier"];
429 $dest = $image["fichier_dest"];
431 $creer = $image["creer"];
434 $im = $image["fonction_imagecreatefrom"]($im);
435 imagepalettetotruecolor($im);
436 $im_ = imagecreatetruecolor($x_i, $y_i);
437 @imagealphablending
($im_, false);
438 @imagesavealpha
($im_,true);
440 $color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
441 imagefill ($im_, 0, 0, $color_t);
443 for ($x = 0; $x < $x_i; $x++
) {
444 for ($y = 0; $y < $y_i; $y++
) {
445 imagecopy($im_, $im, $x_i - $x - 1, $y, $x, $y, 1, 1);
449 _image_gd_output($im_,$image);
454 return _image_ecrire_tag($image,array('src'=>$dest));
457 // http://doc.spip.org/@image_flip_horizontal
458 function image_flip_horizontal($im)
460 $fonction = array('image_flip_horizontal', func_get_args());
461 $image = _image_valeurs_trans($im, "flip_h",false,$fonction);
462 if (!$image) return("");
464 $x_i = $image["largeur"];
465 $y_i = $image["hauteur"];
467 $im = $image["fichier"];
468 $dest = $image["fichier_dest"];
470 $creer = $image["creer"];
473 $im = $image["fonction_imagecreatefrom"]($im);
474 imagepalettetotruecolor($im);
475 $im_ = imagecreatetruecolor($x_i, $y_i);
476 @imagealphablending
($im_, false);
477 @imagesavealpha
($im_,true);
479 $color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
480 imagefill ($im_, 0, 0, $color_t);
482 for ($x = 0; $x < $x_i; $x++
) {
483 for ($y = 0; $y < $y_i; $y++
) {
484 imagecopy($im_, $im, $x, $y_i - $y - 1, $x, $y, 1, 1);
487 _image_gd_output($im_,$image);
492 return _image_ecrire_tag($image,array('src'=>$dest));
495 // http://doc.spip.org/@image_masque
496 function image_masque($im, $masque, $pos="") {
497 // Passer, en plus de l'image d'origine,
498 // une image de "masque": un fichier PNG24 transparent.
499 // Le decoupage se fera selon la transparence du "masque",
500 // et les couleurs seront eclaircies/foncees selon de couleur du masque.
501 // Pour ne pas modifier la couleur, le masque doit etre en gris 50%.
503 // Si l'image source est plus grande que le masque, alors cette image est reduite a la taille du masque.
504 // Sinon, c'est la taille de l'image source qui est utilisee.
506 // $pos est une variable libre, qui permet de passer left=..., right=..., bottom=..., top=...
507 // dans ce cas, le masque est place a ces positions sur l'image d'origine,
508 // et evidemment cette image d'origine n'est pas redimensionnee
510 // Positionnement horizontal: text-align=left, right, center
511 // Positionnement vertical : vertical-align=top, bottom, middle
512 // (les positionnements left, right, top, left sont relativement inutiles, mais coherence avec CSS)
514 // Choix du mode de fusion: mode=masque, normal, eclaircir, obscurcir, produit, difference, ecran, superposer, lumiere_dure, teinte, saturation, valeur
515 // https://en.wikipedia.org/wiki/Blend_modes
516 // masque: mode par defaut
517 // normal: place la nouvelle image par dessus l'ancienne
518 // eclaircir: place uniquement les points plus clairs
519 // obscurcir: place uniquement les points plus fonc'es
520 // produit: multiplie par le masque (points noirs rendent l'image noire, points blancs ne changent rien)
521 // difference: remplit avec l'ecart entre les couleurs d'origine et du masque
522 // ecran: effet inverse de 'produit' -> l'image resultante est plus claire
523 // superposer: combine les modes 'produit' et 'ecran' -> les parties claires sont eclaircies, les parties sombres assombries.
524 // lumiere_dure: equivalent a 'superposer', sauf que l'image du bas et du haut sont inversees.
525 // teinte: utilise la teinte du masque
526 // saturation: utilise la saturation du masque
527 // valeur: utilise la valeur du masque
531 $numargs = func_num_args();
532 $arg_list = func_get_args();
533 $texte = $arg_list[0];
534 for ($i = 1; $i < $numargs; $i++
) {
535 if ( ($p = strpos($arg_list[$i],"=")) !==false) {
536 $nom_variable = substr($arg_list[$i], 0, $p);
537 $val_variable = substr($arg_list[$i], $p+
1);
538 $variable["$nom_variable"] = $val_variable;
539 $defini["$nom_variable"] = 1;
542 if ($defini["mode"]) $mode = $variable["mode"];
544 // utiliser _image_valeurs_trans pour accepter comme masque :
545 // - une balise <img src='...' />
546 // - une image avec un timestamp ?01234
547 $mask = _image_valeurs_trans($masque, "source-image_masque", "png",null, true);
548 if (!$mask) return("");
549 $masque = $mask['fichier'];
551 $pos = md5(serialize($variable).$mask['date_src']);
552 $fonction = array('image_masque', func_get_args());
553 $image = _image_valeurs_trans($im, "masque-$masque-$pos", "png",$fonction);
554 if (!$image) return("");
556 $x_i = $image["largeur"];
557 $y_i = $image["hauteur"];
559 $im = $image["fichier"];
560 $dest = $image["fichier_dest"];
562 $creer = $image["creer"];
564 // doit-on positionner l'image ?
566 foreach (array("right", "left", "bottom", "top", "text-align", "vertical-align") as $pl) {
567 if (isset($defini[$pl]) and $defini[$pl]) {
575 $im_m = $mask["fichier"];
576 $x_m = $mask["largeur"];
577 $y_m = $mask["hauteur"];
579 $im2 = $mask["fonction_imagecreatefrom"]($masque);
580 if ($mask["format_source"] == "gif" AND function_exists('ImageCopyResampled')) {
581 $im2_ = imagecreatetruecolor($x_m, $y_m);
582 // Si un GIF est transparent,
583 // fabriquer un PNG transparent
584 // Conserver la transparence
585 if (function_exists("imageAntiAlias")) imageAntiAlias($im2_,true);
586 @imagealphablending
($im2_, false);
587 @imagesavealpha
($im2_,true);
588 @ImageCopyResampled
($im2_, $im2, 0, 0, 0, 0, $x_m, $y_m, $x_m, $y_m);
594 // On fabriquer une version "agrandie" du masque,
595 // aux dimensions de l'image source
596 // et on "installe" le masque dans cette image
597 // ainsi: aucun redimensionnement
602 if (isset($defini["right"]) and $defini["right"]) {
603 $right = $variable["right"];
604 $dx = ($x_i - $x_m) - $right;
606 if (isset($defini["bottom"]) and $defini["bottom"]) {
607 $bottom = $variable["bottom"];
608 $dy = ($y_i - $y_m) - $bottom;
610 if (isset($defini["top"]) and $defini["top"]) {
611 $top = $variable["top"];
614 if (isset($defini["left"]) and $defini["left"]) {
615 $left = $variable["left"];
618 if (isset($defini["text-align"]) and $defini["text-align"]) {
619 $align = $variable["text-align"];
620 if ($align == "right") {
623 } else if ($align == "left") {
626 } else if ($align = "center") {
627 $dx = round( ($x_i - $x_m) / 2 ) ;
630 if (isset($defini["vertical-align"]) and $defini["vertical-align"]) {
631 $valign = $variable["vertical-align"];
632 if ($valign == "bottom") {
635 } else if ($valign == "top") {
638 } else if ($valign = "middle") {
639 $dy = round( ($y_i - $y_m) / 2 ) ;
644 $im3 = imagecreatetruecolor($x_i, $y_i);
645 @imagealphablending
($im3, false);
646 @imagesavealpha
($im3,true);
647 if ($mode == "masque") $color_t = ImageColorAllocateAlpha( $im3, 128, 128, 128 , 0 );
648 else $color_t = ImageColorAllocateAlpha( $im3, 128, 128, 128 , 127 );
649 imagefill ($im3, 0, 0, $color_t);
652 imagecopy ( $im3, $im2, $dx, $dy, 0, 0, $x_m, $y_m);
655 $im2 = imagecreatetruecolor($x_i, $y_i);
656 @imagealphablending
($im2, false);
657 @imagesavealpha
($im2,true);
659 imagecopy ( $im2, $im3, 0, 0, 0, 0, $x_i, $y_i);
666 $rapport = $x_i / $x_m;
667 if (($y_i / $y_m) < $rapport ) {
668 $rapport = $y_i / $y_m;
671 $x_d = ceil($x_i / $rapport);
672 $y_d = ceil($y_i / $rapport);
675 if ($x_i < $x_m OR $y_i < $y_m) {
683 $x_dec = round(($x_d - $x_m) /2);
684 $y_dec = round(($y_d - $y_m) /2);
688 $nouveau = _image_valeurs_trans(image_reduire($im, $x_d, $y_d),"");
689 if (!is_array($nouveau)) return("");
690 $im_n = $nouveau["fichier"];
693 $im = $nouveau["fonction_imagecreatefrom"]($im_n);
694 imagepalettetotruecolor($im);
695 if ($nouveau["format_source"] == "gif" AND function_exists('ImageCopyResampled')) {
696 $im_ = imagecreatetruecolor($x_dest, $y_dest);
697 // Si un GIF est transparent,
698 // fabriquer un PNG transparent
699 // Conserver la transparence
700 if (function_exists("imageAntiAlias")) imageAntiAlias($im_,true);
701 @imagealphablending
($im_, false);
702 @imagesavealpha
($im_,true);
703 @ImageCopyResampled
($im_, $im, 0, 0, 0, 0, $x_dest, $y_dest, $x_dest, $y_dest);
707 $im_ = imagecreatetruecolor($x_dest, $y_dest);
708 @imagealphablending
($im_, false);
709 @imagesavealpha
($im_,true);
710 $color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
711 imagefill ($im_, 0, 0, $color_t);
714 // calcul couleurs de chaque pixel selon les modes de fusion
715 for ($x = 0; $x < $x_dest; $x++
) {
716 for ($y=0; $y < $y_dest; $y++
) {
717 $rgb = ImageColorAt($im2, $x, $y); // image au dessus
718 $a = ($rgb >> 24) & 0xFF;
719 $r = ($rgb >> 16) & 0xFF;
720 $g = ($rgb >> 8) & 0xFF;
723 $rgb2 = ImageColorAt($im, $x+
$x_dec, $y+
$y_dec); // image en dessous
724 $a2 = ($rgb2 >> 24) & 0xFF;
725 $r2 = ($rgb2 >> 16) & 0xFF;
726 $g2 = ($rgb2 >> 8) & 0xFF;
729 if ($mode == "normal") {
730 $v = (127 - $a) / 127;
736 $v2 = (127 - $a2) / 127;
741 } else if ($v2 == 0) {
745 } else if ($v == 0) {
750 $r_ = $r +
(($r2 - $r) * $v2 * (1 - $v));
751 $g_ = $g +
(($g2 - $g) * $v2 * (1 - $v));
752 $b_ = $b +
(($b2 - $b) * $v2 * (1 - $v));
757 } elseif (in_array($mode, array("produit","difference","superposer","lumiere_dure","ecran"))) {
758 if ($mode == "produit") {
762 } elseif ($mode == "difference") {
766 } elseif ($mode == "superposer") {
767 $r = ($r2 < 128) ?
2 * $r * $r2 / 255 : 255 - (2 * (255 - $r) * (255 - $r2) / 255);
768 $g = ($g2 < 128) ?
2 * $g * $g2 / 255 : 255 - (2 * (255 - $g) * (255 - $g2) / 255);
769 $b = ($b2 < 128) ?
2 * $b * $b2 / 255 : 255 - (2 * (255 - $b) * (255 - $b2) / 255);
770 } elseif ($mode == "lumiere_dure") {
771 $r = ($r < 128) ?
2 * $r * $r2 / 255 : 255 - (2 * (255 - $r2) * (255 - $r) / 255);
772 $g = ($g < 128) ?
2 * $g * $g2 / 255 : 255 - (2 * (255 - $g2) * (255 - $g) / 255);
773 $b = ($b < 128) ?
2 * $b * $b2 / 255 : 255 - (2 * (255 - $b2) * (255 - $b) / 255);
774 } elseif ($mode == "ecran") {
775 $r = 255 - (((255 - $r) * (255 - $r2)) / 255);
776 $g = 255 - (((255 - $g) * (255 - $g2)) / 255);
777 $b = 255 - (((255 - $b) * (255 - $b2)) / 255);
779 $r = max(0, min($r, 255));
780 $g = max(0, min($g, 255));
781 $b = max(0, min($b, 255));
783 // melange en fonction de la transparence du masque
784 $v = (127 - $a) / 127;
785 if ($v == 1) { // melange complet
790 $v2 = (127 - $a2) / 127;
791 if ($v+
$v2 == 0) { // ??
795 } else { // pas de melange (transparence du masque)
796 $r_ = $r +
(($r2 - $r) * $v2 * (1 - $v));
797 $g_ = $g +
(($g2 - $g) * $v2 * (1 - $v));
798 $b_ = $b +
(($b2 - $b) * $v2 * (1 - $v));
803 } elseif ($mode == "eclaircir" OR $mode == "obscurcir") {
804 $v = (127 - $a) / 127;
810 $v2 = (127 - $a2) / 127;
816 $r_ = $r +
(($r2 - $r) * $v2 * (1 - $v));
817 $g_ = $g +
(($g2 - $g) * $v2 * (1 - $v));
818 $b_ = $b +
(($b2 - $b) * $v2 * (1 - $v));
821 if ($mode == "eclaircir") {
822 $r_ = max ($r_, $r2);
823 $g_ = max ($g_, $g2);
824 $b_ = max ($b_, $b2);
826 $r_ = min ($r_, $r2);
827 $g_ = min ($g_, $g2);
828 $b_ = min ($b_, $b2);
832 } elseif (in_array($mode, array("teinte","saturation","valeur"))) {
833 include_spip("filtres/images_lib");
834 $hsv = _couleur_rgb2hsv($r, $g, $b); // image au dessus
838 $hsv2 = _couleur_rgb2hsv($r2, $g2, $b2); // image en dessous
844 $rgb3 = _couleur_hsv2rgb($h, $s2, $v2);
847 $rgb3 = _couleur_hsv2rgb($h2, $s, $v2);
850 $rgb3 = _couleur_hsv2rgb($h2, $s2, $v);
857 // melange en fonction de la transparence du masque
858 $v = (127 - $a) / 127;
859 if ($v == 1) { // melange complet
864 $v2 = (127 - $a2) / 127;
865 if ($v+
$v2 == 0) { // ??
869 } else { // pas de melange (transparence du masque)
870 $r_ = $r +
(($r2 - $r) * $v2 * (1 - $v));
871 $g_ = $g +
(($g2 - $g) * $v2 * (1 - $v));
872 $b_ = $b +
(($b2 - $b) * $v2 * (1 - $v));
878 $r_ = $r2 +
1 * ($r - 127);
879 $r_ = max(0, min($r_, 255));
880 $g_ = $g2 +
1 * ($g - 127);
881 $g_ = max(0, min($g_, 255));
882 $b_ = $b2 +
1 * ($b - 127);
883 $b_ = max(0, min($b_, 255));
884 $a_ = $a +
$a2 - round($a*$a2/127);
887 $color = ImageColorAllocateAlpha( $im_, $r_, $g_, $b_ , $a_ );
888 imagesetpixel ($im_, $x, $y, $color);
892 _image_gd_output($im_,$image);
898 $x_dest = largeur($dest);
899 $y_dest = hauteur($dest);
900 return _image_ecrire_tag($image,array('src'=>$dest,'width'=>$x_dest,'height'=>$y_dest));
903 // Passage de l'image en noir et blanc
904 // un noir & blanc "photo" n'est pas "neutre": les composantes de couleur sont
905 // ponderees pour obtenir le niveau de gris;
906 // on peut ici regler cette ponderation en "pour mille"
907 // http://doc.spip.org/@image_nb
908 function image_nb($im, $val_r = 299, $val_g = 587, $val_b = 114)
910 $fonction = array('image_nb', func_get_args());
911 $image = _image_valeurs_trans($im, "nb-$val_r-$val_g-$val_b",false,$fonction);
912 if (!$image) return("");
914 $x_i = $image["largeur"];
915 $y_i = $image["hauteur"];
917 $im = $image["fichier"];
918 $dest = $image["fichier_dest"];
920 $creer = $image["creer"];
923 // resultat plus beau, mais tres lourd
924 // Et: indispensable pour preserver transparence!
927 // Creation de l'image en deux temps
928 // de facon a conserver les GIF transparents
929 $im = $image["fonction_imagecreatefrom"]($im);
930 imagepalettetotruecolor($im);
931 $im_ = imagecreatetruecolor($x_i, $y_i);
932 @imagealphablending
($im_, false);
933 @imagesavealpha
($im_,true);
934 $color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
935 imagefill ($im_, 0, 0, $color_t);
936 imagecopy($im_, $im, 0, 0, 0, 0, $x_i, $y_i);
938 for ($x = 0; $x < $x_i; $x++
) {
939 for ($y=0; $y < $y_i; $y++
) {
940 $rgb = ImageColorAt($im_, $x, $y);
941 $a = ($rgb >> 24) & 0xFF;
942 $r = ($rgb >> 16) & 0xFF;
943 $g = ($rgb >> 8) & 0xFF;
946 $c = round(($val_r * $r / 1000) +
($val_g * $g / 1000) +
($val_b * $b / 1000));
948 if ($c > 254) $c = 254;
951 $color = ImageColorAllocateAlpha( $im_, $c, $c, $c , $a );
952 imagesetpixel ($im_, $x, $y, $color);
955 _image_gd_output($im_,$image);
960 return _image_ecrire_tag($image,array('src'=>$dest));
963 // http://doc.spip.org/@image_flou
964 function image_flou($im,$niveau=3)
966 // Il s'agit d'une modification du script blur qu'on trouve un peu partout:
967 // + la transparence est geree correctement
968 // + les dimensions de l'image sont augmentees pour flouter les bords
974 array ( 1, 4, 6, 4, 1),
975 array ( 1, 5, 10, 10, 5, 1),
976 array ( 1, 6, 15, 20, 15, 6, 1),
977 array ( 1, 7, 21, 35, 35, 21, 7, 1),
978 array ( 1, 8, 28, 56, 70, 56, 28, 8, 1),
979 array ( 1, 9, 36, 84, 126, 126, 84, 36, 9, 1),
980 array ( 1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1),
981 array ( 1, 11, 55, 165, 330, 462, 462, 330, 165, 55, 11, 1)
984 $fonction = array('image_flou', func_get_args());
985 $image = _image_valeurs_trans($im, "flou-$niveau", false,$fonction);
986 if (!$image) return("");
988 $x_i = $image["largeur"];
989 $y_i = $image["hauteur"];
990 $sum = pow (2, $niveau);
992 $im = $image["fichier"];
993 $dest = $image["fichier_dest"];
995 $creer = $image["creer"];
998 // resultat plus beau, mais tres lourd
999 // Et: indispensable pour preserver transparence!
1002 // Creation de l'image en deux temps
1003 // de facon a conserver les GIF transparents
1004 $im = $image["fonction_imagecreatefrom"]($im);
1005 imagepalettetotruecolor($im);
1006 $temp1 = imagecreatetruecolor($x_i+
$niveau, $y_i);
1007 $temp2 = imagecreatetruecolor($x_i+
$niveau, $y_i+
$niveau);
1009 @imagealphablending
($temp1, false);
1010 @imagesavealpha
($temp1,true);
1011 @imagealphablending
($temp2, false);
1012 @imagesavealpha
($temp2,true);
1015 for ($i = 0; $i < $x_i+
$niveau; $i++
) {
1016 for ($j=0; $j < $y_i; $j++
) {
1023 for ( $k=0 ; $k <= $niveau ; ++
$k ) {
1024 $color = imagecolorat($im, $i_ = ($i-$niveau)+
$k , $j);
1026 $a = ($color >> 24) & 0xFF;
1027 $r = ($color >> 16) & 0xFF;
1028 $g = ($color >> 8) & 0xFF;
1029 $b = ($color) & 0xFF;
1031 if ($i_ < 0 OR $i_ >= $x_i) $a = 127;
1033 $coef = $coeffs[$niveau][$k];
1035 $ac = ((127-$a) / 127);
1039 $sumr +
= $r * $coef * $ac;
1040 $sumg +
= $g * $coef * $ac;
1041 $sumb +
= $b * $coef * $ac;
1042 $sum +
= $coef * $ac;
1045 if ($sum > 0) $color = ImageColorAllocateAlpha ($temp1, $sumr/$sum, $sumg/$sum, $sumb/$sum, $suma/$sum_);
1046 else $color = ImageColorAllocateAlpha ($temp1, 255, 255, 255, 127);
1047 imagesetpixel($temp1,$i,$j,$color);
1051 for ($i = 0; $i < $x_i+
$niveau; $i++
) {
1052 for ($j=0; $j < $y_i+
$niveau; $j++
) {
1059 for ( $k=0 ; $k <= $niveau ; ++
$k ) {
1060 $color = imagecolorat($temp1, $i, $j_ = $j-$niveau+
$k);
1061 $a = ($color >> 24) & 0xFF;
1062 $r = ($color >> 16) & 0xFF;
1063 $g = ($color >> 8) & 0xFF;
1064 $b = ($color) & 0xFF;
1065 if ($j_ < 0 OR $j_ >= $y_i) $a = 127;
1067 $suma +
= $a*$coeffs[$niveau][$k];
1068 $ac = ((127-$a) / 127);
1070 $sumr +
= $r * $coeffs[$niveau][$k] * $ac;
1071 $sumg +
= $g * $coeffs[$niveau][$k] * $ac;
1072 $sumb +
= $b * $coeffs[$niveau][$k] * $ac;
1073 $sum +
= $coeffs[$niveau][$k] * $ac;
1074 $sum_ +
= $coeffs[$niveau][$k];
1077 if ($sum > 0) $color = ImageColorAllocateAlpha ($temp2, $sumr/$sum, $sumg/$sum, $sumb/$sum, $suma/$sum_);
1078 else $color = ImageColorAllocateAlpha ($temp2, 255, 255, 255, 127);
1079 imagesetpixel($temp2,$i,$j,$color);
1083 _image_gd_output($temp2,$image);
1084 imagedestroy($temp1);
1085 imagedestroy($temp2);
1088 return _image_ecrire_tag($image,array('src'=>$dest,'width'=>($x_i+
$niveau),'height'=>($y_i+
$niveau)));
1091 // http://doc.spip.org/@image_RotateBicubic
1092 function image_RotateBicubic($src_img, $angle, $bicubic=0) {
1093 include_spip('filtres/images_lib');
1095 if (round($angle/90)*90 == $angle) {
1097 if (round($angle/180)*180 == $angle) $rot = 180;
1103 // convert degrees to radians
1104 $angle = $angle +
180;
1105 $angle = deg2rad($angle);
1109 $src_x = imagesx($src_img);
1110 $src_y = imagesy($src_img);
1113 $center_x = floor(($src_x-1)/2);
1114 $center_y = floor(($src_y-1)/2);
1116 $cosangle = cos($angle);
1117 $sinangle = sin($angle);
1119 // calculer dimensions en simplifiant angles droits, ce qui evite "floutage"
1120 // des rotations a angle droit
1122 $corners=array(array(0,0), array($src_x,0), array($src_x,$src_y), array(0,$src_y));
1124 foreach($corners as $key=>$value) {
1125 $value[0]-=$center_x; //Translate coords to center for rotation
1126 $value[1]-=$center_y;
1128 $temp[0]=$value[0]*$cosangle+
$value[1]*$sinangle;
1129 $temp[1]=$value[1]*$cosangle-$value[0]*$sinangle;
1130 $corners[$key]=$temp;
1133 $min_x=1000000000000000;
1134 $max_x=-1000000000000000;
1135 $min_y=1000000000000000;
1136 $max_y=-1000000000000000;
1138 foreach($corners as $key => $value) {
1139 if($value[0]<$min_x)
1141 if($value[0]>$max_x)
1144 if($value[1]<$min_y)
1146 if($value[1]>$max_y)
1150 $rotate_width=ceil($max_x-$min_x);
1151 $rotate_height=ceil($max_y-$min_y);
1155 $rotate_height = $src_y;
1156 $rotate_width = $src_x;
1158 $rotate_height = $src_x;
1159 $rotate_width = $src_y;
1165 $rotate=imagecreatetruecolor($rotate_width,$rotate_height);
1166 imagealphablending($rotate, false);
1167 imagesavealpha($rotate, true);
1169 $cosangle = cos($angle);
1170 $sinangle = sin($angle);
1172 // arrondir pour rotations angle droit (car cos et sin dans {-1,0,1})
1174 $cosangle = round($cosangle);
1175 $sinangle = round($sinangle);
1178 $newcenter_x = ($rotate_width-1)/2;
1179 $newcenter_y = ($rotate_height-1)/2;
1182 for ($y = 0; $y < $rotate_height; $y++
) {
1183 for ($x = 0; $x < $rotate_width; $x++
) {
1185 $old_x = ((($newcenter_x-$x) * $cosangle +
($newcenter_y-$y) * $sinangle))
1187 $old_y = ((($newcenter_y-$y) * $cosangle - ($newcenter_x-$x) * $sinangle))
1190 $old_x = ceil($old_x);
1191 $old_y = ceil($old_y);
1193 if ( $old_x >= 0 && $old_x < $src_x
1194 && $old_y >= 0 && $old_y < $src_y ) {
1195 if ($bicubic == true) {
1203 // on prend chaque point, mais on pondere en fonction de la distance
1204 $rgb = ImageColorAt($src_img, $x0, $y0);
1205 $a1 = ($rgb >> 24) & 0xFF;
1206 $r1 = ($rgb >> 16) & 0xFF;
1207 $g1 = ($rgb >> 8) & 0xFF;
1209 $d1 = _image_distance_pixel($xo, $yo, $x0, $y0);
1211 $rgb = ImageColorAt($src_img, $x1, $y0);
1212 $a2 = ($rgb >> 24) & 0xFF;
1213 $r2 = ($rgb >> 16) & 0xFF;
1214 $g2 = ($rgb >> 8) & 0xFF;
1216 $d2 = _image_distance_pixel($xo, $yo, $x1, $y0);
1218 $rgb = ImageColorAt($src_img,$x0, $y1);
1219 $a3 = ($rgb >> 24) & 0xFF;
1220 $r3 = ($rgb >> 16) & 0xFF;
1221 $g3 = ($rgb >> 8) & 0xFF;
1223 $d3 = _image_distance_pixel($xo, $yo, $x0, $y1);
1225 $rgb = ImageColorAt($src_img,$x1, $y1);
1226 $a4 = ($rgb >> 24) & 0xFF;
1227 $r4 = ($rgb >> 16) & 0xFF;
1228 $g4 = ($rgb >> 8) & 0xFF;
1230 $d4 = _image_distance_pixel($xo, $yo, $x1, $y1);
1232 $ac1 = ((127-$a1) / 127);
1233 $ac2 = ((127-$a2) / 127);
1234 $ac3 = ((127-$a3) / 127);
1235 $ac4 = ((127-$a4) / 127);
1237 // limiter impact des couleurs transparentes,
1238 // mais attention tout transp: division par 0
1239 if ($ac1*$d1 +
$ac2*$d2 +
$ac3+
$d3 +
$ac4+
$d4 > 0) {
1240 if ($ac1 > 0) $d1 = $d1 * $ac1;
1241 if ($ac2 > 0) $d2 = $d2 * $ac2;
1242 if ($ac3 > 0) $d3 = $d3 * $ac3;
1243 if ($ac4 > 0) $d4 = $d4 * $ac4;
1246 $tot = $d1 +
$d2 +
$d3 +
$d4;
1248 $r = round((($d1*$r1)+
($d2*$r2)+
($d3*$r3)+
($d4*$r4))/$tot);
1249 $g = round((($d1*$g1+
($d2*$g2)+
$d3*$g3+
$d4*$g4))/$tot);
1250 $b = round((($d1*$b1+
($d2*$b2)+
$d3*$b3+
$d4*$b4))/$tot);
1251 $a = round((($d1*$a1+
($d2*$a2)+
$d3*$a3+
$d4*$a4))/$tot);
1252 $color = imagecolorallocatealpha($src_img, $r,$g,$b,$a);
1255 $color = imagecolorat($src_img, round($old_x), round($old_y));
1259 // this line sets the background colour
1260 $color = imagecolorallocatealpha($src_img, 255, 255, 255, 127);
1262 @imagesetpixel
($rotate, $x, $y, $color);
1268 // permet de faire tourner une image d'un angle quelconque
1269 // la fonction "crop" n'est pas implementee...
1270 // http://doc.spip.org/@image_rotation
1271 function image_rotation($im, $angle, $crop=false)
1273 $fonction = array('image_rotation', func_get_args());
1274 $image = _image_valeurs_trans($im, "rot-$angle-$crop", "png", $fonction);
1275 if (!$image) return("");
1277 $im = $image["fichier"];
1278 $dest = $image["fichier_dest"];
1280 $creer = $image["creer"];
1283 $effectuer_gd = true;
1285 if(is_callable(array('Imagick','rotateImage'))){
1286 $imagick = new Imagick();
1287 $imagick->readImage($im);
1288 $imagick->rotateImage(new ImagickPixel('none'), $angle);
1289 $imagick->writeImage($dest);
1290 $effectuer_gd = false;
1292 else if ($GLOBALS['meta']['image_process'] == "convert") {
1293 if (_CONVERT_COMMAND
!='') {
1294 @define
('_CONVERT_COMMAND', 'convert');
1295 @define
('_ROTATE_COMMAND', _CONVERT_COMMAND
.' -background none -rotate %t %src %dest');
1297 @define
('_ROTATE_COMMAND', '');
1298 if (_ROTATE_COMMAND
!=='') {
1299 $commande = str_replace(
1300 array('%t', '%src', '%dest'),
1303 escapeshellcmd($im),
1304 escapeshellcmd($dest)
1307 spip_log($commande);
1309 if (file_exists($dest)) // precaution
1310 $effectuer_gd = false;
1313 // cette variante genere-t-elle un fond transparent
1314 // dans les coins vide issus de la rotation ?
1315 elseif (function_exists('imagick_rotate')) {
1316 $handle = imagick_readimage ($im);
1317 if ($handle && imagick_isopaqueimage( $handle )) {
1318 imagick_setfillcolor($handle, 'transparent');
1319 imagick_rotate( $handle, $angle);
1320 imagick_writeimage( $handle, $dest);
1321 $effectuer_gd = false;
1324 if ($effectuer_gd) {
1325 // Creation de l'image en deux temps
1326 // de facon a conserver les GIF transparents
1327 $im = $image["fonction_imagecreatefrom"]($im);
1328 imagepalettetotruecolor($im);
1329 $im = image_RotateBicubic($im, $angle, true);
1330 _image_gd_output($im,$image);
1334 list ($src_y,$src_x) = taille_image($dest);
1335 return _image_ecrire_tag($image,array('src'=>$dest,'width'=>$src_x,'height'=>$src_y));
1338 // Permet d'appliquer un filtre php_imagick a une image
1339 // par exemple: [(#LOGO_ARTICLE|image_imagick{imagick_wave,20,60})]
1340 // liste des fonctions: http://www.linux-nantes.org/~fmonnier/doc/imagick/
1341 // http://doc.spip.org/@image_imagick
1342 function image_imagick () {
1343 $tous = func_get_args();
1347 $tous_var = join($tous, "-");
1349 $fonction = array('image_imagick', func_get_args());
1350 $image = _image_valeurs_trans($img, "$tous_var", "png",$fonction);
1351 if (!$image) return("");
1353 $im = $image["fichier"];
1354 $dest = $image["fichier_dest"];
1356 $creer = $image["creer"];
1359 if (function_exists($fonc)) {
1361 $handle = imagick_readimage ($im);
1363 for ($i=2; $i < count($tous); $i++
) $arr[] = $tous[$i];
1364 call_user_func_array($fonc, $arr);
1365 // Creer image dans fichier temporaire, puis renommer vers "bon" fichier
1366 // de facon a eviter time_out pendant creation de l'image definitive
1367 $tmp = preg_replace(",[.]png$,i", "-tmp.png", $dest);
1368 imagick_writeimage( $handle, $tmp);
1369 rename($tmp, $dest);
1370 ecrire_fichier($dest.".src",serialize($image));
1373 list ($src_y,$src_x) = taille_image($dest);
1374 return _image_ecrire_tag($image,array('src'=>$dest,'width'=>$src_x,'height'=>$src_y));
1378 // Permet de rendre une image
1379 // plus claire (gamma > 0)
1380 // ou plus foncee (gamma < 0)
1381 // http://doc.spip.org/@image_gamma
1382 function image_gamma($im, $gamma = 0){
1383 include_spip('filtres/images_lib');
1384 $fonction = array('image_gamma', func_get_args());
1385 $image = _image_valeurs_trans($im, "gamma-$gamma",false,$fonction);
1386 if (!$image) return("");
1388 $x_i = $image["largeur"];
1389 $y_i = $image["hauteur"];
1391 $im = $image["fichier"];
1392 $dest = $image["fichier_dest"];
1394 $creer = $image["creer"];
1397 // Creation de l'image en deux temps
1398 // de facon a conserver les GIF transparents
1399 $im = $image["fonction_imagecreatefrom"]($im);
1400 imagepalettetotruecolor($im);
1401 $im_ = imagecreatetruecolor($x_i, $y_i);
1402 @imagealphablending
($im_, false);
1403 @imagesavealpha
($im_,true);
1404 $color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
1405 imagefill ($im_, 0, 0, $color_t);
1406 imagecopy($im_, $im, 0, 0, 0, 0, $x_i, $y_i);
1408 for ($x = 0; $x < $x_i; $x++
) {
1409 for ($y=0; $y < $y_i; $y++
) {
1410 $rgb = ImageColorAt($im_, $x, $y);
1411 $a = ($rgb >> 24) & 0xFF;
1412 $r = ($rgb >> 16) & 0xFF;
1413 $g = ($rgb >> 8) & 0xFF;
1416 $r = _image_decale_composante($r, $gamma);
1417 $g = _image_decale_composante($g, $gamma);
1418 $b = _image_decale_composante($b, $gamma);
1420 $color = ImageColorAllocateAlpha( $im_, $r, $g, $b , $a );
1421 imagesetpixel ($im_, $x, $y, $color);
1424 _image_gd_output($im_,$image);
1426 return _image_ecrire_tag($image,array('src'=>$dest));
1429 // Passe l'image en "sepia"
1430 // On peut fixer les valeurs RGB
1431 // de la couleur "complementaire" pour forcer une dominante
1432 //function image_sepia($im, $dr = 137, $dv = 111, $db = 94)
1433 // http://doc.spip.org/@image_sepia
1434 function image_sepia($im, $rgb = "896f5e"){
1435 include_spip('filtres/images_lib');
1437 if (!function_exists("imagecreatetruecolor")) return $im;
1439 $couleurs = _couleur_hex_to_dec($rgb);
1440 $dr= $couleurs["red"];
1441 $dv= $couleurs["green"];
1442 $db= $couleurs["blue"];
1444 $fonction = array('image_sepia', func_get_args());
1445 $image = _image_valeurs_trans($im, "sepia-$dr-$dv-$db",false,$fonction);
1446 if (!$image) return("");
1448 $x_i = $image["largeur"];
1449 $y_i = $image["hauteur"];
1451 $im = $image["fichier"];
1452 $dest = $image["fichier_dest"];
1454 $creer = $image["creer"];
1457 // Creation de l'image en deux temps
1458 // de facon a conserver les GIF transparents
1459 $im = $image["fonction_imagecreatefrom"]($im);
1460 imagepalettetotruecolor($im);
1461 $im_ = imagecreatetruecolor($x_i, $y_i);
1462 @imagealphablending
($im_, false);
1463 @imagesavealpha
($im_,true);
1464 $color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
1465 imagefill ($im_, 0, 0, $color_t);
1466 imagecopy($im_, $im, 0, 0, 0, 0, $x_i, $y_i);
1468 for ($x = 0; $x < $x_i; $x++
) {
1469 for ($y=0; $y < $y_i; $y++
) {
1470 $rgb = ImageColorAt($im_, $x, $y);
1471 $a = ($rgb >> 24) & 0xFF;
1472 $r = ($rgb >> 16) & 0xFF;
1473 $g = ($rgb >> 8) & 0xFF;
1476 $r = round(.299 * $r +
.587 * $g +
.114 * $b);
1481 $r = _image_decale_composante_127($r, $dr);
1482 $g = _image_decale_composante_127($g, $dv);
1483 $b = _image_decale_composante_127($b, $db);
1485 $color = ImageColorAllocateAlpha( $im_, $r, $g, $b , $a );
1486 imagesetpixel ($im_, $x, $y, $color);
1489 _image_gd_output($im_,$image);
1494 return _image_ecrire_tag($image,array('src'=>$dest));
1498 // Renforcer la nettete d'une image
1499 // http://doc.spip.org/@image_renforcement
1500 function image_renforcement($im, $k=0.5)
1502 $fonction = array('image_flou', func_get_args());
1503 $image = _image_valeurs_trans($im, "renforcement-$k",false,$fonction);
1504 if (!$image) return("");
1506 $x_i = $image["largeur"];
1507 $y_i = $image["hauteur"];
1508 $im = $image["fichier"];
1509 $dest = $image["fichier_dest"];
1510 $creer = $image["creer"];
1513 $im = $image["fonction_imagecreatefrom"]($im);
1514 imagepalettetotruecolor($im);
1515 $im_ = imagecreatetruecolor($x_i, $y_i);
1516 @imagealphablending
($im_, false);
1517 @imagesavealpha
($im_,true);
1518 $color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
1519 imagefill ($im_, 0, 0, $color_t);
1521 for ($x = 0; $x < $x_i; $x++
) {
1522 for ($y=0; $y < $y_i; $y++
) {
1524 $rgb[1][0]=imagecolorat($im,$x,$y-1);
1525 $rgb[0][1]=imagecolorat($im,$x-1,$y);
1526 $rgb[1][1]=imagecolorat($im,$x,$y);
1527 $rgb[2][1]=imagecolorat($im,$x+
1,$y);
1528 $rgb[1][2]=imagecolorat($im,$x,$y+
1);
1531 if ($x-1 < 0) $rgb[0][1] = $rgb[1][1];
1532 if ($y-1 < 0) $rgb[1][0] = $rgb[1][1];
1533 if ($x+
1 == $x_i) $rgb[2][1] = $rgb[1][1];
1534 if ($y+
1 == $y_i) $rgb[1][2] = $rgb[1][1];
1536 $a = ($rgb[0][0] >> 24) & 0xFF;
1537 $r = -$k *(($rgb[1][0] >> 16) & 0xFF) +
1538 -$k *(($rgb[0][1] >> 16) & 0xFF) +
1539 (1+
4*$k) *(($rgb[1][1] >> 16) & 0xFF) +
1540 -$k *(($rgb[2][1] >> 16) & 0xFF) +
1541 -$k *(($rgb[1][2] >> 16) & 0xFF) ;
1543 $g = -$k *(($rgb[1][0] >> 8) & 0xFF) +
1544 -$k *(($rgb[0][1] >> 8) & 0xFF) +
1545 (1+
4*$k) *(($rgb[1][1] >> 8) & 0xFF) +
1546 -$k *(($rgb[2][1] >> 8) & 0xFF) +
1547 -$k *(($rgb[1][2] >> 8) & 0xFF) ;
1549 $b = -$k *($rgb[1][0] & 0xFF) +
1550 -$k *($rgb[0][1] & 0xFF) +
1551 (1+
4*$k) *($rgb[1][1] & 0xFF) +
1552 -$k *($rgb[2][1] & 0xFF) +
1553 -$k *($rgb[1][2] & 0xFF) ;
1555 $r=min(255,max(0,$r));
1556 $g=min(255,max(0,$g));
1557 $b=min(255,max(0,$b));
1560 $color = ImageColorAllocateAlpha( $im_, $r, $g, $b , $a );
1561 imagesetpixel ($im_, $x, $y, $color);
1564 _image_gd_output($im_,$image);
1567 return _image_ecrire_tag($image,array('src'=>$dest));
1574 * Transforme la couleur de fond de l'image en transparence
1575 * Le filtre ne gere pas la notion de contiguite aux bords, et affectera tous les pixels de l'image dans la couleur visee
1576 * $background_color : couleur cible
1577 * $tolerance : distance L1 dans l'espace RGB des couleur autour de la couleur $background_color pour lequel la transparence sera appliquee
1578 * $alpha : transparence a appliquer pour les pixels de la couleur cibles avec la tolerance ci-dessus
1579 * $coeff_lissage : coeff applique a la tolerance pour determiner la decroissance de la transparence fonction de la distance L1 entre la couleur du pixel et la couleur cible
1582 * @param string $background_color
1583 * @param int $tolerance
1585 * alpha = 0: aucune transparence
1586 * alpha = 127: completement transparent
1587 * @param int $coeff_lissage
1588 * @return mixed|null|string
1590 function image_fond_transparent($im, $background_color, $tolerance=12, $alpha = 127, $coeff_lissage=7)
1592 $fonction = array('image_fond_transparent', func_get_args());
1593 $image = _image_valeurs_trans($im, "fond_transparent-$background_color-$tolerance-$coeff_lissage-$alpha", "png", $fonction);
1594 if (!$image) return("");
1596 $x_i = $image["largeur"];
1597 $y_i = $image["hauteur"];
1599 $im = $image["fichier"];
1600 $dest = $image["fichier_dest"];
1602 $creer = $image["creer"];
1605 $bg = _couleur_hex_to_dec($background_color);
1607 $bg_g = $bg['green'];
1608 $bg_b = $bg['blue'];
1610 // Creation de l'image en deux temps
1611 // de facon a conserver les GIF transparents
1612 $im = $image["fonction_imagecreatefrom"]($im);
1613 imagepalettetotruecolor($im);
1614 $im2 = imagecreatetruecolor($x_i, $y_i);
1615 @imagealphablending
($im2, false);
1616 @imagesavealpha
($im2,true);
1617 $color_t = ImageColorAllocateAlpha( $im2, 255, 255, 255 , 127 );
1618 imagefill ($im2, 0, 0, $color_t);
1619 imagecopy($im2, $im, 0, 0, 0, 0, $x_i, $y_i);
1621 $im_ = imagecreatetruecolor($x_i, $y_i);
1622 imagealphablending ($im_, FALSE );
1623 imagesavealpha ( $im_, TRUE );
1624 $color_f = ImageColorAllocateAlpha( $im_, 255, 255, 255 , $alpha );
1626 for ($x = 0; $x < $x_i; $x++
) {
1627 for ($y = 0; $y < $y_i; $y++
) {
1628 $rgb = ImageColorAt($im2, $x, $y);
1629 $r = ($rgb >> 16) & 0xFF;
1630 $g = ($rgb >> 8) & 0xFF;
1632 if ((($d=abs($r-$bg_r)+
abs($g-$bg_g)+
abs($b-$bg_b))<=$tolerance)){
1633 imagesetpixel ( $im_, $x, $y, $color_f );
1635 elseif ($tolerance AND $d<=($coeff_lissage+
1)*$tolerance){
1636 $transp = round($alpha*(1-($d-$tolerance)/($coeff_lissage*$tolerance)));
1637 $color_p = ImageColorAllocateAlpha( $im_, $r, $g, $b , $transp);
1638 imagesetpixel ( $im_, $x, $y, $color_p );
1641 imagesetpixel ( $im_, $x, $y, $rgb );
1644 _image_gd_output($im_,$image);
1650 return _image_ecrire_tag($image,array('src'=>$dest));