source: spip-zone/_core_/branches/spip-3.0/plugins/filtres_images/filtres/images_transforme.php @ 104360

Last change on this file since 104360 was 104360, checked in by spip.franck@…, 3 years ago

code.spip est maintenant en https, donc j'ajoute le "s" à http

File size: 49.6 KB
Line 
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
19if (!defined('_ECRIRE_INC_VERSION')) return;
20
21// librairie de base du core
22include_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// https://code.spip.net/@image_aplatir
32// 3/ $transparence a "true" permet de conserver la transparence (utile pour conversion GIF)
33// https://code.spip.net/@image_aplatir
34function 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// https://code.spip.net/@image_format
163function 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// https://code.spip.net/@image_alpha
174function 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 * https://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 */
252function 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 */
354function 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// https://code.spip.net/@image_flip_vertical
453function 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// https://code.spip.net/@image_flip_horizontal
492function 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// https://code.spip.net/@image_masque
530function 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// https://code.spip.net/@image_nb
942function 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// https://code.spip.net/@image_flou
998function 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// https://code.spip.net/@image_RotateBicubic
1126function 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// https://code.spip.net/@image_rotation
1305function 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// https://code.spip.net/@image_imagick
1376function 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// https://code.spip.net/@image_gamma
1416function 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// https://code.spip.net/@image_sepia
1468function 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// https://code.spip.net/@image_renforcement
1534function 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 */
1624function 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?>
Note: See TracBrowser for help on using the repository browser.