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://code.spip.net/@image_aplatir
32 // 3/ $transparence a "true" permet de conserver la transparence (utile pour conversion GIF)
33 // http://code.spip.net/@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://code.spip.net/@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://code.spip.net/@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));
236 * http://code.spip.net/@image_recadre
239 * @param string|int $width
240 * largeur du recadrage
241 * ou ratio sous la forme "16:9"
242 * @param string|int $height
243 * hauteur du recadrage
244 * ou "+" (agrandir) ou "-" (reduire) si un ratio est fourni pour width
245 * @param string $position
246 * center, left, right, top, bottom, ou combinaisons ("top left")
247 * @param string $background_color
248 * couleur de fond si on agrandit l'image
250 * balise image recadree
252 function image_recadre($im,$width,$height,$position='center', $background_color='white')
254 $fonction = array('image_recadre', func_get_args());
255 $image = _image_valeurs_trans($im, "recadre-$width-$height-$position-$background_color",false,$fonction);
257 if (!$image) return("");
259 $x_i = $image["largeur"];
260 $y_i = $image["hauteur"];
262 if (_IMG_GD_MAX_PIXELS
&& $x_i*$y_i>_IMG_GD_MAX_PIXELS
){
263 spip_log("image_recadre impossible sur $im : ".$srcWidth*$srcHeight."pixels");
264 // on se rabat sur une reduction CSS
265 return _image_tag_changer_taille($im,$width,$height);
268 // on recadre pour respecter un ratio ?
270 // height : "+" pour agrandir l'image et "-" pour la croper
271 if (strpos($width,":")!==false){
272 list($wr,$hr) = explode(":",$width);
273 $hm = $x_i / $wr * $hr;
274 $ym = $y_i / $hr * $wr;
275 if ($height=="+"?
($y_i<$hm):($y_i>$hm)){
285 if ($width==0) $width=$x_i;
286 if ($height==0) $height=$y_i;
288 $offset_width = $x_i-$width;
289 $offset_height = $y_i-$height;
290 $position=strtolower($position);
291 if (strpos($position,'left')!==FALSE){
292 if (preg_match(';left=(\d{1}\d+);', $position, $left)){
293 $offset_width=$left[1];
299 elseif (strpos($position,'right')!==FALSE)
300 $offset_width=$offset_width;
302 $offset_width=intval(ceil($offset_width/2));
304 if (strpos($position,'top')!==FALSE){
305 if (preg_match(';top=(\d{1}\d+);', $position, $top)){
306 $offset_height=$top[1];
312 elseif (strpos($position,'bottom')!==FALSE)
313 $offset_height=$offset_height;
315 $offset_height=intval(ceil($offset_height/2));
317 $im = $image["fichier"];
318 $dest = $image["fichier_dest"];
320 $creer = $image["creer"];
323 $im = $image["fonction_imagecreatefrom"]($im);
324 imagepalettetotruecolor($im);
325 $im_ = imagecreatetruecolor($width, $height);
326 @imagealphablending
($im_, false);
327 @imagesavealpha
($im_,true);
329 if ($background_color=='transparent')
330 $color_t = imagecolorallocatealpha( $im_, 255, 255, 255 , 127 );
332 $bg = _couleur_hex_to_dec($background_color);
333 $color_t = imagecolorallocate( $im_, $bg['red'], $bg['green'], $bg['blue']);
335 imagefill ($im_, 0, 0, $color_t);
336 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));
338 _image_gd_output($im_,$image);
343 return _image_ecrire_tag($image,array('src'=>$dest,'width'=>$width,'height'=>$height));
348 * Recadrer une image dans le rectangle le plus petit possible sans perte
349 * de pixels non transparent
354 function image_recadre_mini($im)
356 $fonction = array('image_recadre_mini', func_get_args());
357 $image = _image_valeurs_trans($im, "recadre_mini",false,$fonction);
359 if (!$image) return("");
361 $width = $image["largeur"];
362 $height = $image["hauteur"];
364 $im = $image["fichier"];
365 $dest = $image["fichier_dest"];
367 $creer = $image["creer"];
369 $im = $image["fonction_imagecreatefrom"]($im);
370 imagepalettetotruecolor($im);
372 // trouver le rectangle mini qui contient des infos de couleur
373 // recherche optimisee qui ne balaye que par zone
378 while ($yy<=$height/2 AND $max_y<=$min_y){
380 for ($xx = 0; $xx < $width; $xx++
) {
381 $color_index = imagecolorat($im, $xx, $yy);
382 $color_tran = imagecolorsforindex($im, $color_index);
383 if ($color_tran['alpha']!==127){
384 $min_y = min($yy,$min_y);
385 $max_y = max($height-1-$yy,$max_y);
389 if($height-1-$yy>$max_y)
390 for ($xx = 0; $xx < $width; $xx++
) {
391 $color_index = imagecolorat($im, $xx, $height-1-$yy);
392 $color_tran = imagecolorsforindex($im, $color_index);
393 if ($color_tran['alpha']!==127){
394 $min_y = min($yy,$min_y);
395 $max_y = max($height-1-$yy,$max_y);
401 $min_y = min($max_y,$min_y); // tout a 0 aucun pixel trouve
404 while ($xx<=$width/2 AND $max_x<=$min_x){
406 for ($yy = $min_y; $yy < $max_y; $yy++
) {
407 $color_index = imagecolorat($im, $xx, $yy);
408 $color_tran = imagecolorsforindex($im, $color_index);
409 if ($color_tran['alpha']!==127){
410 $min_x = min($xx,$min_x);
411 $max_x = max($xx,$max_x);
412 break; // inutile de continuer sur cette colonne
415 if ($width-1-$xx>$max_x)
416 for ($yy = $min_y; $yy < $max_y; $yy++
) {
417 $color_index = imagecolorat($im, $width-1-$xx, $yy);
418 $color_tran = imagecolorsforindex($im, $color_index);
419 if ($color_tran['alpha']!==127){
420 $min_x = min($width-1-$xx,$min_x);
421 $max_x = max($width-1-$xx,$max_x);
422 break; // inutile de continuer sur cette colonne
427 $min_x = min($max_x,$min_x); // tout a 0 aucun pixel trouve
429 $width = $max_x-$min_x+
1;
430 $height = $max_y-$min_y+
1;
432 $im_ = imagecreatetruecolor($width, $height);
433 @imagealphablending
($im_, false);
434 @imagesavealpha
($im_,true);
436 $color_t = imagecolorallocatealpha( $im_, 255, 255, 255 , 127 );
437 imagefill ($im_, 0, 0, $color_t);
438 imagecopy($im_, $im, 0, 0, $min_x, $min_y, $width, $height);
440 _image_gd_output($im_,$image);
445 list ($height,$width) = taille_image($image['fichier_dest']);
448 return _image_ecrire_tag($image,array('src'=>$dest,'width'=>$width,'height'=>$height));
452 // http://code.spip.net/@image_flip_vertical
453 function image_flip_vertical($im)
455 $fonction = array('image_flip_vertical', func_get_args());
456 $image = _image_valeurs_trans($im, "flip_v", false,$fonction);
457 if (!$image) return("");
459 $x_i = $image["largeur"];
460 $y_i = $image["hauteur"];
462 $im = $image["fichier"];
463 $dest = $image["fichier_dest"];
465 $creer = $image["creer"];
468 $im = $image["fonction_imagecreatefrom"]($im);
469 imagepalettetotruecolor($im);
470 $im_ = imagecreatetruecolor($x_i, $y_i);
471 @imagealphablending
($im_, false);
472 @imagesavealpha
($im_,true);
474 $color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
475 imagefill ($im_, 0, 0, $color_t);
477 for ($x = 0; $x < $x_i; $x++
) {
478 for ($y = 0; $y < $y_i; $y++
) {
479 imagecopy($im_, $im, $x_i - $x - 1, $y, $x, $y, 1, 1);
483 _image_gd_output($im_,$image);
488 return _image_ecrire_tag($image,array('src'=>$dest));
491 // http://code.spip.net/@image_flip_horizontal
492 function image_flip_horizontal($im)
494 $fonction = array('image_flip_horizontal', func_get_args());
495 $image = _image_valeurs_trans($im, "flip_h",false,$fonction);
496 if (!$image) return("");
498 $x_i = $image["largeur"];
499 $y_i = $image["hauteur"];
501 $im = $image["fichier"];
502 $dest = $image["fichier_dest"];
504 $creer = $image["creer"];
507 $im = $image["fonction_imagecreatefrom"]($im);
508 imagepalettetotruecolor($im);
509 $im_ = imagecreatetruecolor($x_i, $y_i);
510 @imagealphablending
($im_, false);
511 @imagesavealpha
($im_,true);
513 $color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
514 imagefill ($im_, 0, 0, $color_t);
516 for ($x = 0; $x < $x_i; $x++
) {
517 for ($y = 0; $y < $y_i; $y++
) {
518 imagecopy($im_, $im, $x, $y_i - $y - 1, $x, $y, 1, 1);
521 _image_gd_output($im_,$image);
526 return _image_ecrire_tag($image,array('src'=>$dest));
529 // http://code.spip.net/@image_masque
530 function image_masque($im, $masque, $pos="") {
531 // Passer, en plus de l'image d'origine,
532 // une image de "masque": un fichier PNG24 transparent.
533 // Le decoupage se fera selon la transparence du "masque",
534 // et les couleurs seront eclaircies/foncees selon de couleur du masque.
535 // Pour ne pas modifier la couleur, le masque doit etre en gris 50%.
537 // Si l'image source est plus grande que le masque, alors cette image est reduite a la taille du masque.
538 // Sinon, c'est la taille de l'image source qui est utilisee.
540 // $pos est une variable libre, qui permet de passer left=..., right=..., bottom=..., top=...
541 // dans ce cas, le masque est place a ces positions sur l'image d'origine,
542 // et evidemment cette image d'origine n'est pas redimensionnee
544 // Positionnement horizontal: text-align=left, right, center
545 // Positionnement vertical : vertical-align=top, bottom, middle
546 // (les positionnements left, right, top, left sont relativement inutiles, mais coherence avec CSS)
548 // Choix du mode de fusion: mode=masque, normal, eclaircir, obscurcir, produit, difference, ecran, superposer, lumiere_dure, teinte, saturation, valeur
549 // https://en.wikipedia.org/wiki/Blend_modes
550 // masque: mode par defaut
551 // normal: place la nouvelle image par dessus l'ancienne
552 // eclaircir: place uniquement les points plus clairs
553 // obscurcir: place uniquement les points plus fonc'es
554 // produit: multiplie par le masque (points noirs rendent l'image noire, points blancs ne changent rien)
555 // difference: remplit avec l'ecart entre les couleurs d'origine et du masque
556 // ecran: effet inverse de 'produit' -> l'image resultante est plus claire
557 // superposer: combine les modes 'produit' et 'ecran' -> les parties claires sont eclaircies, les parties sombres assombries.
558 // lumiere_dure: equivalent a 'superposer', sauf que l'image du bas et du haut sont inversees.
559 // teinte: utilise la teinte du masque
560 // saturation: utilise la saturation du masque
561 // valeur: utilise la valeur du masque
565 $numargs = func_num_args();
566 $arg_list = func_get_args();
567 $texte = $arg_list[0];
568 for ($i = 1; $i < $numargs; $i++
) {
569 if ( ($p = strpos($arg_list[$i],"=")) !==false) {
570 $nom_variable = substr($arg_list[$i], 0, $p);
571 $val_variable = substr($arg_list[$i], $p+
1);
572 $variable["$nom_variable"] = $val_variable;
573 $defini["$nom_variable"] = 1;
576 if ($defini["mode"]) $mode = $variable["mode"];
578 // utiliser _image_valeurs_trans pour accepter comme masque :
579 // - une balise <img src='...' />
580 // - une image avec un timestamp ?01234
581 $mask = _image_valeurs_trans($masque, "source-image_masque", "png",null, true);
582 if (!$mask) return("");
583 $masque = $mask['fichier'];
585 $pos = md5(serialize($variable).$mask['date_src']);
586 $fonction = array('image_masque', func_get_args());
587 $image = _image_valeurs_trans($im, "masque-$masque-$pos", "png",$fonction);
588 if (!$image) return("");
590 $x_i = $image["largeur"];
591 $y_i = $image["hauteur"];
593 $im = $image["fichier"];
594 $dest = $image["fichier_dest"];
596 $creer = $image["creer"];
598 // doit-on positionner l'image ?
600 foreach (array("right", "left", "bottom", "top", "text-align", "vertical-align") as $pl) {
601 if (isset($defini[$pl]) and $defini[$pl]) {
609 $im_m = $mask["fichier"];
610 $x_m = $mask["largeur"];
611 $y_m = $mask["hauteur"];
613 $im2 = $mask["fonction_imagecreatefrom"]($masque);
614 if ($mask["format_source"] == "gif" AND function_exists('ImageCopyResampled')) {
615 $im2_ = imagecreatetruecolor($x_m, $y_m);
616 // Si un GIF est transparent,
617 // fabriquer un PNG transparent
618 // Conserver la transparence
619 if (function_exists("imageAntiAlias")) imageAntiAlias($im2_,true);
620 @imagealphablending
($im2_, false);
621 @imagesavealpha
($im2_,true);
622 @ImageCopyResampled
($im2_, $im2, 0, 0, 0, 0, $x_m, $y_m, $x_m, $y_m);
628 // On fabriquer une version "agrandie" du masque,
629 // aux dimensions de l'image source
630 // et on "installe" le masque dans cette image
631 // ainsi: aucun redimensionnement
636 if (isset($defini["right"]) and $defini["right"]) {
637 $right = $variable["right"];
638 $dx = ($x_i - $x_m) - $right;
640 if (isset($defini["bottom"]) and $defini["bottom"]) {
641 $bottom = $variable["bottom"];
642 $dy = ($y_i - $y_m) - $bottom;
644 if (isset($defini["top"]) and $defini["top"]) {
645 $top = $variable["top"];
648 if (isset($defini["left"]) and $defini["left"]) {
649 $left = $variable["left"];
652 if (isset($defini["text-align"]) and $defini["text-align"]) {
653 $align = $variable["text-align"];
654 if ($align == "right") {
657 } else if ($align == "left") {
660 } else if ($align = "center") {
661 $dx = round( ($x_i - $x_m) / 2 ) ;
664 if (isset($defini["vertical-align"]) and $defini["vertical-align"]) {
665 $valign = $variable["vertical-align"];
666 if ($valign == "bottom") {
669 } else if ($valign == "top") {
672 } else if ($valign = "middle") {
673 $dy = round( ($y_i - $y_m) / 2 ) ;
678 $im3 = imagecreatetruecolor($x_i, $y_i);
679 @imagealphablending
($im3, false);
680 @imagesavealpha
($im3,true);
681 if ($mode == "masque") $color_t = ImageColorAllocateAlpha( $im3, 128, 128, 128 , 0 );
682 else $color_t = ImageColorAllocateAlpha( $im3, 128, 128, 128 , 127 );
683 imagefill ($im3, 0, 0, $color_t);
686 imagecopy ( $im3, $im2, $dx, $dy, 0, 0, $x_m, $y_m);
689 $im2 = imagecreatetruecolor($x_i, $y_i);
690 @imagealphablending
($im2, false);
691 @imagesavealpha
($im2,true);
693 imagecopy ( $im2, $im3, 0, 0, 0, 0, $x_i, $y_i);
700 $rapport = $x_i / $x_m;
701 if (($y_i / $y_m) < $rapport ) {
702 $rapport = $y_i / $y_m;
705 $x_d = ceil($x_i / $rapport);
706 $y_d = ceil($y_i / $rapport);
709 if ($x_i < $x_m OR $y_i < $y_m) {
717 $x_dec = round(($x_d - $x_m) /2);
718 $y_dec = round(($y_d - $y_m) /2);
722 $nouveau = _image_valeurs_trans(image_reduire($im, $x_d, $y_d),"");
723 if (!is_array($nouveau)) return("");
724 $im_n = $nouveau["fichier"];
727 $im = $nouveau["fonction_imagecreatefrom"]($im_n);
728 imagepalettetotruecolor($im);
729 if ($nouveau["format_source"] == "gif" AND function_exists('ImageCopyResampled')) {
730 $im_ = imagecreatetruecolor($x_dest, $y_dest);
731 // Si un GIF est transparent,
732 // fabriquer un PNG transparent
733 // Conserver la transparence
734 if (function_exists("imageAntiAlias")) imageAntiAlias($im_,true);
735 @imagealphablending
($im_, false);
736 @imagesavealpha
($im_,true);
737 @ImageCopyResampled
($im_, $im, 0, 0, 0, 0, $x_dest, $y_dest, $x_dest, $y_dest);
741 $im_ = imagecreatetruecolor($x_dest, $y_dest);
742 @imagealphablending
($im_, false);
743 @imagesavealpha
($im_,true);
744 $color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
745 imagefill ($im_, 0, 0, $color_t);
748 // calcul couleurs de chaque pixel selon les modes de fusion
749 for ($x = 0; $x < $x_dest; $x++
) {
750 for ($y=0; $y < $y_dest; $y++
) {
751 $rgb = ImageColorAt($im2, $x, $y); // image au dessus
752 $a = ($rgb >> 24) & 0xFF;
753 $r = ($rgb >> 16) & 0xFF;
754 $g = ($rgb >> 8) & 0xFF;
757 $rgb2 = ImageColorAt($im, $x+
$x_dec, $y+
$y_dec); // image en dessous
758 $a2 = ($rgb2 >> 24) & 0xFF;
759 $r2 = ($rgb2 >> 16) & 0xFF;
760 $g2 = ($rgb2 >> 8) & 0xFF;
763 if ($mode == "normal") {
764 $v = (127 - $a) / 127;
770 $v2 = (127 - $a2) / 127;
775 } else if ($v2 == 0) {
779 } else if ($v == 0) {
784 $r_ = $r +
(($r2 - $r) * $v2 * (1 - $v));
785 $g_ = $g +
(($g2 - $g) * $v2 * (1 - $v));
786 $b_ = $b +
(($b2 - $b) * $v2 * (1 - $v));
791 } elseif (in_array($mode, array("produit","difference","superposer","lumiere_dure","ecran"))) {
792 if ($mode == "produit") {
796 } elseif ($mode == "difference") {
800 } elseif ($mode == "superposer") {
801 $r = ($r2 < 128) ?
2 * $r * $r2 / 255 : 255 - (2 * (255 - $r) * (255 - $r2) / 255);
802 $g = ($g2 < 128) ?
2 * $g * $g2 / 255 : 255 - (2 * (255 - $g) * (255 - $g2) / 255);
803 $b = ($b2 < 128) ?
2 * $b * $b2 / 255 : 255 - (2 * (255 - $b) * (255 - $b2) / 255);
804 } elseif ($mode == "lumiere_dure") {
805 $r = ($r < 128) ?
2 * $r * $r2 / 255 : 255 - (2 * (255 - $r2) * (255 - $r) / 255);
806 $g = ($g < 128) ?
2 * $g * $g2 / 255 : 255 - (2 * (255 - $g2) * (255 - $g) / 255);
807 $b = ($b < 128) ?
2 * $b * $b2 / 255 : 255 - (2 * (255 - $b2) * (255 - $b) / 255);
808 } elseif ($mode == "ecran") {
809 $r = 255 - (((255 - $r) * (255 - $r2)) / 255);
810 $g = 255 - (((255 - $g) * (255 - $g2)) / 255);
811 $b = 255 - (((255 - $b) * (255 - $b2)) / 255);
813 $r = max(0, min($r, 255));
814 $g = max(0, min($g, 255));
815 $b = max(0, min($b, 255));
817 // melange en fonction de la transparence du masque
818 $v = (127 - $a) / 127;
819 if ($v == 1) { // melange complet
824 $v2 = (127 - $a2) / 127;
825 if ($v+
$v2 == 0) { // ??
829 } else { // pas de melange (transparence du masque)
830 $r_ = $r +
(($r2 - $r) * $v2 * (1 - $v));
831 $g_ = $g +
(($g2 - $g) * $v2 * (1 - $v));
832 $b_ = $b +
(($b2 - $b) * $v2 * (1 - $v));
837 } elseif ($mode == "eclaircir" OR $mode == "obscurcir") {
838 $v = (127 - $a) / 127;
844 $v2 = (127 - $a2) / 127;
850 $r_ = $r +
(($r2 - $r) * $v2 * (1 - $v));
851 $g_ = $g +
(($g2 - $g) * $v2 * (1 - $v));
852 $b_ = $b +
(($b2 - $b) * $v2 * (1 - $v));
855 if ($mode == "eclaircir") {
856 $r_ = max ($r_, $r2);
857 $g_ = max ($g_, $g2);
858 $b_ = max ($b_, $b2);
860 $r_ = min ($r_, $r2);
861 $g_ = min ($g_, $g2);
862 $b_ = min ($b_, $b2);
866 } elseif (in_array($mode, array("teinte","saturation","valeur"))) {
867 include_spip("filtres/images_lib");
868 $hsv = _couleur_rgb2hsv($r, $g, $b); // image au dessus
872 $hsv2 = _couleur_rgb2hsv($r2, $g2, $b2); // image en dessous
878 $rgb3 = _couleur_hsv2rgb($h, $s2, $v2);
881 $rgb3 = _couleur_hsv2rgb($h2, $s, $v2);
884 $rgb3 = _couleur_hsv2rgb($h2, $s2, $v);
891 // melange en fonction de la transparence du masque
892 $v = (127 - $a) / 127;
893 if ($v == 1) { // melange complet
898 $v2 = (127 - $a2) / 127;
899 if ($v+
$v2 == 0) { // ??
903 } else { // pas de melange (transparence du masque)
904 $r_ = $r +
(($r2 - $r) * $v2 * (1 - $v));
905 $g_ = $g +
(($g2 - $g) * $v2 * (1 - $v));
906 $b_ = $b +
(($b2 - $b) * $v2 * (1 - $v));
912 $r_ = $r2 +
1 * ($r - 127);
913 $r_ = max(0, min($r_, 255));
914 $g_ = $g2 +
1 * ($g - 127);
915 $g_ = max(0, min($g_, 255));
916 $b_ = $b2 +
1 * ($b - 127);
917 $b_ = max(0, min($b_, 255));
918 $a_ = $a +
$a2 - round($a*$a2/127);
921 $color = ImageColorAllocateAlpha( $im_, $r_, $g_, $b_ , $a_ );
922 imagesetpixel ($im_, $x, $y, $color);
926 _image_gd_output($im_,$image);
932 $x_dest = largeur($dest);
933 $y_dest = hauteur($dest);
934 return _image_ecrire_tag($image,array('src'=>$dest,'width'=>$x_dest,'height'=>$y_dest));
937 // Passage de l'image en noir et blanc
938 // un noir & blanc "photo" n'est pas "neutre": les composantes de couleur sont
939 // ponderees pour obtenir le niveau de gris;
940 // on peut ici regler cette ponderation en "pour mille"
941 // http://code.spip.net/@image_nb
942 function image_nb($im, $val_r = 299, $val_g = 587, $val_b = 114)
944 $fonction = array('image_nb', func_get_args());
945 $image = _image_valeurs_trans($im, "nb-$val_r-$val_g-$val_b",false,$fonction);
946 if (!$image) return("");
948 $x_i = $image["largeur"];
949 $y_i = $image["hauteur"];
951 $im = $image["fichier"];
952 $dest = $image["fichier_dest"];
954 $creer = $image["creer"];
957 // resultat plus beau, mais tres lourd
958 // Et: indispensable pour preserver transparence!
961 // Creation de l'image en deux temps
962 // de facon a conserver les GIF transparents
963 $im = $image["fonction_imagecreatefrom"]($im);
964 imagepalettetotruecolor($im);
965 $im_ = imagecreatetruecolor($x_i, $y_i);
966 @imagealphablending
($im_, false);
967 @imagesavealpha
($im_,true);
968 $color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
969 imagefill ($im_, 0, 0, $color_t);
970 imagecopy($im_, $im, 0, 0, 0, 0, $x_i, $y_i);
972 for ($x = 0; $x < $x_i; $x++
) {
973 for ($y=0; $y < $y_i; $y++
) {
974 $rgb = ImageColorAt($im_, $x, $y);
975 $a = ($rgb >> 24) & 0xFF;
976 $r = ($rgb >> 16) & 0xFF;
977 $g = ($rgb >> 8) & 0xFF;
980 $c = round(($val_r * $r / 1000) +
($val_g * $g / 1000) +
($val_b * $b / 1000));
982 if ($c > 254) $c = 254;
985 $color = ImageColorAllocateAlpha( $im_, $c, $c, $c , $a );
986 imagesetpixel ($im_, $x, $y, $color);
989 _image_gd_output($im_,$image);
994 return _image_ecrire_tag($image,array('src'=>$dest));
997 // http://code.spip.net/@image_flou
998 function image_flou($im,$niveau=3)
1000 // Il s'agit d'une modification du script blur qu'on trouve un peu partout:
1001 // + la transparence est geree correctement
1002 // + les dimensions de l'image sont augmentees pour flouter les bords
1007 array ( 1, 3, 3, 1),
1008 array ( 1, 4, 6, 4, 1),
1009 array ( 1, 5, 10, 10, 5, 1),
1010 array ( 1, 6, 15, 20, 15, 6, 1),
1011 array ( 1, 7, 21, 35, 35, 21, 7, 1),
1012 array ( 1, 8, 28, 56, 70, 56, 28, 8, 1),
1013 array ( 1, 9, 36, 84, 126, 126, 84, 36, 9, 1),
1014 array ( 1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1),
1015 array ( 1, 11, 55, 165, 330, 462, 462, 330, 165, 55, 11, 1)
1018 $fonction = array('image_flou', func_get_args());
1019 $image = _image_valeurs_trans($im, "flou-$niveau", false,$fonction);
1020 if (!$image) return("");
1022 $x_i = $image["largeur"];
1023 $y_i = $image["hauteur"];
1024 $sum = pow (2, $niveau);
1026 $im = $image["fichier"];
1027 $dest = $image["fichier_dest"];
1029 $creer = $image["creer"];
1032 // resultat plus beau, mais tres lourd
1033 // Et: indispensable pour preserver transparence!
1036 // Creation de l'image en deux temps
1037 // de facon a conserver les GIF transparents
1038 $im = $image["fonction_imagecreatefrom"]($im);
1039 imagepalettetotruecolor($im);
1040 $temp1 = imagecreatetruecolor($x_i+
$niveau, $y_i);
1041 $temp2 = imagecreatetruecolor($x_i+
$niveau, $y_i+
$niveau);
1043 @imagealphablending
($temp1, false);
1044 @imagesavealpha
($temp1,true);
1045 @imagealphablending
($temp2, false);
1046 @imagesavealpha
($temp2,true);
1049 for ($i = 0; $i < $x_i+
$niveau; $i++
) {
1050 for ($j=0; $j < $y_i; $j++
) {
1057 for ( $k=0 ; $k <= $niveau ; ++
$k ) {
1058 $color = imagecolorat($im, $i_ = ($i-$niveau)+
$k , $j);
1060 $a = ($color >> 24) & 0xFF;
1061 $r = ($color >> 16) & 0xFF;
1062 $g = ($color >> 8) & 0xFF;
1063 $b = ($color) & 0xFF;
1065 if ($i_ < 0 OR $i_ >= $x_i) $a = 127;
1067 $coef = $coeffs[$niveau][$k];
1069 $ac = ((127-$a) / 127);
1073 $sumr +
= $r * $coef * $ac;
1074 $sumg +
= $g * $coef * $ac;
1075 $sumb +
= $b * $coef * $ac;
1076 $sum +
= $coef * $ac;
1079 if ($sum > 0) $color = ImageColorAllocateAlpha ($temp1, $sumr/$sum, $sumg/$sum, $sumb/$sum, $suma/$sum_);
1080 else $color = ImageColorAllocateAlpha ($temp1, 255, 255, 255, 127);
1081 imagesetpixel($temp1,$i,$j,$color);
1085 for ($i = 0; $i < $x_i+
$niveau; $i++
) {
1086 for ($j=0; $j < $y_i+
$niveau; $j++
) {
1093 for ( $k=0 ; $k <= $niveau ; ++
$k ) {
1094 $color = imagecolorat($temp1, $i, $j_ = $j-$niveau+
$k);
1095 $a = ($color >> 24) & 0xFF;
1096 $r = ($color >> 16) & 0xFF;
1097 $g = ($color >> 8) & 0xFF;
1098 $b = ($color) & 0xFF;
1099 if ($j_ < 0 OR $j_ >= $y_i) $a = 127;
1101 $suma +
= $a*$coeffs[$niveau][$k];
1102 $ac = ((127-$a) / 127);
1104 $sumr +
= $r * $coeffs[$niveau][$k] * $ac;
1105 $sumg +
= $g * $coeffs[$niveau][$k] * $ac;
1106 $sumb +
= $b * $coeffs[$niveau][$k] * $ac;
1107 $sum +
= $coeffs[$niveau][$k] * $ac;
1108 $sum_ +
= $coeffs[$niveau][$k];
1111 if ($sum > 0) $color = ImageColorAllocateAlpha ($temp2, $sumr/$sum, $sumg/$sum, $sumb/$sum, $suma/$sum_);
1112 else $color = ImageColorAllocateAlpha ($temp2, 255, 255, 255, 127);
1113 imagesetpixel($temp2,$i,$j,$color);
1117 _image_gd_output($temp2,$image);
1118 imagedestroy($temp1);
1119 imagedestroy($temp2);
1122 return _image_ecrire_tag($image,array('src'=>$dest,'width'=>($x_i+
$niveau),'height'=>($y_i+
$niveau)));
1125 // http://code.spip.net/@image_RotateBicubic
1126 function image_RotateBicubic($src_img, $angle, $bicubic=0) {
1127 include_spip('filtres/images_lib');
1129 if (round($angle/90)*90 == $angle) {
1131 if (round($angle/180)*180 == $angle) $rot = 180;
1137 // convert degrees to radians
1138 $angle = $angle +
180;
1139 $angle = deg2rad($angle);
1143 $src_x = imagesx($src_img);
1144 $src_y = imagesy($src_img);
1147 $center_x = floor(($src_x-1)/2);
1148 $center_y = floor(($src_y-1)/2);
1150 $cosangle = cos($angle);
1151 $sinangle = sin($angle);
1153 // calculer dimensions en simplifiant angles droits, ce qui evite "floutage"
1154 // des rotations a angle droit
1156 $corners=array(array(0,0), array($src_x,0), array($src_x,$src_y), array(0,$src_y));
1158 foreach($corners as $key=>$value) {
1159 $value[0]-=$center_x; //Translate coords to center for rotation
1160 $value[1]-=$center_y;
1162 $temp[0]=$value[0]*$cosangle+
$value[1]*$sinangle;
1163 $temp[1]=$value[1]*$cosangle-$value[0]*$sinangle;
1164 $corners[$key]=$temp;
1167 $min_x=1000000000000000;
1168 $max_x=-1000000000000000;
1169 $min_y=1000000000000000;
1170 $max_y=-1000000000000000;
1172 foreach($corners as $key => $value) {
1173 if($value[0]<$min_x)
1175 if($value[0]>$max_x)
1178 if($value[1]<$min_y)
1180 if($value[1]>$max_y)
1184 $rotate_width=ceil($max_x-$min_x);
1185 $rotate_height=ceil($max_y-$min_y);
1189 $rotate_height = $src_y;
1190 $rotate_width = $src_x;
1192 $rotate_height = $src_x;
1193 $rotate_width = $src_y;
1199 $rotate=imagecreatetruecolor($rotate_width,$rotate_height);
1200 imagealphablending($rotate, false);
1201 imagesavealpha($rotate, true);
1203 $cosangle = cos($angle);
1204 $sinangle = sin($angle);
1206 // arrondir pour rotations angle droit (car cos et sin dans {-1,0,1})
1208 $cosangle = round($cosangle);
1209 $sinangle = round($sinangle);
1212 $newcenter_x = ($rotate_width-1)/2;
1213 $newcenter_y = ($rotate_height-1)/2;
1216 for ($y = 0; $y < $rotate_height; $y++
) {
1217 for ($x = 0; $x < $rotate_width; $x++
) {
1219 $old_x = ((($newcenter_x-$x) * $cosangle +
($newcenter_y-$y) * $sinangle))
1221 $old_y = ((($newcenter_y-$y) * $cosangle - ($newcenter_x-$x) * $sinangle))
1224 $old_x = ceil($old_x);
1225 $old_y = ceil($old_y);
1227 if ( $old_x >= 0 && $old_x < $src_x
1228 && $old_y >= 0 && $old_y < $src_y ) {
1229 if ($bicubic == true) {
1237 // on prend chaque point, mais on pondere en fonction de la distance
1238 $rgb = ImageColorAt($src_img, $x0, $y0);
1239 $a1 = ($rgb >> 24) & 0xFF;
1240 $r1 = ($rgb >> 16) & 0xFF;
1241 $g1 = ($rgb >> 8) & 0xFF;
1243 $d1 = _image_distance_pixel($xo, $yo, $x0, $y0);
1245 $rgb = ImageColorAt($src_img, $x1, $y0);
1246 $a2 = ($rgb >> 24) & 0xFF;
1247 $r2 = ($rgb >> 16) & 0xFF;
1248 $g2 = ($rgb >> 8) & 0xFF;
1250 $d2 = _image_distance_pixel($xo, $yo, $x1, $y0);
1252 $rgb = ImageColorAt($src_img,$x0, $y1);
1253 $a3 = ($rgb >> 24) & 0xFF;
1254 $r3 = ($rgb >> 16) & 0xFF;
1255 $g3 = ($rgb >> 8) & 0xFF;
1257 $d3 = _image_distance_pixel($xo, $yo, $x0, $y1);
1259 $rgb = ImageColorAt($src_img,$x1, $y1);
1260 $a4 = ($rgb >> 24) & 0xFF;
1261 $r4 = ($rgb >> 16) & 0xFF;
1262 $g4 = ($rgb >> 8) & 0xFF;
1264 $d4 = _image_distance_pixel($xo, $yo, $x1, $y1);
1266 $ac1 = ((127-$a1) / 127);
1267 $ac2 = ((127-$a2) / 127);
1268 $ac3 = ((127-$a3) / 127);
1269 $ac4 = ((127-$a4) / 127);
1271 // limiter impact des couleurs transparentes,
1272 // mais attention tout transp: division par 0
1273 if ($ac1*$d1 +
$ac2*$d2 +
$ac3+
$d3 +
$ac4+
$d4 > 0) {
1274 if ($ac1 > 0) $d1 = $d1 * $ac1;
1275 if ($ac2 > 0) $d2 = $d2 * $ac2;
1276 if ($ac3 > 0) $d3 = $d3 * $ac3;
1277 if ($ac4 > 0) $d4 = $d4 * $ac4;
1280 $tot = $d1 +
$d2 +
$d3 +
$d4;
1282 $r = round((($d1*$r1)+
($d2*$r2)+
($d3*$r3)+
($d4*$r4))/$tot);
1283 $g = round((($d1*$g1+
($d2*$g2)+
$d3*$g3+
$d4*$g4))/$tot);
1284 $b = round((($d1*$b1+
($d2*$b2)+
$d3*$b3+
$d4*$b4))/$tot);
1285 $a = round((($d1*$a1+
($d2*$a2)+
$d3*$a3+
$d4*$a4))/$tot);
1286 $color = imagecolorallocatealpha($src_img, $r,$g,$b,$a);
1289 $color = imagecolorat($src_img, round($old_x), round($old_y));
1293 // this line sets the background colour
1294 $color = imagecolorallocatealpha($src_img, 255, 255, 255, 127);
1296 @imagesetpixel
($rotate, $x, $y, $color);
1302 // permet de faire tourner une image d'un angle quelconque
1303 // la fonction "crop" n'est pas implementee...
1304 // http://code.spip.net/@image_rotation
1305 function image_rotation($im, $angle, $crop=false)
1307 $fonction = array('image_rotation', func_get_args());
1308 $image = _image_valeurs_trans($im, "rot-$angle-$crop", "png", $fonction);
1309 if (!$image) return("");
1311 $im = $image["fichier"];
1312 $dest = $image["fichier_dest"];
1314 $creer = $image["creer"];
1317 $effectuer_gd = true;
1319 if(method_exists('Imagick','rotateImage')){
1320 $imagick = new Imagick();
1321 $imagick->readImage($im);
1322 $imagick->rotateImage(new ImagickPixel('none'), $angle);
1323 $imagick->writeImage($dest);
1324 $effectuer_gd = false;
1326 else if ($GLOBALS['meta']['image_process'] == "convert") {
1327 if (_CONVERT_COMMAND
!='') {
1328 @define
('_CONVERT_COMMAND', 'convert');
1329 @define
('_ROTATE_COMMAND', _CONVERT_COMMAND
.' -background none -rotate %t %src %dest');
1331 @define
('_ROTATE_COMMAND', '');
1332 if (_ROTATE_COMMAND
!=='') {
1333 $commande = str_replace(
1334 array('%t', '%src', '%dest'),
1337 escapeshellcmd($im),
1338 escapeshellcmd($dest)
1341 spip_log($commande);
1343 if (file_exists($dest)) // precaution
1344 $effectuer_gd = false;
1347 // cette variante genere-t-elle un fond transparent
1348 // dans les coins vide issus de la rotation ?
1349 elseif (function_exists('imagick_rotate')) {
1350 $handle = imagick_readimage ($im);
1351 if ($handle && imagick_isopaqueimage( $handle )) {
1352 imagick_setfillcolor($handle, 'transparent');
1353 imagick_rotate( $handle, $angle);
1354 imagick_writeimage( $handle, $dest);
1355 $effectuer_gd = false;
1358 if ($effectuer_gd) {
1359 // Creation de l'image en deux temps
1360 // de facon a conserver les GIF transparents
1361 $im = $image["fonction_imagecreatefrom"]($im);
1362 imagepalettetotruecolor($im);
1363 $im = image_RotateBicubic($im, $angle, true);
1364 _image_gd_output($im,$image);
1368 list ($src_y,$src_x) = taille_image($dest);
1369 return _image_ecrire_tag($image,array('src'=>$dest,'width'=>$src_x,'height'=>$src_y));
1372 // Permet d'appliquer un filtre php_imagick a une image
1373 // par exemple: [(#LOGO_ARTICLE|image_imagick{imagick_wave,20,60})]
1374 // liste des fonctions: http://www.linux-nantes.org/~fmonnier/doc/imagick/
1375 // http://code.spip.net/@image_imagick
1376 function image_imagick () {
1377 $tous = func_get_args();
1381 $tous_var = join($tous, "-");
1383 $fonction = array('image_imagick', func_get_args());
1384 $image = _image_valeurs_trans($img, "$tous_var", "png",$fonction);
1385 if (!$image) return("");
1387 $im = $image["fichier"];
1388 $dest = $image["fichier_dest"];
1390 $creer = $image["creer"];
1393 if (function_exists($fonc)) {
1395 $handle = imagick_readimage ($im);
1397 for ($i=2; $i < count($tous); $i++
) $arr[] = $tous[$i];
1398 call_user_func_array($fonc, $arr);
1399 // Creer image dans fichier temporaire, puis renommer vers "bon" fichier
1400 // de facon a eviter time_out pendant creation de l'image definitive
1401 $tmp = preg_replace(",[.]png$,i", "-tmp.png", $dest);
1402 imagick_writeimage( $handle, $tmp);
1403 rename($tmp, $dest);
1404 ecrire_fichier($dest.".src",serialize($image));
1407 list ($src_y,$src_x) = taille_image($dest);
1408 return _image_ecrire_tag($image,array('src'=>$dest,'width'=>$src_x,'height'=>$src_y));
1412 // Permet de rendre une image
1413 // plus claire (gamma > 0)
1414 // ou plus foncee (gamma < 0)
1415 // http://code.spip.net/@image_gamma
1416 function image_gamma($im, $gamma = 0){
1417 include_spip('filtres/images_lib');
1418 $fonction = array('image_gamma', func_get_args());
1419 $image = _image_valeurs_trans($im, "gamma-$gamma",false,$fonction);
1420 if (!$image) return("");
1422 $x_i = $image["largeur"];
1423 $y_i = $image["hauteur"];
1425 $im = $image["fichier"];
1426 $dest = $image["fichier_dest"];
1428 $creer = $image["creer"];
1431 // Creation de l'image en deux temps
1432 // de facon a conserver les GIF transparents
1433 $im = $image["fonction_imagecreatefrom"]($im);
1434 imagepalettetotruecolor($im);
1435 $im_ = imagecreatetruecolor($x_i, $y_i);
1436 @imagealphablending
($im_, false);
1437 @imagesavealpha
($im_,true);
1438 $color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
1439 imagefill ($im_, 0, 0, $color_t);
1440 imagecopy($im_, $im, 0, 0, 0, 0, $x_i, $y_i);
1442 for ($x = 0; $x < $x_i; $x++
) {
1443 for ($y=0; $y < $y_i; $y++
) {
1444 $rgb = ImageColorAt($im_, $x, $y);
1445 $a = ($rgb >> 24) & 0xFF;
1446 $r = ($rgb >> 16) & 0xFF;
1447 $g = ($rgb >> 8) & 0xFF;
1450 $r = _image_decale_composante($r, $gamma);
1451 $g = _image_decale_composante($g, $gamma);
1452 $b = _image_decale_composante($b, $gamma);
1454 $color = ImageColorAllocateAlpha( $im_, $r, $g, $b , $a );
1455 imagesetpixel ($im_, $x, $y, $color);
1458 _image_gd_output($im_,$image);
1460 return _image_ecrire_tag($image,array('src'=>$dest));
1463 // Passe l'image en "sepia"
1464 // On peut fixer les valeurs RGB
1465 // de la couleur "complementaire" pour forcer une dominante
1466 //function image_sepia($im, $dr = 137, $dv = 111, $db = 94)
1467 // http://code.spip.net/@image_sepia
1468 function image_sepia($im, $rgb = "896f5e"){
1469 include_spip('filtres/images_lib');
1471 if (!function_exists("imagecreatetruecolor")) return $im;
1473 $couleurs = _couleur_hex_to_dec($rgb);
1474 $dr= $couleurs["red"];
1475 $dv= $couleurs["green"];
1476 $db= $couleurs["blue"];
1478 $fonction = array('image_sepia', func_get_args());
1479 $image = _image_valeurs_trans($im, "sepia-$dr-$dv-$db",false,$fonction);
1480 if (!$image) return("");
1482 $x_i = $image["largeur"];
1483 $y_i = $image["hauteur"];
1485 $im = $image["fichier"];
1486 $dest = $image["fichier_dest"];
1488 $creer = $image["creer"];
1491 // Creation de l'image en deux temps
1492 // de facon a conserver les GIF transparents
1493 $im = $image["fonction_imagecreatefrom"]($im);
1494 imagepalettetotruecolor($im);
1495 $im_ = imagecreatetruecolor($x_i, $y_i);
1496 @imagealphablending
($im_, false);
1497 @imagesavealpha
($im_,true);
1498 $color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
1499 imagefill ($im_, 0, 0, $color_t);
1500 imagecopy($im_, $im, 0, 0, 0, 0, $x_i, $y_i);
1502 for ($x = 0; $x < $x_i; $x++
) {
1503 for ($y=0; $y < $y_i; $y++
) {
1504 $rgb = ImageColorAt($im_, $x, $y);
1505 $a = ($rgb >> 24) & 0xFF;
1506 $r = ($rgb >> 16) & 0xFF;
1507 $g = ($rgb >> 8) & 0xFF;
1510 $r = round(.299 * $r +
.587 * $g +
.114 * $b);
1515 $r = _image_decale_composante_127($r, $dr);
1516 $g = _image_decale_composante_127($g, $dv);
1517 $b = _image_decale_composante_127($b, $db);
1519 $color = ImageColorAllocateAlpha( $im_, $r, $g, $b , $a );
1520 imagesetpixel ($im_, $x, $y, $color);
1523 _image_gd_output($im_,$image);
1528 return _image_ecrire_tag($image,array('src'=>$dest));
1532 // Renforcer la nettete d'une image
1533 // http://code.spip.net/@image_renforcement
1534 function image_renforcement($im, $k=0.5)
1536 $fonction = array('image_flou', func_get_args());
1537 $image = _image_valeurs_trans($im, "renforcement-$k",false,$fonction);
1538 if (!$image) return("");
1540 $x_i = $image["largeur"];
1541 $y_i = $image["hauteur"];
1542 $im = $image["fichier"];
1543 $dest = $image["fichier_dest"];
1544 $creer = $image["creer"];
1547 $im = $image["fonction_imagecreatefrom"]($im);
1548 imagepalettetotruecolor($im);
1549 $im_ = imagecreatetruecolor($x_i, $y_i);
1550 @imagealphablending
($im_, false);
1551 @imagesavealpha
($im_,true);
1552 $color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
1553 imagefill ($im_, 0, 0, $color_t);
1555 for ($x = 0; $x < $x_i; $x++
) {
1556 for ($y=0; $y < $y_i; $y++
) {
1558 $rgb[1][0]=imagecolorat($im,$x,$y-1);
1559 $rgb[0][1]=imagecolorat($im,$x-1,$y);
1560 $rgb[1][1]=imagecolorat($im,$x,$y);
1561 $rgb[2][1]=imagecolorat($im,$x+
1,$y);
1562 $rgb[1][2]=imagecolorat($im,$x,$y+
1);
1565 if ($x-1 < 0) $rgb[0][1] = $rgb[1][1];
1566 if ($y-1 < 0) $rgb[1][0] = $rgb[1][1];
1567 if ($x+
1 == $x_i) $rgb[2][1] = $rgb[1][1];
1568 if ($y+
1 == $y_i) $rgb[1][2] = $rgb[1][1];
1570 $a = ($rgb[0][0] >> 24) & 0xFF;
1571 $r = -$k *(($rgb[1][0] >> 16) & 0xFF) +
1572 -$k *(($rgb[0][1] >> 16) & 0xFF) +
1573 (1+
4*$k) *(($rgb[1][1] >> 16) & 0xFF) +
1574 -$k *(($rgb[2][1] >> 16) & 0xFF) +
1575 -$k *(($rgb[1][2] >> 16) & 0xFF) ;
1577 $g = -$k *(($rgb[1][0] >> 8) & 0xFF) +
1578 -$k *(($rgb[0][1] >> 8) & 0xFF) +
1579 (1+
4*$k) *(($rgb[1][1] >> 8) & 0xFF) +
1580 -$k *(($rgb[2][1] >> 8) & 0xFF) +
1581 -$k *(($rgb[1][2] >> 8) & 0xFF) ;
1583 $b = -$k *($rgb[1][0] & 0xFF) +
1584 -$k *($rgb[0][1] & 0xFF) +
1585 (1+
4*$k) *($rgb[1][1] & 0xFF) +
1586 -$k *($rgb[2][1] & 0xFF) +
1587 -$k *($rgb[1][2] & 0xFF) ;
1589 $r=min(255,max(0,$r));
1590 $g=min(255,max(0,$g));
1591 $b=min(255,max(0,$b));
1594 $color = ImageColorAllocateAlpha( $im_, $r, $g, $b , $a );
1595 imagesetpixel ($im_, $x, $y, $color);
1598 _image_gd_output($im_,$image);
1601 return _image_ecrire_tag($image,array('src'=>$dest));
1608 * Transforme la couleur de fond de l'image en transparence
1609 * Le filtre ne gere pas la notion de contiguite aux bords, et affectera tous les pixels de l'image dans la couleur visee
1610 * $background_color : couleur cible
1611 * $tolerance : distance L1 dans l'espace RGB des couleur autour de la couleur $background_color pour lequel la transparence sera appliquee
1612 * $alpha : transparence a appliquer pour les pixels de la couleur cibles avec la tolerance ci-dessus
1613 * $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
1616 * @param string $background_color
1617 * @param int $tolerance
1619 * alpha = 0: aucune transparence
1620 * alpha = 127: completement transparent
1621 * @param int $coeff_lissage
1622 * @return mixed|null|string
1624 function image_fond_transparent($im, $background_color, $tolerance=12, $alpha = 127, $coeff_lissage=7)
1626 $fonction = array('image_fond_transparent', func_get_args());
1627 $image = _image_valeurs_trans($im, "fond_transparent-$background_color-$tolerance-$coeff_lissage-$alpha", "png", $fonction);
1628 if (!$image) return("");
1630 $x_i = $image["largeur"];
1631 $y_i = $image["hauteur"];
1633 $im = $image["fichier"];
1634 $dest = $image["fichier_dest"];
1636 $creer = $image["creer"];
1639 $bg = _couleur_hex_to_dec($background_color);
1641 $bg_g = $bg['green'];
1642 $bg_b = $bg['blue'];
1644 // Creation de l'image en deux temps
1645 // de facon a conserver les GIF transparents
1646 $im = $image["fonction_imagecreatefrom"]($im);
1647 imagepalettetotruecolor($im);
1648 $im2 = imagecreatetruecolor($x_i, $y_i);
1649 @imagealphablending
($im2, false);
1650 @imagesavealpha
($im2,true);
1651 $color_t = ImageColorAllocateAlpha( $im2, 255, 255, 255 , 127 );
1652 imagefill ($im2, 0, 0, $color_t);
1653 imagecopy($im2, $im, 0, 0, 0, 0, $x_i, $y_i);
1655 $im_ = imagecreatetruecolor($x_i, $y_i);
1656 imagealphablending ($im_, FALSE );
1657 imagesavealpha ( $im_, TRUE );
1658 $color_f = ImageColorAllocateAlpha( $im_, 255, 255, 255 , $alpha );
1660 for ($x = 0; $x < $x_i; $x++
) {
1661 for ($y = 0; $y < $y_i; $y++
) {
1662 $rgb = ImageColorAt($im2, $x, $y);
1663 $r = ($rgb >> 16) & 0xFF;
1664 $g = ($rgb >> 8) & 0xFF;
1666 if ((($d=abs($r-$bg_r)+
abs($g-$bg_g)+
abs($b-$bg_b))<=$tolerance)){
1667 imagesetpixel ( $im_, $x, $y, $color_f );
1669 elseif ($tolerance AND $d<=($coeff_lissage+
1)*$tolerance){
1670 $transp = round($alpha*(1-($d-$tolerance)/($coeff_lissage*$tolerance)));
1671 $color_p = ImageColorAllocateAlpha( $im_, $r, $g, $b , $transp);
1672 imagesetpixel ( $im_, $x, $y, $color_p );
1675 imagesetpixel ( $im_, $x, $y, $rgb );
1678 _image_gd_output($im_,$image);
1684 return _image_ecrire_tag($image,array('src'=>$dest));