[SPIP] ~maj v3.0.14-->v3.0.17
[ptitvelo/web/www.git] / www / plugins-dist / filtres_images / filtres / images_transforme.php
1 <?php
2 /***************************************************************************\
3 * SPIP, Systeme de publication pour l'internet *
4 * *
5 * Copyright (c) 2001-2014 *
6 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
7 * *
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 \***************************************************************************/
11
12 /**
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
17 */
18
19 if (!defined('_ECRIRE_INC_VERSION')) return;
20
21 // librairie de base du core
22 include_spip('inc/filtres_images_mini');
23
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)
35 {
36 if ($qualite===NULL){
37 if ($format=='jpg') $qualite=_IMG_GD_QUALITE;
38 elseif ($format=='png') $qualite=0;
39 else $qualite=128;
40 }
41 $fonction = array('image_aplatir', func_get_args());
42 $image = _image_valeurs_trans($im, "aplatir-$format-$coul-$qualite-$transparence", $format, $fonction);
43
44 if (!$image) return("");
45
46 include_spip('inc/filtres');
47 $couleurs = _couleur_hex_to_dec($coul);
48 $dr= $couleurs["red"];
49 $dv= $couleurs["green"];
50 $db= $couleurs["blue"];
51
52 $x_i = $image["largeur"];
53 $y_i = $image["hauteur"];
54
55 $im = $image["fichier"];
56 $dest = $image["fichier_dest"];
57
58 $creer = $image["creer"];
59
60 if ($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);
72 imagedestroy($im);
73 $im = $im_;
74 }
75
76 // allouer la couleur de fond
77 if ($transparence) {
78 @imagealphablending($im_, false);
79 @imagesavealpha($im_,true);
80 $color_t = imagecolorallocatealpha( $im_, $dr, $dv, $db, 127);
81 }
82 else $color_t = ImageColorAllocate( $im_, $dr, $dv, $db);
83
84 imagefill ($im_, 0, 0, $color_t);
85
86 //??
87 //$dist = abs($trait);
88
89 $transp_x = false;
90
91 for ($x = 0; $x < $x_i; $x++) {
92 for ($y=0; $y < $y_i; $y++) {
93
94 $rgb = ImageColorAt($im, $x, $y);
95 $a = ($rgb >> 24) & 0xFF;
96 $r = ($rgb >> 16) & 0xFF;
97 $g = ($rgb >> 8) & 0xFF;
98 $b = $rgb & 0xFF;
99
100 $a = (127-$a) / 127;
101
102 if ($a == 1) { // Limiter calculs
103 $r = $r;
104 $g = $g;
105 $b = $b;
106 }
107 else if ($a == 0) { // Limiter calculs
108 $r = $dr;
109 $g = $dv;
110 $b = $db;
111
112 $transp_x = $x; // Memoriser un point transparent
113 $transp_y = $y;
114
115 } else {
116 $r = round($a * $r + $dr * (1-$a));
117 $g = round($a * $g + $dv * (1-$a));
118 $b = round($a * $b + $db * (1-$a));
119 }
120 $a = (1-$a) *127;
121 $color = ImageColorAllocateAlpha( $im_, $r, $g, $b, $a);
122 imagesetpixel ($im_, $x, $y, $color);
123 }
124 }
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)
128
129
130 @imagetruecolortopalette($im,true,$qualite);
131
132
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);
140
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);
144 }
145
146
147 // produire le resultat
148 _image_gd_output($im, $image, $qualite);
149 }
150 else
151 _image_gd_output($im_, $image, $qualite);
152 imagedestroy($im_);
153 imagedestroy($im);
154 }
155 return _image_ecrire_tag($image,array('src'=>$dest));
156 }
157
158
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') {
164 $qualite = null;
165 if ($format=='png8') {$format='png';$qualite=128;}
166 return image_aplatir($img, $format, 'cccccc', $qualite, true);
167 }
168
169
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)
175 {
176 $fonction = array('image_alpha', func_get_args());
177 $image = _image_valeurs_trans($im, "alpha-$alpha", "png",$fonction);
178 if (!$image) return("");
179
180 $x_i = $image["largeur"];
181 $y_i = $image["hauteur"];
182
183 $im = $image["fichier"];
184 $dest = $image["fichier_dest"];
185
186 $creer = $image["creer"];
187
188 if ($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);
199
200 $im_ = imagecreatetruecolor($x_i, $y_i);
201 imagealphablending ($im_, FALSE );
202 imagesavealpha ( $im_, TRUE );
203
204
205
206 for ($x = 0; $x < $x_i; $x++) {
207 for ($y = 0; $y < $y_i; $y++) {
208 $rgb = ImageColorAt($im2, $x, $y);
209
210 if (function_exists('imagecolorallocatealpha')) {
211 $a = ($rgb >> 24) & 0xFF;
212 $r = ($rgb >> 16) & 0xFF;
213 $g = ($rgb >> 8) & 0xFF;
214 $b = $rgb & 0xFF;
215
216
217 $a_ = $alpha + $a - round($a*$alpha/127);
218 $rgb = imagecolorallocatealpha($im_, $r, $g, $b, $a_);
219 }
220 imagesetpixel ( $im_, $x, $y, $rgb );
221 }
222 }
223 _image_gd_output($im_,$image);
224 imagedestroy($im_);
225 imagedestroy($im);
226 imagedestroy($im2);
227 }
228
229
230 return _image_ecrire_tag($image,array('src'=>$dest));
231
232 }
233
234 // http://doc.spip.org/@image_recadre
235 function image_recadre($im,$width,$height,$position='center', $background_color='white')
236 {
237 $fonction = array('image_recadre', func_get_args());
238 $image = _image_valeurs_trans($im, "recadre-$width-$height-$position-$background_color",false,$fonction);
239
240 if (!$image) return("");
241
242 $x_i = $image["largeur"];
243 $y_i = $image["hauteur"];
244
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);
249 }
250
251 if ($width==0) $width=$x_i;
252 if ($height==0) $height=$y_i;
253
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];
260 }
261 else{
262 $offset_width=0;
263 }
264 }
265 elseif (strpos($position,'right')!==FALSE)
266 $offset_width=$offset_width;
267 else
268 $offset_width=intval(ceil($offset_width/2));
269
270 if (strpos($position,'top')!==FALSE){
271 if (preg_match(';top=(\d{1}\d+);', $position, $top)){
272 $offset_height=$top[1];
273 }
274 else{
275 $offset_height=0;
276 }
277 }
278 elseif (strpos($position,'bottom')!==FALSE)
279 $offset_height=$offset_height;
280 else
281 $offset_height=intval(ceil($offset_height/2));
282
283 $im = $image["fichier"];
284 $dest = $image["fichier_dest"];
285
286 $creer = $image["creer"];
287
288 if ($creer) {
289 $im = $image["fonction_imagecreatefrom"]($im);
290 imagepalettetotruecolor($im);
291 $im_ = imagecreatetruecolor($width, $height);
292 @imagealphablending($im_, false);
293 @imagesavealpha($im_,true);
294
295 if ($background_color=='transparent')
296 $color_t = imagecolorallocatealpha( $im_, 255, 255, 255 , 127 );
297 else {
298 $bg = _couleur_hex_to_dec($background_color);
299 $color_t = imagecolorallocate( $im_, $bg['red'], $bg['green'], $bg['blue']);
300 }
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));
303
304 _image_gd_output($im_,$image);
305 imagedestroy($im_);
306 imagedestroy($im);
307 }
308
309 return _image_ecrire_tag($image,array('src'=>$dest,'width'=>$width,'height'=>$height));
310 }
311
312
313 /**
314 * Recadrer une image dans le rectangle le plus petit possible sans perte
315 * de pixels non transparent
316 *
317 * @param string $im
318 * @return string
319 */
320 function image_recadre_mini($im)
321 {
322 $fonction = array('image_recadre_mini', func_get_args());
323 $image = _image_valeurs_trans($im, "recadre_mini",false,$fonction);
324
325 if (!$image) return("");
326
327 $width = $image["largeur"];
328 $height = $image["hauteur"];
329
330 $im = $image["fichier"];
331 $dest = $image["fichier_dest"];
332
333 $creer = $image["creer"];
334 if ($creer) {
335 $im = $image["fonction_imagecreatefrom"]($im);
336 imagepalettetotruecolor($im);
337
338 // trouver le rectangle mini qui contient des infos de couleur
339 // recherche optimisee qui ne balaye que par zone
340 $min_x = $width;
341 $min_y = $height;
342 $max_y = $max_x = 0;
343 $yy = 0;
344 while ($yy<=$height/2 AND $max_y<=$min_y){
345 if($yy<$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);
352 break;
353 }
354 }
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);
362 break;
363 }
364 }
365 $yy++;
366 }
367 $min_y = min($max_y,$min_y); // tout a 0 aucun pixel trouve
368
369 $xx = 0;
370 while ($xx<=$width/2 AND $max_x<=$min_x){
371 if ($xx<$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
379 }
380 }
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
389 }
390 }
391 $xx++;
392 }
393 $min_x = min($max_x,$min_x); // tout a 0 aucun pixel trouve
394
395 $width = $max_x-$min_x+1;
396 $height = $max_y-$min_y+1;
397
398 $im_ = imagecreatetruecolor($width, $height);
399 @imagealphablending($im_, false);
400 @imagesavealpha($im_,true);
401
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);
405
406 _image_gd_output($im_,$image);
407 imagedestroy($im_);
408 imagedestroy($im);
409 }
410 else {
411 list ($height,$width) = taille_image($image['fichier_dest']);
412 }
413
414 return _image_ecrire_tag($image,array('src'=>$dest,'width'=>$width,'height'=>$height));
415 }
416
417
418 // http://doc.spip.org/@image_flip_vertical
419 function image_flip_vertical($im)
420 {
421 $fonction = array('image_flip_vertical', func_get_args());
422 $image = _image_valeurs_trans($im, "flip_v", false,$fonction);
423 if (!$image) return("");
424
425 $x_i = $image["largeur"];
426 $y_i = $image["hauteur"];
427
428 $im = $image["fichier"];
429 $dest = $image["fichier_dest"];
430
431 $creer = $image["creer"];
432
433 if ($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);
439
440 $color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
441 imagefill ($im_, 0, 0, $color_t);
442
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);
446 }
447 }
448
449 _image_gd_output($im_,$image);
450 imagedestroy($im_);
451 imagedestroy($im);
452 }
453
454 return _image_ecrire_tag($image,array('src'=>$dest));
455 }
456
457 // http://doc.spip.org/@image_flip_horizontal
458 function image_flip_horizontal($im)
459 {
460 $fonction = array('image_flip_horizontal', func_get_args());
461 $image = _image_valeurs_trans($im, "flip_h",false,$fonction);
462 if (!$image) return("");
463
464 $x_i = $image["largeur"];
465 $y_i = $image["hauteur"];
466
467 $im = $image["fichier"];
468 $dest = $image["fichier_dest"];
469
470 $creer = $image["creer"];
471
472 if ($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);
478
479 $color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
480 imagefill ($im_, 0, 0, $color_t);
481
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);
485 }
486 }
487 _image_gd_output($im_,$image);
488 imagedestroy($im_);
489 imagedestroy($im);
490 }
491
492 return _image_ecrire_tag($image,array('src'=>$dest));
493 }
494
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%.
502 //
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.
505 //
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
509 //
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)
513 //
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
528
529 $mode = "masque";
530
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;
540 }
541 }
542 if ($defini["mode"]) $mode = $variable["mode"];
543
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'];
550
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("");
555
556 $x_i = $image["largeur"];
557 $y_i = $image["hauteur"];
558
559 $im = $image["fichier"];
560 $dest = $image["fichier_dest"];
561
562 $creer = $image["creer"];
563
564 // doit-on positionner l'image ?
565 $placer = false;
566 foreach (array("right", "left", "bottom", "top", "text-align", "vertical-align") as $pl) {
567 if (isset($defini[$pl]) and $defini[$pl]) {
568 $placer = true;
569 break;
570 }
571 }
572
573 if ($creer) {
574
575 $im_m = $mask["fichier"];
576 $x_m = $mask["largeur"];
577 $y_m = $mask["hauteur"];
578
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);
589 imagedestroy($im2);
590 $im2 = $im2_;
591 }
592
593 if ($placer) {
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
598
599 $dx = 0;
600 $dy = 0;
601
602 if (isset($defini["right"]) and $defini["right"]) {
603 $right = $variable["right"];
604 $dx = ($x_i - $x_m) - $right;
605 }
606 if (isset($defini["bottom"]) and $defini["bottom"]) {
607 $bottom = $variable["bottom"];
608 $dy = ($y_i - $y_m) - $bottom;
609 }
610 if (isset($defini["top"]) and $defini["top"]) {
611 $top = $variable["top"];
612 $dy = $top;
613 }
614 if (isset($defini["left"]) and $defini["left"]) {
615 $left = $variable["left"];
616 $dx = $left;
617 }
618 if (isset($defini["text-align"]) and $defini["text-align"]) {
619 $align = $variable["text-align"];
620 if ($align == "right") {
621 $right = 0;
622 $dx = ($x_i - $x_m);
623 } else if ($align == "left") {
624 $left = 0;
625 $dx = 0;
626 } else if ($align = "center") {
627 $dx = round( ($x_i - $x_m) / 2 ) ;
628 }
629 }
630 if (isset($defini["vertical-align"]) and $defini["vertical-align"]) {
631 $valign = $variable["vertical-align"];
632 if ($valign == "bottom") {
633 $bottom = 0;
634 $dy = ($y_i - $y_m);
635 } else if ($valign == "top") {
636 $top = 0;
637 $dy = 0;
638 } else if ($valign = "middle") {
639 $dy = round( ($y_i - $y_m) / 2 ) ;
640 }
641 }
642
643
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);
650
651
652 imagecopy ( $im3, $im2, $dx, $dy, 0, 0, $x_m, $y_m);
653
654 imagedestroy($im2);
655 $im2 = imagecreatetruecolor($x_i, $y_i);
656 @imagealphablending($im2, false);
657 @imagesavealpha($im2,true);
658
659 imagecopy ( $im2, $im3, 0, 0, 0, 0, $x_i, $y_i);
660 imagedestroy($im3);
661 $x_m = $x_i;
662 $y_m = $y_i;
663 }
664
665
666 $rapport = $x_i / $x_m;
667 if (($y_i / $y_m) < $rapport ) {
668 $rapport = $y_i / $y_m;
669 }
670
671 $x_d = ceil($x_i / $rapport);
672 $y_d = ceil($y_i / $rapport);
673
674
675 if ($x_i < $x_m OR $y_i < $y_m) {
676 $x_dest = $x_i;
677 $y_dest = $y_i;
678 $x_dec = 0;
679 $y_dec = 0;
680 } else {
681 $x_dest = $x_m;
682 $y_dest = $y_m;
683 $x_dec = round(($x_d - $x_m) /2);
684 $y_dec = round(($y_d - $y_m) /2);
685 }
686
687
688 $nouveau = _image_valeurs_trans(image_reduire($im, $x_d, $y_d),"");
689 if (!is_array($nouveau)) return("");
690 $im_n = $nouveau["fichier"];
691
692
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);
704 imagedestroy($im);
705 $im = $im_;
706 }
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);
712
713
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;
721 $b = $rgb & 0xFF;
722
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;
727 $b2 = $rgb2 & 0xFF;
728
729 if ($mode == "normal") {
730 $v = (127 - $a) / 127;
731 if ($v == 1) {
732 $r_ = $r;
733 $g_ = $g;
734 $b_ = $b;
735 } else {
736 $v2 = (127 - $a2) / 127;
737 if ($v+$v2 == 0) {
738 $r_ = $r2;
739 $g_ = $g2;
740 $b_ = $b2;
741 } else if ($v2 == 0) {
742 $r_ = $r;
743 $g_ = $g;
744 $b_ = $b;
745 } else if ($v == 0) {
746 $r_ = $r2;
747 $g_ = $g2;
748 $b_ = $b2;
749 }else {
750 $r_ = $r + (($r2 - $r) * $v2 * (1 - $v));
751 $g_ = $g + (($g2 - $g) * $v2 * (1 - $v));
752 $b_ = $b + (($b2 - $b) * $v2 * (1 - $v));
753 }
754 }
755 $a_ = min($a,$a2);
756
757 } elseif (in_array($mode, array("produit","difference","superposer","lumiere_dure","ecran"))) {
758 if ($mode == "produit") {
759 $r = ($r/255) * $r2;
760 $g = ($g/255) * $g2;
761 $b = ($b/255) * $b2;
762 } elseif ($mode == "difference") {
763 $r = abs($r-$r2);
764 $g = abs($g-$g2);
765 $b = abs($b-$b2);
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);
778 }
779 $r = max(0, min($r, 255));
780 $g = max(0, min($g, 255));
781 $b = max(0, min($b, 255));
782
783 // melange en fonction de la transparence du masque
784 $v = (127 - $a) / 127;
785 if ($v == 1) { // melange complet
786 $r_ = $r;
787 $g_ = $g;
788 $b_ = $b;
789 } else {
790 $v2 = (127 - $a2) / 127;
791 if ($v+$v2 == 0) { // ??
792 $r_ = $r2;
793 $g_ = $g2;
794 $b_ = $b2;
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));
799 }
800 }
801 $a_ = $a2;
802
803 } elseif ($mode == "eclaircir" OR $mode == "obscurcir") {
804 $v = (127 - $a) / 127;
805 if ($v == 1) {
806 $r_ = $r;
807 $g_ = $g;
808 $b_ = $b;
809 } else {
810 $v2 = (127 - $a2) / 127;
811 if ($v+$v2 == 0) {
812 $r_ = $r2;
813 $g_ = $g2;
814 $b_ = $b2;
815 } else {
816 $r_ = $r + (($r2 - $r) * $v2 * (1 - $v));
817 $g_ = $g + (($g2 - $g) * $v2 * (1 - $v));
818 $b_ = $b + (($b2 - $b) * $v2 * (1 - $v));
819 }
820 }
821 if ($mode == "eclaircir") {
822 $r_ = max ($r_, $r2);
823 $g_ = max ($g_, $g2);
824 $b_ = max ($b_, $b2);
825 } else {
826 $r_ = min ($r_, $r2);
827 $g_ = min ($g_, $g2);
828 $b_ = min ($b_, $b2);
829 }
830 $a_ = min($a,$a2);
831
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
835 $h = $hsv["h"];
836 $s = $hsv["s"];
837 $v = $hsv["v"];
838 $hsv2 = _couleur_rgb2hsv($r2, $g2, $b2); // image en dessous
839 $h2 = $hsv2["h"];
840 $s2 = $hsv2["s"];
841 $v2 = $hsv2["v"];
842 switch ($mode) {
843 case "teinte";
844 $rgb3 = _couleur_hsv2rgb($h, $s2, $v2);
845 break;
846 case "saturation";
847 $rgb3 = _couleur_hsv2rgb($h2, $s, $v2);
848 break;
849 case "valeur";
850 $rgb3 = _couleur_hsv2rgb($h2, $s2, $v);
851 break;
852 }
853 $r = $rgb3["r"];
854 $g = $rgb3["g"];
855 $b = $rgb3["b"];
856
857 // melange en fonction de la transparence du masque
858 $v = (127 - $a) / 127;
859 if ($v == 1) { // melange complet
860 $r_ = $r;
861 $g_ = $g;
862 $b_ = $b;
863 } else {
864 $v2 = (127 - $a2) / 127;
865 if ($v+$v2 == 0) { // ??
866 $r_ = $r2;
867 $g_ = $g2;
868 $b_ = $b2;
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));
873 }
874 }
875 $a_ = $a2;
876
877 } else {
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);
885 }
886
887 $color = ImageColorAllocateAlpha( $im_, $r_, $g_, $b_ , $a_ );
888 imagesetpixel ($im_, $x, $y, $color);
889 }
890 }
891
892 _image_gd_output($im_,$image);
893 imagedestroy($im_);
894 imagedestroy($im);
895 imagedestroy($im2);
896
897 }
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));
901 }
902
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)
909 {
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("");
913
914 $x_i = $image["largeur"];
915 $y_i = $image["hauteur"];
916
917 $im = $image["fichier"];
918 $dest = $image["fichier_dest"];
919
920 $creer = $image["creer"];
921
922 // Methode precise
923 // resultat plus beau, mais tres lourd
924 // Et: indispensable pour preserver transparence!
925
926 if ($creer) {
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);
937
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;
944 $b = $rgb & 0xFF;
945
946 $c = round(($val_r * $r / 1000) + ($val_g * $g / 1000) + ($val_b * $b / 1000));
947 if ($c < 0) $c = 0;
948 if ($c > 254) $c = 254;
949
950
951 $color = ImageColorAllocateAlpha( $im_, $c, $c, $c , $a );
952 imagesetpixel ($im_, $x, $y, $color);
953 }
954 }
955 _image_gd_output($im_,$image);
956 imagedestroy($im_);
957 imagedestroy($im);
958 }
959
960 return _image_ecrire_tag($image,array('src'=>$dest));
961 }
962
963 // http://doc.spip.org/@image_flou
964 function image_flou($im,$niveau=3)
965 {
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
969 $coeffs = array (
970 array ( 1),
971 array ( 1, 1),
972 array ( 1, 2, 1),
973 array ( 1, 3, 3, 1),
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)
982 );
983
984 $fonction = array('image_flou', func_get_args());
985 $image = _image_valeurs_trans($im, "flou-$niveau", false,$fonction);
986 if (!$image) return("");
987
988 $x_i = $image["largeur"];
989 $y_i = $image["hauteur"];
990 $sum = pow (2, $niveau);
991
992 $im = $image["fichier"];
993 $dest = $image["fichier_dest"];
994
995 $creer = $image["creer"];
996
997 // Methode precise
998 // resultat plus beau, mais tres lourd
999 // Et: indispensable pour preserver transparence!
1000
1001 if ($creer) {
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);
1008
1009 @imagealphablending($temp1, false);
1010 @imagesavealpha($temp1,true);
1011 @imagealphablending($temp2, false);
1012 @imagesavealpha($temp2,true);
1013
1014
1015 for ($i = 0; $i < $x_i+$niveau; $i++) {
1016 for ($j=0; $j < $y_i; $j++) {
1017 $suma=0;
1018 $sumr=0;
1019 $sumg=0;
1020 $sumb=0;
1021 $sum = 0;
1022 $sum_ = 0;
1023 for ( $k=0 ; $k <= $niveau ; ++$k ) {
1024 $color = imagecolorat($im, $i_ = ($i-$niveau)+$k , $j);
1025
1026 $a = ($color >> 24) & 0xFF;
1027 $r = ($color >> 16) & 0xFF;
1028 $g = ($color >> 8) & 0xFF;
1029 $b = ($color) & 0xFF;
1030
1031 if ($i_ < 0 OR $i_ >= $x_i) $a = 127;
1032
1033 $coef = $coeffs[$niveau][$k];
1034 $suma += $a*$coef;
1035 $ac = ((127-$a) / 127);
1036
1037 $ac = $ac*$ac;
1038
1039 $sumr += $r * $coef * $ac;
1040 $sumg += $g * $coef * $ac;
1041 $sumb += $b * $coef * $ac;
1042 $sum += $coef * $ac;
1043 $sum_ += $coef;
1044 }
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);
1048 }
1049 }
1050 imagedestroy($im);
1051 for ($i = 0; $i < $x_i+$niveau; $i++) {
1052 for ($j=0; $j < $y_i+$niveau; $j++) {
1053 $suma=0;
1054 $sumr=0;
1055 $sumg=0;
1056 $sumb=0;
1057 $sum = 0;
1058 $sum_ = 0;
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;
1066
1067 $suma += $a*$coeffs[$niveau][$k];
1068 $ac = ((127-$a) / 127);
1069
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];
1075
1076 }
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);
1080 }
1081 }
1082
1083 _image_gd_output($temp2,$image);
1084 imagedestroy($temp1);
1085 imagedestroy($temp2);
1086 }
1087
1088 return _image_ecrire_tag($image,array('src'=>$dest,'width'=>($x_i+$niveau),'height'=>($y_i+$niveau)));
1089 }
1090
1091 // http://doc.spip.org/@image_RotateBicubic
1092 function image_RotateBicubic($src_img, $angle, $bicubic=0) {
1093 include_spip('filtres/images_lib');
1094
1095 if (round($angle/90)*90 == $angle) {
1096 $droit = true;
1097 if (round($angle/180)*180 == $angle) $rot = 180;
1098 else $rot = 90;
1099 }
1100 else
1101 $droit = false;
1102
1103 // convert degrees to radians
1104 $angle = $angle + 180;
1105 $angle = deg2rad($angle);
1106
1107
1108
1109 $src_x = imagesx($src_img);
1110 $src_y = imagesy($src_img);
1111
1112
1113 $center_x = floor(($src_x-1)/2);
1114 $center_y = floor(($src_y-1)/2);
1115
1116 $cosangle = cos($angle);
1117 $sinangle = sin($angle);
1118
1119 // calculer dimensions en simplifiant angles droits, ce qui evite "floutage"
1120 // des rotations a angle droit
1121 if (!$droit) {
1122 $corners=array(array(0,0), array($src_x,0), array($src_x,$src_y), array(0,$src_y));
1123
1124 foreach($corners as $key=>$value) {
1125 $value[0]-=$center_x; //Translate coords to center for rotation
1126 $value[1]-=$center_y;
1127 $temp=array();
1128 $temp[0]=$value[0]*$cosangle+$value[1]*$sinangle;
1129 $temp[1]=$value[1]*$cosangle-$value[0]*$sinangle;
1130 $corners[$key]=$temp;
1131 }
1132
1133 $min_x=1000000000000000;
1134 $max_x=-1000000000000000;
1135 $min_y=1000000000000000;
1136 $max_y=-1000000000000000;
1137
1138 foreach($corners as $key => $value) {
1139 if($value[0]<$min_x)
1140 $min_x=$value[0];
1141 if($value[0]>$max_x)
1142 $max_x=$value[0];
1143
1144 if($value[1]<$min_y)
1145 $min_y=$value[1];
1146 if($value[1]>$max_y)
1147 $max_y=$value[1];
1148 }
1149
1150 $rotate_width=ceil($max_x-$min_x);
1151 $rotate_height=ceil($max_y-$min_y);
1152 }
1153 else {
1154 if ($rot == 180) {
1155 $rotate_height = $src_y;
1156 $rotate_width = $src_x;
1157 } else {
1158 $rotate_height = $src_x;
1159 $rotate_width = $src_y;
1160 }
1161 $bicubic = false;
1162 }
1163
1164
1165 $rotate=imagecreatetruecolor($rotate_width,$rotate_height);
1166 imagealphablending($rotate, false);
1167 imagesavealpha($rotate, true);
1168
1169 $cosangle = cos($angle);
1170 $sinangle = sin($angle);
1171
1172 // arrondir pour rotations angle droit (car cos et sin dans {-1,0,1})
1173 if ($droit) {
1174 $cosangle = round($cosangle);
1175 $sinangle = round($sinangle);
1176 }
1177
1178 $newcenter_x = ($rotate_width-1)/2;
1179 $newcenter_y = ($rotate_height-1)/2;
1180
1181
1182 for ($y = 0; $y < $rotate_height; $y++) {
1183 for ($x = 0; $x < $rotate_width; $x++) {
1184 // rotate...
1185 $old_x = ((($newcenter_x-$x) * $cosangle + ($newcenter_y-$y) * $sinangle))
1186 + $center_x;
1187 $old_y = ((($newcenter_y-$y) * $cosangle - ($newcenter_x-$x) * $sinangle))
1188 + $center_y;
1189
1190 $old_x = ceil($old_x);
1191 $old_y = ceil($old_y);
1192
1193 if ( $old_x >= 0 && $old_x < $src_x
1194 && $old_y >= 0 && $old_y < $src_y ) {
1195 if ($bicubic == true) {
1196 $xo = $old_x;
1197 $x0 = floor($xo);
1198 $x1 = ceil($xo);
1199 $yo = $old_y;
1200 $y0 = floor($yo);
1201 $y1 = ceil($yo);
1202
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;
1208 $b1 = $rgb & 0xFF;
1209 $d1 = _image_distance_pixel($xo, $yo, $x0, $y0);
1210
1211 $rgb = ImageColorAt($src_img, $x1, $y0);
1212 $a2 = ($rgb >> 24) & 0xFF;
1213 $r2 = ($rgb >> 16) & 0xFF;
1214 $g2 = ($rgb >> 8) & 0xFF;
1215 $b2 = $rgb & 0xFF;
1216 $d2 = _image_distance_pixel($xo, $yo, $x1, $y0);
1217
1218 $rgb = ImageColorAt($src_img,$x0, $y1);
1219 $a3 = ($rgb >> 24) & 0xFF;
1220 $r3 = ($rgb >> 16) & 0xFF;
1221 $g3 = ($rgb >> 8) & 0xFF;
1222 $b3 = $rgb & 0xFF;
1223 $d3 = _image_distance_pixel($xo, $yo, $x0, $y1);
1224
1225 $rgb = ImageColorAt($src_img,$x1, $y1);
1226 $a4 = ($rgb >> 24) & 0xFF;
1227 $r4 = ($rgb >> 16) & 0xFF;
1228 $g4 = ($rgb >> 8) & 0xFF;
1229 $b4 = $rgb & 0xFF;
1230 $d4 = _image_distance_pixel($xo, $yo, $x1, $y1);
1231
1232 $ac1 = ((127-$a1) / 127);
1233 $ac2 = ((127-$a2) / 127);
1234 $ac3 = ((127-$a3) / 127);
1235 $ac4 = ((127-$a4) / 127);
1236
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;
1244 }
1245
1246 $tot = $d1 + $d2 + $d3 + $d4;
1247
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);
1253 }
1254 else {
1255 $color = imagecolorat($src_img, round($old_x), round($old_y));
1256 }
1257 }
1258 else {
1259 // this line sets the background colour
1260 $color = imagecolorallocatealpha($src_img, 255, 255, 255, 127);
1261 }
1262 @imagesetpixel($rotate, $x, $y, $color);
1263 }
1264 }
1265 return $rotate;
1266 }
1267
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)
1272 {
1273 $fonction = array('image_rotation', func_get_args());
1274 $image = _image_valeurs_trans($im, "rot-$angle-$crop", "png", $fonction);
1275 if (!$image) return("");
1276
1277 $im = $image["fichier"];
1278 $dest = $image["fichier_dest"];
1279
1280 $creer = $image["creer"];
1281
1282 if ($creer) {
1283 $effectuer_gd = true;
1284
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;
1291 }
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');
1296 } else
1297 @define ('_ROTATE_COMMAND', '');
1298 if (_ROTATE_COMMAND!=='') {
1299 $commande = str_replace(
1300 array('%t', '%src', '%dest'),
1301 array(
1302 $angle,
1303 escapeshellcmd($im),
1304 escapeshellcmd($dest)
1305 ),
1306 _ROTATE_COMMAND);
1307 spip_log($commande);
1308 exec($commande);
1309 if (file_exists($dest)) // precaution
1310 $effectuer_gd = false;
1311 }
1312 }
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;
1322 }
1323 }
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);
1331 imagedestroy($im);
1332 }
1333 }
1334 list ($src_y,$src_x) = taille_image($dest);
1335 return _image_ecrire_tag($image,array('src'=>$dest,'width'=>$src_x,'height'=>$src_y));
1336 }
1337
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();
1344 $img = $tous[0];
1345 $fonc = $tous[1];
1346 $tous[0]="";
1347 $tous_var = join($tous, "-");
1348
1349 $fonction = array('image_imagick', func_get_args());
1350 $image = _image_valeurs_trans($img, "$tous_var", "png",$fonction);
1351 if (!$image) return("");
1352
1353 $im = $image["fichier"];
1354 $dest = $image["fichier_dest"];
1355
1356 $creer = $image["creer"];
1357
1358 if ($creer) {
1359 if (function_exists($fonc)) {
1360
1361 $handle = imagick_readimage ($im);
1362 $arr[0] = $handle;
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));
1371 }
1372 }
1373 list ($src_y,$src_x) = taille_image($dest);
1374 return _image_ecrire_tag($image,array('src'=>$dest,'width'=>$src_x,'height'=>$src_y));
1375
1376 }
1377
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("");
1387
1388 $x_i = $image["largeur"];
1389 $y_i = $image["hauteur"];
1390
1391 $im = $image["fichier"];
1392 $dest = $image["fichier_dest"];
1393
1394 $creer = $image["creer"];
1395
1396 if ($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);
1407
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;
1414 $b = $rgb & 0xFF;
1415
1416 $r = _image_decale_composante($r, $gamma);
1417 $g = _image_decale_composante($g, $gamma);
1418 $b = _image_decale_composante($b, $gamma);
1419
1420 $color = ImageColorAllocateAlpha( $im_, $r, $g, $b , $a );
1421 imagesetpixel ($im_, $x, $y, $color);
1422 }
1423 }
1424 _image_gd_output($im_,$image);
1425 }
1426 return _image_ecrire_tag($image,array('src'=>$dest));
1427 }
1428
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');
1436
1437 if (!function_exists("imagecreatetruecolor")) return $im;
1438
1439 $couleurs = _couleur_hex_to_dec($rgb);
1440 $dr= $couleurs["red"];
1441 $dv= $couleurs["green"];
1442 $db= $couleurs["blue"];
1443
1444 $fonction = array('image_sepia', func_get_args());
1445 $image = _image_valeurs_trans($im, "sepia-$dr-$dv-$db",false,$fonction);
1446 if (!$image) return("");
1447
1448 $x_i = $image["largeur"];
1449 $y_i = $image["hauteur"];
1450
1451 $im = $image["fichier"];
1452 $dest = $image["fichier_dest"];
1453
1454 $creer = $image["creer"];
1455
1456 if ($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);
1467
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;
1474 $b = $rgb & 0xFF;
1475
1476 $r = round(.299 * $r + .587 * $g + .114 * $b);
1477 $g = $r;
1478 $b = $r;
1479
1480
1481 $r = _image_decale_composante_127($r, $dr);
1482 $g = _image_decale_composante_127($g, $dv);
1483 $b = _image_decale_composante_127($b, $db);
1484
1485 $color = ImageColorAllocateAlpha( $im_, $r, $g, $b , $a );
1486 imagesetpixel ($im_, $x, $y, $color);
1487 }
1488 }
1489 _image_gd_output($im_,$image);
1490 imagedestroy($im_);
1491 imagedestroy($im);
1492 }
1493
1494 return _image_ecrire_tag($image,array('src'=>$dest));
1495 }
1496
1497
1498 // Renforcer la nettete d'une image
1499 // http://doc.spip.org/@image_renforcement
1500 function image_renforcement($im, $k=0.5)
1501 {
1502 $fonction = array('image_flou', func_get_args());
1503 $image = _image_valeurs_trans($im, "renforcement-$k",false,$fonction);
1504 if (!$image) return("");
1505
1506 $x_i = $image["largeur"];
1507 $y_i = $image["hauteur"];
1508 $im = $image["fichier"];
1509 $dest = $image["fichier_dest"];
1510 $creer = $image["creer"];
1511
1512 if ($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);
1520
1521 for ($x = 0; $x < $x_i; $x++) {
1522 for ($y=0; $y < $y_i; $y++) {
1523
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);
1529
1530
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];
1535
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) ;
1542
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) ;
1548
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) ;
1554
1555 $r=min(255,max(0,$r));
1556 $g=min(255,max(0,$g));
1557 $b=min(255,max(0,$b));
1558
1559
1560 $color = ImageColorAllocateAlpha( $im_, $r, $g, $b , $a );
1561 imagesetpixel ($im_, $x, $y, $color);
1562 }
1563 }
1564 _image_gd_output($im_,$image);
1565 }
1566
1567 return _image_ecrire_tag($image,array('src'=>$dest));
1568 }
1569
1570
1571
1572
1573 /**
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
1580 *
1581 * @param string $im
1582 * @param string $background_color
1583 * @param int $tolerance
1584 * @param int $alpha
1585 * alpha = 0: aucune transparence
1586 * alpha = 127: completement transparent
1587 * @param int $coeff_lissage
1588 * @return mixed|null|string
1589 */
1590 function image_fond_transparent($im, $background_color, $tolerance=12, $alpha = 127, $coeff_lissage=7)
1591 {
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("");
1595
1596 $x_i = $image["largeur"];
1597 $y_i = $image["hauteur"];
1598
1599 $im = $image["fichier"];
1600 $dest = $image["fichier_dest"];
1601
1602 $creer = $image["creer"];
1603
1604 if ($creer) {
1605 $bg = _couleur_hex_to_dec($background_color);
1606 $bg_r = $bg['red'];
1607 $bg_g = $bg['green'];
1608 $bg_b = $bg['blue'];
1609
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);
1620
1621 $im_ = imagecreatetruecolor($x_i, $y_i);
1622 imagealphablending ($im_, FALSE );
1623 imagesavealpha ( $im_, TRUE );
1624 $color_f = ImageColorAllocateAlpha( $im_, 255, 255, 255 , $alpha );
1625
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;
1631 $b = $rgb & 0xFF;
1632 if ((($d=abs($r-$bg_r)+abs($g-$bg_g)+abs($b-$bg_b))<=$tolerance)){
1633 imagesetpixel ( $im_, $x, $y, $color_f );
1634 }
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 );
1639 }
1640 else
1641 imagesetpixel ( $im_, $x, $y, $rgb );
1642 }
1643 }
1644 _image_gd_output($im_,$image);
1645 imagedestroy($im_);
1646 imagedestroy($im);
1647 imagedestroy($im2);
1648 }
1649
1650 return _image_ecrire_tag($image,array('src'=>$dest));
1651 }
1652 ?>