[SPIP] ~v3.0.20-->v3.0.25
[lhc/web/clavette_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-2016 *
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://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)
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://code.spip.net/@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://code.spip.net/@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 /**
235 *
236 * http://code.spip.net/@image_recadre
237 *
238 * @param string $im
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
249 * @return string
250 * balise image recadree
251 */
252 function image_recadre($im,$width,$height,$position='center', $background_color='white')
253 {
254 $fonction = array('image_recadre', func_get_args());
255 $image = _image_valeurs_trans($im, "recadre-$width-$height-$position-$background_color",false,$fonction);
256
257 if (!$image) return("");
258
259 $x_i = $image["largeur"];
260 $y_i = $image["hauteur"];
261
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);
266 }
267
268 // on recadre pour respecter un ratio ?
269 // width : "16:9"
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)){
276 $width = $x_i;
277 $height = $hm;
278 }
279 else {
280 $width = $ym;
281 $height = $y_i;
282 }
283 }
284
285 if ($width==0) $width=$x_i;
286 if ($height==0) $height=$y_i;
287
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];
294 }
295 else{
296 $offset_width=0;
297 }
298 }
299 elseif (strpos($position,'right')!==FALSE)
300 $offset_width=$offset_width;
301 else
302 $offset_width=intval(ceil($offset_width/2));
303
304 if (strpos($position,'top')!==FALSE){
305 if (preg_match(';top=(\d{1}\d+);', $position, $top)){
306 $offset_height=$top[1];
307 }
308 else{
309 $offset_height=0;
310 }
311 }
312 elseif (strpos($position,'bottom')!==FALSE)
313 $offset_height=$offset_height;
314 else
315 $offset_height=intval(ceil($offset_height/2));
316
317 $im = $image["fichier"];
318 $dest = $image["fichier_dest"];
319
320 $creer = $image["creer"];
321
322 if ($creer) {
323 $im = $image["fonction_imagecreatefrom"]($im);
324 imagepalettetotruecolor($im);
325 $im_ = imagecreatetruecolor($width, $height);
326 @imagealphablending($im_, false);
327 @imagesavealpha($im_,true);
328
329 if ($background_color=='transparent')
330 $color_t = imagecolorallocatealpha( $im_, 255, 255, 255 , 127 );
331 else {
332 $bg = _couleur_hex_to_dec($background_color);
333 $color_t = imagecolorallocate( $im_, $bg['red'], $bg['green'], $bg['blue']);
334 }
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));
337
338 _image_gd_output($im_,$image);
339 imagedestroy($im_);
340 imagedestroy($im);
341 }
342
343 return _image_ecrire_tag($image,array('src'=>$dest,'width'=>$width,'height'=>$height));
344 }
345
346
347 /**
348 * Recadrer une image dans le rectangle le plus petit possible sans perte
349 * de pixels non transparent
350 *
351 * @param string $im
352 * @return string
353 */
354 function image_recadre_mini($im)
355 {
356 $fonction = array('image_recadre_mini', func_get_args());
357 $image = _image_valeurs_trans($im, "recadre_mini",false,$fonction);
358
359 if (!$image) return("");
360
361 $width = $image["largeur"];
362 $height = $image["hauteur"];
363
364 $im = $image["fichier"];
365 $dest = $image["fichier_dest"];
366
367 $creer = $image["creer"];
368 if ($creer) {
369 $im = $image["fonction_imagecreatefrom"]($im);
370 imagepalettetotruecolor($im);
371
372 // trouver le rectangle mini qui contient des infos de couleur
373 // recherche optimisee qui ne balaye que par zone
374 $min_x = $width;
375 $min_y = $height;
376 $max_y = $max_x = 0;
377 $yy = 0;
378 while ($yy<=$height/2 AND $max_y<=$min_y){
379 if($yy<$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);
386 break;
387 }
388 }
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);
396 break;
397 }
398 }
399 $yy++;
400 }
401 $min_y = min($max_y,$min_y); // tout a 0 aucun pixel trouve
402
403 $xx = 0;
404 while ($xx<=$width/2 AND $max_x<=$min_x){
405 if ($xx<$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
413 }
414 }
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
423 }
424 }
425 $xx++;
426 }
427 $min_x = min($max_x,$min_x); // tout a 0 aucun pixel trouve
428
429 $width = $max_x-$min_x+1;
430 $height = $max_y-$min_y+1;
431
432 $im_ = imagecreatetruecolor($width, $height);
433 @imagealphablending($im_, false);
434 @imagesavealpha($im_,true);
435
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);
439
440 _image_gd_output($im_,$image);
441 imagedestroy($im_);
442 imagedestroy($im);
443 }
444 else {
445 list ($height,$width) = taille_image($image['fichier_dest']);
446 }
447
448 return _image_ecrire_tag($image,array('src'=>$dest,'width'=>$width,'height'=>$height));
449 }
450
451
452 // http://code.spip.net/@image_flip_vertical
453 function image_flip_vertical($im)
454 {
455 $fonction = array('image_flip_vertical', func_get_args());
456 $image = _image_valeurs_trans($im, "flip_v", false,$fonction);
457 if (!$image) return("");
458
459 $x_i = $image["largeur"];
460 $y_i = $image["hauteur"];
461
462 $im = $image["fichier"];
463 $dest = $image["fichier_dest"];
464
465 $creer = $image["creer"];
466
467 if ($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);
473
474 $color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
475 imagefill ($im_, 0, 0, $color_t);
476
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);
480 }
481 }
482
483 _image_gd_output($im_,$image);
484 imagedestroy($im_);
485 imagedestroy($im);
486 }
487
488 return _image_ecrire_tag($image,array('src'=>$dest));
489 }
490
491 // http://code.spip.net/@image_flip_horizontal
492 function image_flip_horizontal($im)
493 {
494 $fonction = array('image_flip_horizontal', func_get_args());
495 $image = _image_valeurs_trans($im, "flip_h",false,$fonction);
496 if (!$image) return("");
497
498 $x_i = $image["largeur"];
499 $y_i = $image["hauteur"];
500
501 $im = $image["fichier"];
502 $dest = $image["fichier_dest"];
503
504 $creer = $image["creer"];
505
506 if ($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);
512
513 $color_t = ImageColorAllocateAlpha( $im_, 255, 255, 255 , 127 );
514 imagefill ($im_, 0, 0, $color_t);
515
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);
519 }
520 }
521 _image_gd_output($im_,$image);
522 imagedestroy($im_);
523 imagedestroy($im);
524 }
525
526 return _image_ecrire_tag($image,array('src'=>$dest));
527 }
528
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%.
536 //
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.
539 //
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
543 //
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)
547 //
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
562
563 $mode = "masque";
564
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;
574 }
575 }
576 if ($defini["mode"]) $mode = $variable["mode"];
577
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'];
584
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("");
589
590 $x_i = $image["largeur"];
591 $y_i = $image["hauteur"];
592
593 $im = $image["fichier"];
594 $dest = $image["fichier_dest"];
595
596 $creer = $image["creer"];
597
598 // doit-on positionner l'image ?
599 $placer = false;
600 foreach (array("right", "left", "bottom", "top", "text-align", "vertical-align") as $pl) {
601 if (isset($defini[$pl]) and $defini[$pl]) {
602 $placer = true;
603 break;
604 }
605 }
606
607 if ($creer) {
608
609 $im_m = $mask["fichier"];
610 $x_m = $mask["largeur"];
611 $y_m = $mask["hauteur"];
612
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);
623 imagedestroy($im2);
624 $im2 = $im2_;
625 }
626
627 if ($placer) {
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
632
633 $dx = 0;
634 $dy = 0;
635
636 if (isset($defini["right"]) and $defini["right"]) {
637 $right = $variable["right"];
638 $dx = ($x_i - $x_m) - $right;
639 }
640 if (isset($defini["bottom"]) and $defini["bottom"]) {
641 $bottom = $variable["bottom"];
642 $dy = ($y_i - $y_m) - $bottom;
643 }
644 if (isset($defini["top"]) and $defini["top"]) {
645 $top = $variable["top"];
646 $dy = $top;
647 }
648 if (isset($defini["left"]) and $defini["left"]) {
649 $left = $variable["left"];
650 $dx = $left;
651 }
652 if (isset($defini["text-align"]) and $defini["text-align"]) {
653 $align = $variable["text-align"];
654 if ($align == "right") {
655 $right = 0;
656 $dx = ($x_i - $x_m);
657 } else if ($align == "left") {
658 $left = 0;
659 $dx = 0;
660 } else if ($align = "center") {
661 $dx = round( ($x_i - $x_m) / 2 ) ;
662 }
663 }
664 if (isset($defini["vertical-align"]) and $defini["vertical-align"]) {
665 $valign = $variable["vertical-align"];
666 if ($valign == "bottom") {
667 $bottom = 0;
668 $dy = ($y_i - $y_m);
669 } else if ($valign == "top") {
670 $top = 0;
671 $dy = 0;
672 } else if ($valign = "middle") {
673 $dy = round( ($y_i - $y_m) / 2 ) ;
674 }
675 }
676
677
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);
684
685
686 imagecopy ( $im3, $im2, $dx, $dy, 0, 0, $x_m, $y_m);
687
688 imagedestroy($im2);
689 $im2 = imagecreatetruecolor($x_i, $y_i);
690 @imagealphablending($im2, false);
691 @imagesavealpha($im2,true);
692
693 imagecopy ( $im2, $im3, 0, 0, 0, 0, $x_i, $y_i);
694 imagedestroy($im3);
695 $x_m = $x_i;
696 $y_m = $y_i;
697 }
698
699
700 $rapport = $x_i / $x_m;
701 if (($y_i / $y_m) < $rapport ) {
702 $rapport = $y_i / $y_m;
703 }
704
705 $x_d = ceil($x_i / $rapport);
706 $y_d = ceil($y_i / $rapport);
707
708
709 if ($x_i < $x_m OR $y_i < $y_m) {
710 $x_dest = $x_i;
711 $y_dest = $y_i;
712 $x_dec = 0;
713 $y_dec = 0;
714 } else {
715 $x_dest = $x_m;
716 $y_dest = $y_m;
717 $x_dec = round(($x_d - $x_m) /2);
718 $y_dec = round(($y_d - $y_m) /2);
719 }
720
721
722 $nouveau = _image_valeurs_trans(image_reduire($im, $x_d, $y_d),"");
723 if (!is_array($nouveau)) return("");
724 $im_n = $nouveau["fichier"];
725
726
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);
738 imagedestroy($im);
739 $im = $im_;
740 }
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);
746
747
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;
755 $b = $rgb & 0xFF;
756
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;
761 $b2 = $rgb2 & 0xFF;
762
763 if ($mode == "normal") {
764 $v = (127 - $a) / 127;
765 if ($v == 1) {
766 $r_ = $r;
767 $g_ = $g;
768 $b_ = $b;
769 } else {
770 $v2 = (127 - $a2) / 127;
771 if ($v+$v2 == 0) {
772 $r_ = $r2;
773 $g_ = $g2;
774 $b_ = $b2;
775 } else if ($v2 == 0) {
776 $r_ = $r;
777 $g_ = $g;
778 $b_ = $b;
779 } else if ($v == 0) {
780 $r_ = $r2;
781 $g_ = $g2;
782 $b_ = $b2;
783 }else {
784 $r_ = $r + (($r2 - $r) * $v2 * (1 - $v));
785 $g_ = $g + (($g2 - $g) * $v2 * (1 - $v));
786 $b_ = $b + (($b2 - $b) * $v2 * (1 - $v));
787 }
788 }
789 $a_ = min($a,$a2);
790
791 } elseif (in_array($mode, array("produit","difference","superposer","lumiere_dure","ecran"))) {
792 if ($mode == "produit") {
793 $r = ($r/255) * $r2;
794 $g = ($g/255) * $g2;
795 $b = ($b/255) * $b2;
796 } elseif ($mode == "difference") {
797 $r = abs($r-$r2);
798 $g = abs($g-$g2);
799 $b = abs($b-$b2);
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);
812 }
813 $r = max(0, min($r, 255));
814 $g = max(0, min($g, 255));
815 $b = max(0, min($b, 255));
816
817 // melange en fonction de la transparence du masque
818 $v = (127 - $a) / 127;
819 if ($v == 1) { // melange complet
820 $r_ = $r;
821 $g_ = $g;
822 $b_ = $b;
823 } else {
824 $v2 = (127 - $a2) / 127;
825 if ($v+$v2 == 0) { // ??
826 $r_ = $r2;
827 $g_ = $g2;
828 $b_ = $b2;
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));
833 }
834 }
835 $a_ = $a2;
836
837 } elseif ($mode == "eclaircir" OR $mode == "obscurcir") {
838 $v = (127 - $a) / 127;
839 if ($v == 1) {
840 $r_ = $r;
841 $g_ = $g;
842 $b_ = $b;
843 } else {
844 $v2 = (127 - $a2) / 127;
845 if ($v+$v2 == 0) {
846 $r_ = $r2;
847 $g_ = $g2;
848 $b_ = $b2;
849 } else {
850 $r_ = $r + (($r2 - $r) * $v2 * (1 - $v));
851 $g_ = $g + (($g2 - $g) * $v2 * (1 - $v));
852 $b_ = $b + (($b2 - $b) * $v2 * (1 - $v));
853 }
854 }
855 if ($mode == "eclaircir") {
856 $r_ = max ($r_, $r2);
857 $g_ = max ($g_, $g2);
858 $b_ = max ($b_, $b2);
859 } else {
860 $r_ = min ($r_, $r2);
861 $g_ = min ($g_, $g2);
862 $b_ = min ($b_, $b2);
863 }
864 $a_ = min($a,$a2);
865
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
869 $h = $hsv["h"];
870 $s = $hsv["s"];
871 $v = $hsv["v"];
872 $hsv2 = _couleur_rgb2hsv($r2, $g2, $b2); // image en dessous
873 $h2 = $hsv2["h"];
874 $s2 = $hsv2["s"];
875 $v2 = $hsv2["v"];
876 switch ($mode) {
877 case "teinte";
878 $rgb3 = _couleur_hsv2rgb($h, $s2, $v2);
879 break;
880 case "saturation";
881 $rgb3 = _couleur_hsv2rgb($h2, $s, $v2);
882 break;
883 case "valeur";
884 $rgb3 = _couleur_hsv2rgb($h2, $s2, $v);
885 break;
886 }
887 $r = $rgb3["r"];
888 $g = $rgb3["g"];
889 $b = $rgb3["b"];
890
891 // melange en fonction de la transparence du masque
892 $v = (127 - $a) / 127;
893 if ($v == 1) { // melange complet
894 $r_ = $r;
895 $g_ = $g;
896 $b_ = $b;
897 } else {
898 $v2 = (127 - $a2) / 127;
899 if ($v+$v2 == 0) { // ??
900 $r_ = $r2;
901 $g_ = $g2;
902 $b_ = $b2;
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));
907 }
908 }
909 $a_ = $a2;
910
911 } else {
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);
919 }
920
921 $color = ImageColorAllocateAlpha( $im_, $r_, $g_, $b_ , $a_ );
922 imagesetpixel ($im_, $x, $y, $color);
923 }
924 }
925
926 _image_gd_output($im_,$image);
927 imagedestroy($im_);
928 imagedestroy($im);
929 imagedestroy($im2);
930
931 }
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));
935 }
936
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)
943 {
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("");
947
948 $x_i = $image["largeur"];
949 $y_i = $image["hauteur"];
950
951 $im = $image["fichier"];
952 $dest = $image["fichier_dest"];
953
954 $creer = $image["creer"];
955
956 // Methode precise
957 // resultat plus beau, mais tres lourd
958 // Et: indispensable pour preserver transparence!
959
960 if ($creer) {
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);
971
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;
978 $b = $rgb & 0xFF;
979
980 $c = round(($val_r * $r / 1000) + ($val_g * $g / 1000) + ($val_b * $b / 1000));
981 if ($c < 0) $c = 0;
982 if ($c > 254) $c = 254;
983
984
985 $color = ImageColorAllocateAlpha( $im_, $c, $c, $c , $a );
986 imagesetpixel ($im_, $x, $y, $color);
987 }
988 }
989 _image_gd_output($im_,$image);
990 imagedestroy($im_);
991 imagedestroy($im);
992 }
993
994 return _image_ecrire_tag($image,array('src'=>$dest));
995 }
996
997 // http://code.spip.net/@image_flou
998 function image_flou($im,$niveau=3)
999 {
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
1003 $coeffs = array (
1004 array ( 1),
1005 array ( 1, 1),
1006 array ( 1, 2, 1),
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)
1016 );
1017
1018 $fonction = array('image_flou', func_get_args());
1019 $image = _image_valeurs_trans($im, "flou-$niveau", false,$fonction);
1020 if (!$image) return("");
1021
1022 $x_i = $image["largeur"];
1023 $y_i = $image["hauteur"];
1024 $sum = pow (2, $niveau);
1025
1026 $im = $image["fichier"];
1027 $dest = $image["fichier_dest"];
1028
1029 $creer = $image["creer"];
1030
1031 // Methode precise
1032 // resultat plus beau, mais tres lourd
1033 // Et: indispensable pour preserver transparence!
1034
1035 if ($creer) {
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);
1042
1043 @imagealphablending($temp1, false);
1044 @imagesavealpha($temp1,true);
1045 @imagealphablending($temp2, false);
1046 @imagesavealpha($temp2,true);
1047
1048
1049 for ($i = 0; $i < $x_i+$niveau; $i++) {
1050 for ($j=0; $j < $y_i; $j++) {
1051 $suma=0;
1052 $sumr=0;
1053 $sumg=0;
1054 $sumb=0;
1055 $sum = 0;
1056 $sum_ = 0;
1057 for ( $k=0 ; $k <= $niveau ; ++$k ) {
1058 $color = imagecolorat($im, $i_ = ($i-$niveau)+$k , $j);
1059
1060 $a = ($color >> 24) & 0xFF;
1061 $r = ($color >> 16) & 0xFF;
1062 $g = ($color >> 8) & 0xFF;
1063 $b = ($color) & 0xFF;
1064
1065 if ($i_ < 0 OR $i_ >= $x_i) $a = 127;
1066
1067 $coef = $coeffs[$niveau][$k];
1068 $suma += $a*$coef;
1069 $ac = ((127-$a) / 127);
1070
1071 $ac = $ac*$ac;
1072
1073 $sumr += $r * $coef * $ac;
1074 $sumg += $g * $coef * $ac;
1075 $sumb += $b * $coef * $ac;
1076 $sum += $coef * $ac;
1077 $sum_ += $coef;
1078 }
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);
1082 }
1083 }
1084 imagedestroy($im);
1085 for ($i = 0; $i < $x_i+$niveau; $i++) {
1086 for ($j=0; $j < $y_i+$niveau; $j++) {
1087 $suma=0;
1088 $sumr=0;
1089 $sumg=0;
1090 $sumb=0;
1091 $sum = 0;
1092 $sum_ = 0;
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;
1100
1101 $suma += $a*$coeffs[$niveau][$k];
1102 $ac = ((127-$a) / 127);
1103
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];
1109
1110 }
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);
1114 }
1115 }
1116
1117 _image_gd_output($temp2,$image);
1118 imagedestroy($temp1);
1119 imagedestroy($temp2);
1120 }
1121
1122 return _image_ecrire_tag($image,array('src'=>$dest,'width'=>($x_i+$niveau),'height'=>($y_i+$niveau)));
1123 }
1124
1125 // http://code.spip.net/@image_RotateBicubic
1126 function image_RotateBicubic($src_img, $angle, $bicubic=0) {
1127 include_spip('filtres/images_lib');
1128
1129 if (round($angle/90)*90 == $angle) {
1130 $droit = true;
1131 if (round($angle/180)*180 == $angle) $rot = 180;
1132 else $rot = 90;
1133 }
1134 else
1135 $droit = false;
1136
1137 // convert degrees to radians
1138 $angle = $angle + 180;
1139 $angle = deg2rad($angle);
1140
1141
1142
1143 $src_x = imagesx($src_img);
1144 $src_y = imagesy($src_img);
1145
1146
1147 $center_x = floor(($src_x-1)/2);
1148 $center_y = floor(($src_y-1)/2);
1149
1150 $cosangle = cos($angle);
1151 $sinangle = sin($angle);
1152
1153 // calculer dimensions en simplifiant angles droits, ce qui evite "floutage"
1154 // des rotations a angle droit
1155 if (!$droit) {
1156 $corners=array(array(0,0), array($src_x,0), array($src_x,$src_y), array(0,$src_y));
1157
1158 foreach($corners as $key=>$value) {
1159 $value[0]-=$center_x; //Translate coords to center for rotation
1160 $value[1]-=$center_y;
1161 $temp=array();
1162 $temp[0]=$value[0]*$cosangle+$value[1]*$sinangle;
1163 $temp[1]=$value[1]*$cosangle-$value[0]*$sinangle;
1164 $corners[$key]=$temp;
1165 }
1166
1167 $min_x=1000000000000000;
1168 $max_x=-1000000000000000;
1169 $min_y=1000000000000000;
1170 $max_y=-1000000000000000;
1171
1172 foreach($corners as $key => $value) {
1173 if($value[0]<$min_x)
1174 $min_x=$value[0];
1175 if($value[0]>$max_x)
1176 $max_x=$value[0];
1177
1178 if($value[1]<$min_y)
1179 $min_y=$value[1];
1180 if($value[1]>$max_y)
1181 $max_y=$value[1];
1182 }
1183
1184 $rotate_width=ceil($max_x-$min_x);
1185 $rotate_height=ceil($max_y-$min_y);
1186 }
1187 else {
1188 if ($rot == 180) {
1189 $rotate_height = $src_y;
1190 $rotate_width = $src_x;
1191 } else {
1192 $rotate_height = $src_x;
1193 $rotate_width = $src_y;
1194 }
1195 $bicubic = false;
1196 }
1197
1198
1199 $rotate=imagecreatetruecolor($rotate_width,$rotate_height);
1200 imagealphablending($rotate, false);
1201 imagesavealpha($rotate, true);
1202
1203 $cosangle = cos($angle);
1204 $sinangle = sin($angle);
1205
1206 // arrondir pour rotations angle droit (car cos et sin dans {-1,0,1})
1207 if ($droit) {
1208 $cosangle = round($cosangle);
1209 $sinangle = round($sinangle);
1210 }
1211
1212 $newcenter_x = ($rotate_width-1)/2;
1213 $newcenter_y = ($rotate_height-1)/2;
1214
1215
1216 for ($y = 0; $y < $rotate_height; $y++) {
1217 for ($x = 0; $x < $rotate_width; $x++) {
1218 // rotate...
1219 $old_x = ((($newcenter_x-$x) * $cosangle + ($newcenter_y-$y) * $sinangle))
1220 + $center_x;
1221 $old_y = ((($newcenter_y-$y) * $cosangle - ($newcenter_x-$x) * $sinangle))
1222 + $center_y;
1223
1224 $old_x = ceil($old_x);
1225 $old_y = ceil($old_y);
1226
1227 if ( $old_x >= 0 && $old_x < $src_x
1228 && $old_y >= 0 && $old_y < $src_y ) {
1229 if ($bicubic == true) {
1230 $xo = $old_x;
1231 $x0 = floor($xo);
1232 $x1 = ceil($xo);
1233 $yo = $old_y;
1234 $y0 = floor($yo);
1235 $y1 = ceil($yo);
1236
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;
1242 $b1 = $rgb & 0xFF;
1243 $d1 = _image_distance_pixel($xo, $yo, $x0, $y0);
1244
1245 $rgb = ImageColorAt($src_img, $x1, $y0);
1246 $a2 = ($rgb >> 24) & 0xFF;
1247 $r2 = ($rgb >> 16) & 0xFF;
1248 $g2 = ($rgb >> 8) & 0xFF;
1249 $b2 = $rgb & 0xFF;
1250 $d2 = _image_distance_pixel($xo, $yo, $x1, $y0);
1251
1252 $rgb = ImageColorAt($src_img,$x0, $y1);
1253 $a3 = ($rgb >> 24) & 0xFF;
1254 $r3 = ($rgb >> 16) & 0xFF;
1255 $g3 = ($rgb >> 8) & 0xFF;
1256 $b3 = $rgb & 0xFF;
1257 $d3 = _image_distance_pixel($xo, $yo, $x0, $y1);
1258
1259 $rgb = ImageColorAt($src_img,$x1, $y1);
1260 $a4 = ($rgb >> 24) & 0xFF;
1261 $r4 = ($rgb >> 16) & 0xFF;
1262 $g4 = ($rgb >> 8) & 0xFF;
1263 $b4 = $rgb & 0xFF;
1264 $d4 = _image_distance_pixel($xo, $yo, $x1, $y1);
1265
1266 $ac1 = ((127-$a1) / 127);
1267 $ac2 = ((127-$a2) / 127);
1268 $ac3 = ((127-$a3) / 127);
1269 $ac4 = ((127-$a4) / 127);
1270
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;
1278 }
1279
1280 $tot = $d1 + $d2 + $d3 + $d4;
1281
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);
1287 }
1288 else {
1289 $color = imagecolorat($src_img, round($old_x), round($old_y));
1290 }
1291 }
1292 else {
1293 // this line sets the background colour
1294 $color = imagecolorallocatealpha($src_img, 255, 255, 255, 127);
1295 }
1296 @imagesetpixel($rotate, $x, $y, $color);
1297 }
1298 }
1299 return $rotate;
1300 }
1301
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)
1306 {
1307 $fonction = array('image_rotation', func_get_args());
1308 $image = _image_valeurs_trans($im, "rot-$angle-$crop", "png", $fonction);
1309 if (!$image) return("");
1310
1311 $im = $image["fichier"];
1312 $dest = $image["fichier_dest"];
1313
1314 $creer = $image["creer"];
1315
1316 if ($creer) {
1317 $effectuer_gd = true;
1318
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;
1325 }
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');
1330 } else
1331 @define ('_ROTATE_COMMAND', '');
1332 if (_ROTATE_COMMAND!=='') {
1333 $commande = str_replace(
1334 array('%t', '%src', '%dest'),
1335 array(
1336 $angle,
1337 escapeshellcmd($im),
1338 escapeshellcmd($dest)
1339 ),
1340 _ROTATE_COMMAND);
1341 spip_log($commande);
1342 exec($commande);
1343 if (file_exists($dest)) // precaution
1344 $effectuer_gd = false;
1345 }
1346 }
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;
1356 }
1357 }
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);
1365 imagedestroy($im);
1366 }
1367 }
1368 list ($src_y,$src_x) = taille_image($dest);
1369 return _image_ecrire_tag($image,array('src'=>$dest,'width'=>$src_x,'height'=>$src_y));
1370 }
1371
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();
1378 $img = $tous[0];
1379 $fonc = $tous[1];
1380 $tous[0]="";
1381 $tous_var = join($tous, "-");
1382
1383 $fonction = array('image_imagick', func_get_args());
1384 $image = _image_valeurs_trans($img, "$tous_var", "png",$fonction);
1385 if (!$image) return("");
1386
1387 $im = $image["fichier"];
1388 $dest = $image["fichier_dest"];
1389
1390 $creer = $image["creer"];
1391
1392 if ($creer) {
1393 if (function_exists($fonc)) {
1394
1395 $handle = imagick_readimage ($im);
1396 $arr[0] = $handle;
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));
1405 }
1406 }
1407 list ($src_y,$src_x) = taille_image($dest);
1408 return _image_ecrire_tag($image,array('src'=>$dest,'width'=>$src_x,'height'=>$src_y));
1409
1410 }
1411
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("");
1421
1422 $x_i = $image["largeur"];
1423 $y_i = $image["hauteur"];
1424
1425 $im = $image["fichier"];
1426 $dest = $image["fichier_dest"];
1427
1428 $creer = $image["creer"];
1429
1430 if ($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);
1441
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;
1448 $b = $rgb & 0xFF;
1449
1450 $r = _image_decale_composante($r, $gamma);
1451 $g = _image_decale_composante($g, $gamma);
1452 $b = _image_decale_composante($b, $gamma);
1453
1454 $color = ImageColorAllocateAlpha( $im_, $r, $g, $b , $a );
1455 imagesetpixel ($im_, $x, $y, $color);
1456 }
1457 }
1458 _image_gd_output($im_,$image);
1459 }
1460 return _image_ecrire_tag($image,array('src'=>$dest));
1461 }
1462
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');
1470
1471 if (!function_exists("imagecreatetruecolor")) return $im;
1472
1473 $couleurs = _couleur_hex_to_dec($rgb);
1474 $dr= $couleurs["red"];
1475 $dv= $couleurs["green"];
1476 $db= $couleurs["blue"];
1477
1478 $fonction = array('image_sepia', func_get_args());
1479 $image = _image_valeurs_trans($im, "sepia-$dr-$dv-$db",false,$fonction);
1480 if (!$image) return("");
1481
1482 $x_i = $image["largeur"];
1483 $y_i = $image["hauteur"];
1484
1485 $im = $image["fichier"];
1486 $dest = $image["fichier_dest"];
1487
1488 $creer = $image["creer"];
1489
1490 if ($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);
1501
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;
1508 $b = $rgb & 0xFF;
1509
1510 $r = round(.299 * $r + .587 * $g + .114 * $b);
1511 $g = $r;
1512 $b = $r;
1513
1514
1515 $r = _image_decale_composante_127($r, $dr);
1516 $g = _image_decale_composante_127($g, $dv);
1517 $b = _image_decale_composante_127($b, $db);
1518
1519 $color = ImageColorAllocateAlpha( $im_, $r, $g, $b , $a );
1520 imagesetpixel ($im_, $x, $y, $color);
1521 }
1522 }
1523 _image_gd_output($im_,$image);
1524 imagedestroy($im_);
1525 imagedestroy($im);
1526 }
1527
1528 return _image_ecrire_tag($image,array('src'=>$dest));
1529 }
1530
1531
1532 // Renforcer la nettete d'une image
1533 // http://code.spip.net/@image_renforcement
1534 function image_renforcement($im, $k=0.5)
1535 {
1536 $fonction = array('image_flou', func_get_args());
1537 $image = _image_valeurs_trans($im, "renforcement-$k",false,$fonction);
1538 if (!$image) return("");
1539
1540 $x_i = $image["largeur"];
1541 $y_i = $image["hauteur"];
1542 $im = $image["fichier"];
1543 $dest = $image["fichier_dest"];
1544 $creer = $image["creer"];
1545
1546 if ($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);
1554
1555 for ($x = 0; $x < $x_i; $x++) {
1556 for ($y=0; $y < $y_i; $y++) {
1557
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);
1563
1564
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];
1569
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) ;
1576
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) ;
1582
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) ;
1588
1589 $r=min(255,max(0,$r));
1590 $g=min(255,max(0,$g));
1591 $b=min(255,max(0,$b));
1592
1593
1594 $color = ImageColorAllocateAlpha( $im_, $r, $g, $b , $a );
1595 imagesetpixel ($im_, $x, $y, $color);
1596 }
1597 }
1598 _image_gd_output($im_,$image);
1599 }
1600
1601 return _image_ecrire_tag($image,array('src'=>$dest));
1602 }
1603
1604
1605
1606
1607 /**
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
1614 *
1615 * @param string $im
1616 * @param string $background_color
1617 * @param int $tolerance
1618 * @param int $alpha
1619 * alpha = 0: aucune transparence
1620 * alpha = 127: completement transparent
1621 * @param int $coeff_lissage
1622 * @return mixed|null|string
1623 */
1624 function image_fond_transparent($im, $background_color, $tolerance=12, $alpha = 127, $coeff_lissage=7)
1625 {
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("");
1629
1630 $x_i = $image["largeur"];
1631 $y_i = $image["hauteur"];
1632
1633 $im = $image["fichier"];
1634 $dest = $image["fichier_dest"];
1635
1636 $creer = $image["creer"];
1637
1638 if ($creer) {
1639 $bg = _couleur_hex_to_dec($background_color);
1640 $bg_r = $bg['red'];
1641 $bg_g = $bg['green'];
1642 $bg_b = $bg['blue'];
1643
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);
1654
1655 $im_ = imagecreatetruecolor($x_i, $y_i);
1656 imagealphablending ($im_, FALSE );
1657 imagesavealpha ( $im_, TRUE );
1658 $color_f = ImageColorAllocateAlpha( $im_, 255, 255, 255 , $alpha );
1659
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;
1665 $b = $rgb & 0xFF;
1666 if ((($d=abs($r-$bg_r)+abs($g-$bg_g)+abs($b-$bg_b))<=$tolerance)){
1667 imagesetpixel ( $im_, $x, $y, $color_f );
1668 }
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 );
1673 }
1674 else
1675 imagesetpixel ( $im_, $x, $y, $rgb );
1676 }
1677 }
1678 _image_gd_output($im_,$image);
1679 imagedestroy($im_);
1680 imagedestroy($im);
1681 imagedestroy($im2);
1682 }
1683
1684 return _image_ecrire_tag($image,array('src'=>$dest));
1685 }
1686 ?>