3990d97767548a53c29fce1ba69ffc1a458b60ba
2 /***************************************************************************\
3 * SPIP, Systeme de publication pour l'internet *
5 * Copyright (c) 2001-2016 *
6 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
8 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
9 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
10 \***************************************************************************/
13 * Toutes les fonctions image_xx de ce fichier :
14 * - prennent une image en entree
15 * - fournissent une image en sortie
16 * - sont chainables les unes derrieres les autres dans toutes les combinaisons possibles
18 * @package SPIP\FiltresImages\ImagesTransforme
21 if (!defined('_ECRIRE_INC_VERSION')) {
25 // librairie de base du core
26 include_spip('inc/filtres_images_mini');
28 // 1/ Aplatir une image semi-transparente (supprimer couche alpha)
29 // en remplissant la transparence avec couleur choisir $coul.
30 // 2/ Forcer le format de sauvegarde (jpg, png, gif)
31 // pour le format jpg, $qualite correspond au niveau de compression (defaut 85)
32 // pour le format gif, $qualite correspond au nombre de couleurs dans la palette (defaut 128)
33 // pour le format png, $qualite correspond au nombre de couleur dans la palette ou si 0 a une image truecolor (defaut truecolor)
34 // attention, seul 128 est supporte en l'etat (production d'images avec palette reduite pas satisfaisante)
35 // https://code.spip.net/@image_aplatir
36 // 3/ $transparence a "true" permet de conserver la transparence (utile pour conversion GIF)
37 // https://code.spip.net/@image_aplatir
38 function image_aplatir($im, $format = 'jpg', $coul = '000000', $qualite = null, $transparence = false) {
39 if ($qualite === null) {
40 if ($format == 'jpg') {
41 $qualite = _IMG_GD_QUALITE
;
42 } elseif ($format == 'png') {
48 $fonction = array('image_aplatir', func_get_args());
49 $image = _image_valeurs_trans($im, "aplatir-$format-$coul-$qualite-$transparence", $format, $fonction);
55 include_spip('inc/filtres');
56 $couleurs = _couleur_hex_to_dec($coul);
57 $dr = $couleurs["red"];
58 $dv = $couleurs["green"];
59 $db = $couleurs["blue"];
61 $x_i = $image["largeur"];
62 $y_i = $image["hauteur"];
64 $im = $image["fichier"];
65 $dest = $image["fichier_dest"];
67 $creer = $image["creer"];
70 $im = @$image["fonction_imagecreatefrom"]($im);
71 imagepalettetotruecolor($im);
72 $im_ = imagecreatetruecolor($x_i, $y_i);
73 if ($image["format_source"] == "gif" and function_exists('ImageCopyResampled')) {
74 // Si un GIF est transparent,
75 // fabriquer un PNG transparent
76 // Conserver la transparence
77 @imagealphablending
($im_, false);
78 @imagesavealpha
($im_, true);
79 if (function_exists("imageAntiAlias")) {
80 imageAntiAlias($im_, true);
82 @ImageCopyResampled
($im_, $im, 0, 0, 0, 0, $x_i, $y_i, $x_i, $y_i);
87 // allouer la couleur de fond
89 @imagealphablending
($im_, false);
90 @imagesavealpha
($im_, true);
91 $color_t = imagecolorallocatealpha($im_, $dr, $dv, $db, 127);
93 $color_t = ImageColorAllocate($im_, $dr, $dv, $db);
96 imagefill($im_, 0, 0, $color_t);
99 //$dist = abs($trait);
103 if ($image["format_source"] == "jpg") {
106 for ($x = 0; $x < $x_i; $x++
) {
107 for ($y = 0; $y < $y_i; $y++
) {
109 $rgb = ImageColorAt($im, $x, $y);
110 $a = ($rgb >> 24) & 0xFF;
111 $r = ($rgb >> 16) & 0xFF;
112 $g = ($rgb >> 8) & 0xFF;
115 $a = (127 - $a) / 127;
117 if ($a == 1) { // Limiter calculs
122 if ($a == 0) { // Limiter calculs
127 $transp_x = $x; // Memoriser un point transparent
131 $r = round($a * $r +
$dr * (1 - $a));
132 $g = round($a * $g +
$dv * (1 - $a));
133 $b = round($a * $b +
$db * (1 - $a));
137 $color = ImageColorAllocateAlpha($im_, $r, $g, $b, $a);
138 imagesetpixel($im_, $x, $y, $color);
142 // passer en palette si besoin
143 if ($format == 'gif' or ($format == 'png' and $qualite !== 0)) {
144 // creer l'image finale a palette
145 // (on recycle l'image initiale si possible, sinon on en recree une)
147 $im = imagecreatetruecolor($x_i, $y_i);
150 @imagetruecolortopalette
($im, true, $qualite);
153 //$im = imagecreate($x_i, $y_i);
154 // copier l'image true color vers la palette
155 imagecopy($im, $im_, 0, 0, 0, 0, $x_i, $y_i);
156 // matcher les couleurs au mieux par rapport a l'image initiale
157 // si la fonction est disponible (php>=4.3)
158 if (function_exists('imagecolormatch')) {
159 @imagecolormatch
($im_, $im);
162 if ($format == 'gif' && $transparence && $transp_x) {
163 $color_t = ImagecolorAt($im, $transp_x, $transp_y);
164 if ($format == "gif" && $transparence) {
165 @imagecolortransparent
($im, $color_t);
170 // produire le resultat
171 _image_gd_output($im, $image, $qualite);
173 _image_gd_output($im_, $image, $qualite);
181 return _image_ecrire_tag($image, array('src' => $dest));
185 // Enregistrer une image dans un format donne
186 // (conserve la transparence gif, png, ico)
187 // utilise [->@image_aplatir]
188 // https://code.spip.net/@image_format
189 function image_format($img, $format = 'png') {
191 if ($format == 'png8') {
196 return image_aplatir($img, $format, 'cccccc', $qualite, true);
200 // Transforme l'image en PNG transparent
201 // alpha = 0: aucune transparence
202 // alpha = 127: completement transparent
203 // https://code.spip.net/@image_alpha
204 function image_alpha($im, $alpha = 63) {
205 $fonction = array('image_alpha', func_get_args());
206 $image = _image_valeurs_trans($im, "alpha-$alpha", "png", $fonction);
211 $x_i = $image["largeur"];
212 $y_i = $image["hauteur"];
214 $im = $image["fichier"];
215 $dest = $image["fichier_dest"];
217 $creer = $image["creer"];
220 // Creation de l'image en deux temps
221 // de facon a conserver les GIF transparents
222 $im = $image["fonction_imagecreatefrom"]($im);
223 imagepalettetotruecolor($im);
224 $im2 = imagecreatetruecolor($x_i, $y_i);
225 @imagealphablending
($im2, false);
226 @imagesavealpha
($im2, true);
227 $color_t = ImageColorAllocateAlpha($im2, 255, 255, 255, 127);
228 imagefill($im2, 0, 0, $color_t);
229 imagecopy($im2, $im, 0, 0, 0, 0, $x_i, $y_i);
231 $im_ = imagecreatetruecolor($x_i, $y_i);
232 imagealphablending($im_, false);
233 imagesavealpha($im_, true);
236 for ($x = 0; $x < $x_i; $x++
) {
237 for ($y = 0; $y < $y_i; $y++
) {
238 $rgb = ImageColorAt($im2, $x, $y);
240 if (function_exists('imagecolorallocatealpha')) {
241 $a = ($rgb >> 24) & 0xFF;
242 $r = ($rgb >> 16) & 0xFF;
243 $g = ($rgb >> 8) & 0xFF;
247 $a_ = $alpha +
$a - round($a * $alpha / 127);
248 $rgb = imagecolorallocatealpha($im_, $r, $g, $b, $a_);
250 imagesetpixel($im_, $x, $y, $rgb);
253 _image_gd_output($im_, $image);
259 return _image_ecrire_tag($image, array('src' => $dest));
263 * Recadre (rogne) une image en indiquant la taille de la découpe souhaitée
265 * On peut indiquer une proportion ou une taille spécifique, une position de rognage
266 * et une couleur de fond, si le rognage est de taille plus grande que l'image d'origine.
269 * - `[(#FICHIER|image_recadre{800, 400})]`
270 * - `[(#FICHIER|image_recadre{800, 400, center})]`
271 * - `[(#FICHIER|image_recadre{800, 400, center, black})]`
272 * - `[(#FICHIER|image_recadre{16:9})]`
273 * - `[(#FICHIER|image_recadre{16:9, -})]` (- est appliqué par défaut, équivalent à image_passe_partout)
274 * - `[(#FICHIER|image_recadre{16:9, +, center, white})]`
275 * - `[(#FICHIER|image_recadre{16:9, -, top left})]`
276 * - `[(#FICHIER|image_recadre{16:9, -, top=40 left=20})]`
279 * @uses _image_valeurs_trans()
280 * @uses _image_tag_changer_taille() si image trop grande pour être traitée
281 * @uses _image_ecrire_tag()
282 * @link https://www.spip.net/5786
285 * Chemin de l'image ou balise html `<img src=... />`
286 * @param string|int $width
287 * Largeur du recadrage
288 * ou ratio sous la forme "16:9"
289 * @param string|int $height
290 * Hauteur du recadrage
291 * ou "+" (agrandir) ou "-" (reduire) si un ratio est fourni pour width
292 * @param string $position
293 * Indication de position de la découpe :
294 * - `center`, `left`, `right`, `top`, `bottom`,
295 * - ou combinaisons de plusiers `top left`
296 * - ou indication en pixels depuis une position `top=50` ou composée `top=40 left=50`
297 * - ou nom d'une fonction spéciale qui calculera et retournera la position souhaitée
298 * @param string $background_color
299 * Couleur de fond si on agrandit l'image
301 * balise image recadrée
303 function image_recadre($im, $width, $height, $position = 'center', $background_color = 'white') {
304 $fonction = array('image_recadre', func_get_args());
305 $image = _image_valeurs_trans($im, "recadre-$width-$height-$position-$background_color", false, $fonction);
311 $x_i = $image["largeur"];
312 $y_i = $image["hauteur"];
314 if (_IMG_GD_MAX_PIXELS
&& $x_i * $y_i > _IMG_GD_MAX_PIXELS
) {
315 spip_log("image_recadre impossible sur $im : " . $x_i * $y_i . "pixels");
317 // on se rabat sur une reduction CSS
318 return _image_tag_changer_taille($im, $width, $height);
321 // on recadre pour respecter un ratio ?
323 // height : "+" pour agrandir l'image et "-" pour la croper
324 if (strpos($width, ":") !== false) {
325 list($wr, $hr) = explode(":", $width);
326 $hm = $x_i / $wr * $hr;
327 $ym = $y_i / $hr * $wr;
328 if ($height == "+" ?
($y_i < $hm) : ($y_i > $hm)) {
344 $offset_width = $x_i - $width;
345 $offset_height = $y_i - $height;
346 $position = strtolower($position);
348 // chercher une fonction spéciale de calcul des coordonnées de positionnement.
349 // exemple 'focus' ou 'focus-center' avec le plugin 'Centre Image'
350 if (!in_array($position, array('center', 'top', 'right', 'bottom', 'left'))) {
351 if (count(explode(" ", $position)) == 1) {
352 $positionner = charger_fonction("image_positionner_par_" . str_replace("-", "_", $position), "inc", true);
354 $position = $positionner($im, $width, $height);
359 if (strpos($position, 'left') !== false) {
360 if (preg_match(';left=(\d{1}\d+);', $position, $left)) {
361 $offset_width = $left[1];
365 } elseif (strpos($position, 'right') !== false) {
366 $offset_width = $offset_width;
368 $offset_width = intval(ceil($offset_width / 2));
371 if (strpos($position, 'top') !== false) {
372 if (preg_match(';top=(\d{1}\d+);', $position, $top)) {
373 $offset_height = $top[1];
377 } elseif (strpos($position, 'bottom') !== false) {
378 $offset_height = $offset_height;
380 $offset_height = intval(ceil($offset_height / 2));
383 $im = $image["fichier"];
384 $dest = $image["fichier_dest"];
386 $creer = $image["creer"];
389 $im = $image["fonction_imagecreatefrom"]($im);
390 imagepalettetotruecolor($im);
391 $im_ = imagecreatetruecolor($width, $height);
392 @imagealphablending
($im_, false);
393 @imagesavealpha
($im_, true);
395 if ($background_color == 'transparent') {
396 $color_t = imagecolorallocatealpha($im_, 255, 255, 255, 127);
398 $bg = _couleur_hex_to_dec($background_color);
399 $color_t = imagecolorallocate($im_, $bg['red'], $bg['green'], $bg['blue']);
401 imagefill($im_, 0, 0, $color_t);
402 imagecopy($im_, $im, max(0, -$offset_width), max(0, -$offset_height), max(0, $offset_width), max(0, $offset_height),
403 min($width, $x_i), min($height, $y_i));
405 _image_gd_output($im_, $image);
410 return _image_ecrire_tag($image, array('src' => $dest, 'width' => $width, 'height' => $height));
415 * Recadrer une image dans le rectangle le plus petit possible sans perte
416 * de pixels non transparent
421 function image_recadre_mini($im) {
422 $fonction = array('image_recadre_mini', func_get_args());
423 $image = _image_valeurs_trans($im, "recadre_mini", false, $fonction);
429 $width = $image["largeur"];
430 $height = $image["hauteur"];
432 $im = $image["fichier"];
433 $dest = $image["fichier_dest"];
435 $creer = $image["creer"];
437 $im = $image["fonction_imagecreatefrom"]($im);
438 imagepalettetotruecolor($im);
440 // trouver le rectangle mini qui contient des infos de couleur
441 // recherche optimisee qui ne balaye que par zone
446 while ($yy <= $height / 2 and $max_y <= $min_y) {
448 for ($xx = 0; $xx < $width; $xx++
) {
449 $color_index = imagecolorat($im, $xx, $yy);
450 $color_tran = imagecolorsforindex($im, $color_index);
451 if ($color_tran['alpha'] !== 127) {
452 $min_y = min($yy, $min_y);
453 $max_y = max($height - 1 - $yy, $max_y);
458 if ($height - 1 - $yy > $max_y) {
459 for ($xx = 0; $xx < $width; $xx++
) {
460 $color_index = imagecolorat($im, $xx, $height - 1 - $yy);
461 $color_tran = imagecolorsforindex($im, $color_index);
462 if ($color_tran['alpha'] !== 127) {
463 $min_y = min($yy, $min_y);
464 $max_y = max($height - 1 - $yy, $max_y);
471 $min_y = min($max_y, $min_y); // tout a 0 aucun pixel trouve
474 while ($xx <= $width / 2 and $max_x <= $min_x) {
476 for ($yy = $min_y; $yy < $max_y; $yy++
) {
477 $color_index = imagecolorat($im, $xx, $yy);
478 $color_tran = imagecolorsforindex($im, $color_index);
479 if ($color_tran['alpha'] !== 127) {
480 $min_x = min($xx, $min_x);
481 $max_x = max($xx, $max_x);
482 break; // inutile de continuer sur cette colonne
486 if ($width - 1 - $xx > $max_x) {
487 for ($yy = $min_y; $yy < $max_y; $yy++
) {
488 $color_index = imagecolorat($im, $width - 1 - $xx, $yy);
489 $color_tran = imagecolorsforindex($im, $color_index);
490 if ($color_tran['alpha'] !== 127) {
491 $min_x = min($width - 1 - $xx, $min_x);
492 $max_x = max($width - 1 - $xx, $max_x);
493 break; // inutile de continuer sur cette colonne
499 $min_x = min($max_x, $min_x); // tout a 0 aucun pixel trouve
501 $width = $max_x - $min_x +
1;
502 $height = $max_y - $min_y +
1;
504 $im_ = imagecreatetruecolor($width, $height);
505 @imagealphablending
($im_, false);
506 @imagesavealpha
($im_, true);
508 $color_t = imagecolorallocatealpha($im_, 255, 255, 255, 127);
509 imagefill($im_, 0, 0, $color_t);
510 imagecopy($im_, $im, 0, 0, $min_x, $min_y, $width, $height);
512 _image_gd_output($im_, $image);
516 list($height, $width) = taille_image($image['fichier_dest']);
519 return _image_ecrire_tag($image, array('src' => $dest, 'width' => $width, 'height' => $height));
523 // https://code.spip.net/@image_flip_vertical
524 function image_flip_vertical($im) {
525 $fonction = array('image_flip_vertical', func_get_args());
526 $image = _image_valeurs_trans($im, "flip_v", false, $fonction);
531 $x_i = $image["largeur"];
532 $y_i = $image["hauteur"];
534 $im = $image["fichier"];
535 $dest = $image["fichier_dest"];
537 $creer = $image["creer"];
540 $im = $image["fonction_imagecreatefrom"]($im);
541 imagepalettetotruecolor($im);
542 $im_ = imagecreatetruecolor($x_i, $y_i);
543 @imagealphablending
($im_, false);
544 @imagesavealpha
($im_, true);
546 $color_t = ImageColorAllocateAlpha($im_, 255, 255, 255, 127);
547 imagefill($im_, 0, 0, $color_t);
549 for ($x = 0; $x < $x_i; $x++
) {
550 for ($y = 0; $y < $y_i; $y++
) {
551 imagecopy($im_, $im, $x_i - $x - 1, $y, $x, $y, 1, 1);
555 _image_gd_output($im_, $image);
560 return _image_ecrire_tag($image, array('src' => $dest));
563 // https://code.spip.net/@image_flip_horizontal
564 function image_flip_horizontal($im) {
565 $fonction = array('image_flip_horizontal', func_get_args());
566 $image = _image_valeurs_trans($im, "flip_h", false, $fonction);
571 $x_i = $image["largeur"];
572 $y_i = $image["hauteur"];
574 $im = $image["fichier"];
575 $dest = $image["fichier_dest"];
577 $creer = $image["creer"];
580 $im = $image["fonction_imagecreatefrom"]($im);
581 imagepalettetotruecolor($im);
582 $im_ = imagecreatetruecolor($x_i, $y_i);
583 @imagealphablending
($im_, false);
584 @imagesavealpha
($im_, true);
586 $color_t = ImageColorAllocateAlpha($im_, 255, 255, 255, 127);
587 imagefill($im_, 0, 0, $color_t);
589 for ($x = 0; $x < $x_i; $x++
) {
590 for ($y = 0; $y < $y_i; $y++
) {
591 imagecopy($im_, $im, $x, $y_i - $y - 1, $x, $y, 1, 1);
594 _image_gd_output($im_, $image);
599 return _image_ecrire_tag($image, array('src' => $dest));
602 // https://code.spip.net/@image_masque
603 function image_masque($im, $masque, $pos = "") {
604 // Passer, en plus de l'image d'origine,
605 // une image de "masque": un fichier PNG24 transparent.
606 // Le decoupage se fera selon la transparence du "masque",
607 // et les couleurs seront eclaircies/foncees selon de couleur du masque.
608 // Pour ne pas modifier la couleur, le masque doit etre en gris 50%.
610 // Si l'image source est plus grande que le masque, alors cette image est reduite a la taille du masque.
611 // Sinon, c'est la taille de l'image source qui est utilisee.
613 // $pos est une variable libre, qui permet de passer left=..., right=..., bottom=..., top=...
614 // dans ce cas, le masque est place a ces positions sur l'image d'origine,
615 // et evidemment cette image d'origine n'est pas redimensionnee
617 // Positionnement horizontal: text-align=left, right, center
618 // Positionnement vertical : vertical-align=top, bottom, middle
619 // (les positionnements left, right, top, left sont relativement inutiles, mais coherence avec CSS)
621 // Choix du mode de fusion: mode=masque, normal, eclaircir, obscurcir, produit, difference, ecran, superposer, lumiere_dure, teinte, saturation, valeur
622 // https://en.wikipedia.org/wiki/Blend_modes
623 // masque: mode par defaut
624 // normal: place la nouvelle image par dessus l'ancienne
625 // eclaircir: place uniquement les points plus clairs
626 // obscurcir: place uniquement les points plus fonc'es
627 // produit: multiplie par le masque (points noirs rendent l'image noire, points blancs ne changent rien)
628 // difference: remplit avec l'ecart entre les couleurs d'origine et du masque
629 // ecran: effet inverse de 'produit' -> l'image resultante est plus claire
630 // superposer: combine les modes 'produit' et 'ecran' -> les parties claires sont eclaircies, les parties sombres assombries.
631 // lumiere_dure: equivalent a 'superposer', sauf que l'image du bas et du haut sont inversees.
632 // teinte: utilise la teinte du masque
633 // saturation: utilise la saturation du masque
634 // valeur: utilise la valeur du masque
638 $numargs = func_num_args();
639 $arg_list = func_get_args();
642 $texte = $arg_list[0];
643 for ($i = 1; $i < $numargs; $i++
) {
644 if (($p = strpos($arg_list[$i], "=")) !== false) {
645 $nom_variable = substr($arg_list[$i], 0, $p);
646 $val_variable = substr($arg_list[$i], $p +
1);
647 $variable["$nom_variable"] = $val_variable;
648 $defini["$nom_variable"] = 1;
651 if (isset($defini["mode"]) and $defini["mode"]) {
652 $mode = $variable["mode"];
655 // utiliser _image_valeurs_trans pour accepter comme masque :
656 // - une balise <img src='...' />
657 // - une image avec un timestamp ?01234
658 $mask = _image_valeurs_trans($masque, "source-image_masque", "png", null, true);
662 $masque = $mask['fichier'];
664 $pos = md5(serialize($variable) . $mask['date_src']);
665 $fonction = array('image_masque', func_get_args());
666 $image = _image_valeurs_trans($im, "masque-$masque-$pos", "png", $fonction);
671 $x_i = $image["largeur"];
672 $y_i = $image["hauteur"];
674 $im = $image["fichier"];
675 $dest = $image["fichier_dest"];
677 $creer = $image["creer"];
679 // doit-on positionner l'image ?
681 foreach (array("right", "left", "bottom", "top", "text-align", "vertical-align") as $pl) {
682 if (isset($defini[$pl]) and $defini[$pl]) {
690 $im_m = $mask["fichier"];
691 $x_m = $mask["largeur"];
692 $y_m = $mask["hauteur"];
694 $im2 = $mask["fonction_imagecreatefrom"]($masque);
695 if ($mask["format_source"] == "gif" and function_exists('ImageCopyResampled')) {
696 $im2_ = imagecreatetruecolor($x_m, $y_m);
697 // Si un GIF est transparent,
698 // fabriquer un PNG transparent
699 // Conserver la transparence
700 if (function_exists("imageAntiAlias")) {
701 imageAntiAlias($im2_, true);
703 @imagealphablending
($im2_, false);
704 @imagesavealpha
($im2_, true);
705 @ImageCopyResampled
($im2_, $im2, 0, 0, 0, 0, $x_m, $y_m, $x_m, $y_m);
711 // On fabriquer une version "agrandie" du masque,
712 // aux dimensions de l'image source
713 // et on "installe" le masque dans cette image
714 // ainsi: aucun redimensionnement
719 if (isset($defini["right"]) and $defini["right"]) {
720 $right = $variable["right"];
721 $dx = ($x_i - $x_m) - $right;
723 if (isset($defini["bottom"]) and $defini["bottom"]) {
724 $bottom = $variable["bottom"];
725 $dy = ($y_i - $y_m) - $bottom;
727 if (isset($defini["top"]) and $defini["top"]) {
728 $top = $variable["top"];
731 if (isset($defini["left"]) and $defini["left"]) {
732 $left = $variable["left"];
735 if (isset($defini["text-align"]) and $defini["text-align"]) {
736 $align = $variable["text-align"];
737 if ($align == "right") {
741 if ($align == "left") {
745 if ($align = "center") {
746 $dx = round(($x_i - $x_m) / 2);
751 if (isset($defini["vertical-align"]) and $defini["vertical-align"]) {
752 $valign = $variable["vertical-align"];
753 if ($valign == "bottom") {
757 if ($valign == "top") {
761 if ($valign = "middle") {
762 $dy = round(($y_i - $y_m) / 2);
769 $im3 = imagecreatetruecolor($x_i, $y_i);
770 @imagealphablending
($im3, false);
771 @imagesavealpha
($im3, true);
772 if ($mode == "masque") {
773 $color_t = ImageColorAllocateAlpha($im3, 128, 128, 128, 0);
775 $color_t = ImageColorAllocateAlpha($im3, 128, 128, 128, 127);
777 imagefill($im3, 0, 0, $color_t);
780 imagecopy($im3, $im2, $dx, $dy, 0, 0, $x_m, $y_m);
783 $im2 = imagecreatetruecolor($x_i, $y_i);
784 @imagealphablending
($im2, false);
785 @imagesavealpha
($im2, true);
787 imagecopy($im2, $im3, 0, 0, 0, 0, $x_i, $y_i);
794 $rapport = $x_i / $x_m;
795 if (($y_i / $y_m) < $rapport) {
796 $rapport = $y_i / $y_m;
799 $x_d = ceil($x_i / $rapport);
800 $y_d = ceil($y_i / $rapport);
803 if ($x_i < $x_m or $y_i < $y_m) {
811 $x_dec = round(($x_d - $x_m) / 2);
812 $y_dec = round(($y_d - $y_m) / 2);
816 $nouveau = _image_valeurs_trans(image_reduire($im, $x_d, $y_d), "");
817 if (!is_array($nouveau)) {
820 $im_n = $nouveau["fichier"];
823 $im = $nouveau["fonction_imagecreatefrom"]($im_n);
824 imagepalettetotruecolor($im);
825 if ($nouveau["format_source"] == "gif" and function_exists('ImageCopyResampled')) {
826 $im_ = imagecreatetruecolor($x_dest, $y_dest);
827 // Si un GIF est transparent,
828 // fabriquer un PNG transparent
829 // Conserver la transparence
830 if (function_exists("imageAntiAlias")) {
831 imageAntiAlias($im_, true);
833 @imagealphablending
($im_, false);
834 @imagesavealpha
($im_, true);
835 @ImageCopyResampled
($im_, $im, 0, 0, 0, 0, $x_dest, $y_dest, $x_dest, $y_dest);
839 $im_ = imagecreatetruecolor($x_dest, $y_dest);
840 @imagealphablending
($im_, false);
841 @imagesavealpha
($im_, true);
842 $color_t = ImageColorAllocateAlpha($im_, 255, 255, 255, 127);
843 imagefill($im_, 0, 0, $color_t);
846 // calcul couleurs de chaque pixel selon les modes de fusion
847 for ($x = 0; $x < $x_dest; $x++
) {
848 for ($y = 0; $y < $y_dest; $y++
) {
849 $rgb = ImageColorAt($im2, $x, $y); // image au dessus
850 $a = ($rgb >> 24) & 0xFF;
851 $r = ($rgb >> 16) & 0xFF;
852 $g = ($rgb >> 8) & 0xFF;
855 $rgb2 = ImageColorAt($im, $x +
$x_dec, $y +
$y_dec); // image en dessous
856 $a2 = ($rgb2 >> 24) & 0xFF;
857 $r2 = ($rgb2 >> 16) & 0xFF;
858 $g2 = ($rgb2 >> 8) & 0xFF;
861 if ($mode == "normal") {
862 $v = (127 - $a) / 127;
868 $v2 = (127 - $a2) / 127;
884 $r_ = $r +
(($r2 - $r) * $v2 * (1 - $v));
885 $g_ = $g +
(($g2 - $g) * $v2 * (1 - $v));
886 $b_ = $b +
(($b2 - $b) * $v2 * (1 - $v));
893 } elseif (in_array($mode, array("produit", "difference", "superposer", "lumiere_dure", "ecran"))) {
894 if ($mode == "produit") {
895 $r = ($r / 255) * $r2;
896 $g = ($g / 255) * $g2;
897 $b = ($b / 255) * $b2;
898 } elseif ($mode == "difference") {
902 } elseif ($mode == "superposer") {
903 $r = ($r2 < 128) ?
2 * $r * $r2 / 255 : 255 - (2 * (255 - $r) * (255 - $r2) / 255);
904 $g = ($g2 < 128) ?
2 * $g * $g2 / 255 : 255 - (2 * (255 - $g) * (255 - $g2) / 255);
905 $b = ($b2 < 128) ?
2 * $b * $b2 / 255 : 255 - (2 * (255 - $b) * (255 - $b2) / 255);
906 } elseif ($mode == "lumiere_dure") {
907 $r = ($r < 128) ?
2 * $r * $r2 / 255 : 255 - (2 * (255 - $r2) * (255 - $r) / 255);
908 $g = ($g < 128) ?
2 * $g * $g2 / 255 : 255 - (2 * (255 - $g2) * (255 - $g) / 255);
909 $b = ($b < 128) ?
2 * $b * $b2 / 255 : 255 - (2 * (255 - $b2) * (255 - $b) / 255);
910 } elseif ($mode == "ecran") {
911 $r = 255 - (((255 - $r) * (255 - $r2)) / 255);
912 $g = 255 - (((255 - $g) * (255 - $g2)) / 255);
913 $b = 255 - (((255 - $b) * (255 - $b2)) / 255);
915 $r = max(0, min($r, 255));
916 $g = max(0, min($g, 255));
917 $b = max(0, min($b, 255));
919 // melange en fonction de la transparence du masque
920 $v = (127 - $a) / 127;
921 if ($v == 1) { // melange complet
926 $v2 = (127 - $a2) / 127;
927 if ($v +
$v2 == 0) { // ??
931 } else { // pas de melange (transparence du masque)
932 $r_ = $r +
(($r2 - $r) * $v2 * (1 - $v));
933 $g_ = $g +
(($g2 - $g) * $v2 * (1 - $v));
934 $b_ = $b +
(($b2 - $b) * $v2 * (1 - $v));
939 } elseif ($mode == "eclaircir" or $mode == "obscurcir") {
940 $v = (127 - $a) / 127;
946 $v2 = (127 - $a2) / 127;
952 $r_ = $r +
(($r2 - $r) * $v2 * (1 - $v));
953 $g_ = $g +
(($g2 - $g) * $v2 * (1 - $v));
954 $b_ = $b +
(($b2 - $b) * $v2 * (1 - $v));
957 if ($mode == "eclaircir") {
968 } elseif (in_array($mode, array("teinte", "saturation", "valeur"))) {
969 include_spip("filtres/images_lib");
970 $hsv = _couleur_rgb2hsv($r, $g, $b); // image au dessus
974 $hsv2 = _couleur_rgb2hsv($r2, $g2, $b2); // image en dessous
980 $rgb3 = _couleur_hsv2rgb($h, $s2, $v2);
983 $rgb3 = _couleur_hsv2rgb($h2, $s, $v2);
986 $rgb3 = _couleur_hsv2rgb($h2, $s2, $v);
993 // melange en fonction de la transparence du masque
994 $v = (127 - $a) / 127;
995 if ($v == 1) { // melange complet
1000 $v2 = (127 - $a2) / 127;
1001 if ($v +
$v2 == 0) { // ??
1005 } else { // pas de melange (transparence du masque)
1006 $r_ = $r +
(($r2 - $r) * $v2 * (1 - $v));
1007 $g_ = $g +
(($g2 - $g) * $v2 * (1 - $v));
1008 $b_ = $b +
(($b2 - $b) * $v2 * (1 - $v));
1014 $r_ = $r2 +
1 * ($r - 127);
1015 $r_ = max(0, min($r_, 255));
1016 $g_ = $g2 +
1 * ($g - 127);
1017 $g_ = max(0, min($g_, 255));
1018 $b_ = $b2 +
1 * ($b - 127);
1019 $b_ = max(0, min($b_, 255));
1020 $a_ = $a +
$a2 - round($a * $a2 / 127);
1023 $color = ImageColorAllocateAlpha($im_, $r_, $g_, $b_, $a_);
1024 imagesetpixel($im_, $x, $y, $color);
1028 _image_gd_output($im_, $image);
1034 $x_dest = largeur($dest);
1035 $y_dest = hauteur($dest);
1037 return _image_ecrire_tag($image, array('src' => $dest, 'width' => $x_dest, 'height' => $y_dest));
1040 // Passage de l'image en noir et blanc
1041 // un noir & blanc "photo" n'est pas "neutre": les composantes de couleur sont
1042 // ponderees pour obtenir le niveau de gris;
1043 // on peut ici regler cette ponderation en "pour mille"
1044 // https://code.spip.net/@image_nb
1045 function image_nb($im, $val_r = 299, $val_g = 587, $val_b = 114) {
1046 $fonction = array('image_nb', func_get_args());
1047 $image = _image_valeurs_trans($im, "nb-$val_r-$val_g-$val_b", false, $fonction);
1052 $x_i = $image["largeur"];
1053 $y_i = $image["hauteur"];
1055 $im = $image["fichier"];
1056 $dest = $image["fichier_dest"];
1058 $creer = $image["creer"];
1061 // resultat plus beau, mais tres lourd
1062 // Et: indispensable pour preserver transparence!
1065 // Creation de l'image en deux temps
1066 // de facon a conserver les GIF transparents
1067 $im = $image["fonction_imagecreatefrom"]($im);
1068 imagepalettetotruecolor($im);
1069 $im_ = imagecreatetruecolor($x_i, $y_i);
1070 @imagealphablending
($im_, false);
1071 @imagesavealpha
($im_, true);
1072 $color_t = ImageColorAllocateAlpha($im_, 255, 255, 255, 127);
1073 imagefill($im_, 0, 0, $color_t);
1074 imagecopy($im_, $im, 0, 0, 0, 0, $x_i, $y_i);
1076 for ($x = 0; $x < $x_i; $x++
) {
1077 for ($y = 0; $y < $y_i; $y++
) {
1078 $rgb = ImageColorAt($im_, $x, $y);
1079 $a = ($rgb >> 24) & 0xFF;
1080 $r = ($rgb >> 16) & 0xFF;
1081 $g = ($rgb >> 8) & 0xFF;
1084 $c = round(($val_r * $r / 1000) +
($val_g * $g / 1000) +
($val_b * $b / 1000));
1093 $color = ImageColorAllocateAlpha($im_, $c, $c, $c, $a);
1094 imagesetpixel($im_, $x, $y, $color);
1097 _image_gd_output($im_, $image);
1102 return _image_ecrire_tag($image, array('src' => $dest));
1105 // https://code.spip.net/@image_flou
1106 function image_flou($im, $niveau = 3) {
1107 // Il s'agit d'une modification du script blur qu'on trouve un peu partout:
1108 // + la transparence est geree correctement
1109 // + les dimensions de l'image sont augmentees pour flouter les bords
1115 array(1, 4, 6, 4, 1),
1116 array(1, 5, 10, 10, 5, 1),
1117 array(1, 6, 15, 20, 15, 6, 1),
1118 array(1, 7, 21, 35, 35, 21, 7, 1),
1119 array(1, 8, 28, 56, 70, 56, 28, 8, 1),
1120 array(1, 9, 36, 84, 126, 126, 84, 36, 9, 1),
1121 array(1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1),
1122 array(1, 11, 55, 165, 330, 462, 462, 330, 165, 55, 11, 1)
1125 $fonction = array('image_flou', func_get_args());
1126 $image = _image_valeurs_trans($im, "flou-$niveau", false, $fonction);
1131 $x_i = $image["largeur"];
1132 $y_i = $image["hauteur"];
1133 $sum = pow(2, $niveau);
1135 $im = $image["fichier"];
1136 $dest = $image["fichier_dest"];
1138 $creer = $image["creer"];
1141 // resultat plus beau, mais tres lourd
1142 // Et: indispensable pour preserver transparence!
1145 // Creation de l'image en deux temps
1146 // de facon a conserver les GIF transparents
1147 $im = $image["fonction_imagecreatefrom"]($im);
1148 imagepalettetotruecolor($im);
1149 $temp1 = imagecreatetruecolor($x_i +
$niveau, $y_i);
1150 $temp2 = imagecreatetruecolor($x_i +
$niveau, $y_i +
$niveau);
1152 @imagealphablending
($temp1, false);
1153 @imagesavealpha
($temp1, true);
1154 @imagealphablending
($temp2, false);
1155 @imagesavealpha
($temp2, true);
1158 for ($i = 0; $i < $x_i +
$niveau; $i++
) {
1159 for ($j = 0; $j < $y_i; $j++
) {
1166 for ($k = 0; $k <= $niveau; ++
$k) {
1167 $color = imagecolorat($im, $i_ = ($i - $niveau) +
$k, $j);
1169 $a = ($color >> 24) & 0xFF;
1170 $r = ($color >> 16) & 0xFF;
1171 $g = ($color >> 8) & 0xFF;
1172 $b = ($color) & 0xFF;
1174 if ($i_ < 0 or $i_ >= $x_i) {
1178 $coef = $coeffs[$niveau][$k];
1179 $suma +
= $a * $coef;
1180 $ac = ((127 - $a) / 127);
1184 $sumr +
= $r * $coef * $ac;
1185 $sumg +
= $g * $coef * $ac;
1186 $sumb +
= $b * $coef * $ac;
1187 $sum +
= $coef * $ac;
1191 $color = ImageColorAllocateAlpha($temp1, $sumr / $sum, $sumg / $sum, $sumb / $sum, $suma / $sum_);
1193 $color = ImageColorAllocateAlpha($temp1, 255, 255, 255, 127);
1195 imagesetpixel($temp1, $i, $j, $color);
1199 for ($i = 0; $i < $x_i +
$niveau; $i++
) {
1200 for ($j = 0; $j < $y_i +
$niveau; $j++
) {
1207 for ($k = 0; $k <= $niveau; ++
$k) {
1208 $color = imagecolorat($temp1, $i, $j_ = $j - $niveau +
$k);
1209 $a = ($color >> 24) & 0xFF;
1210 $r = ($color >> 16) & 0xFF;
1211 $g = ($color >> 8) & 0xFF;
1212 $b = ($color) & 0xFF;
1213 if ($j_ < 0 or $j_ >= $y_i) {
1217 $suma +
= $a * $coeffs[$niveau][$k];
1218 $ac = ((127 - $a) / 127);
1220 $sumr +
= $r * $coeffs[$niveau][$k] * $ac;
1221 $sumg +
= $g * $coeffs[$niveau][$k] * $ac;
1222 $sumb +
= $b * $coeffs[$niveau][$k] * $ac;
1223 $sum +
= $coeffs[$niveau][$k] * $ac;
1224 $sum_ +
= $coeffs[$niveau][$k];
1228 $color = ImageColorAllocateAlpha($temp2, $sumr / $sum, $sumg / $sum, $sumb / $sum, $suma / $sum_);
1230 $color = ImageColorAllocateAlpha($temp2, 255, 255, 255, 127);
1232 imagesetpixel($temp2, $i, $j, $color);
1236 _image_gd_output($temp2, $image);
1237 imagedestroy($temp1);
1238 imagedestroy($temp2);
1241 return _image_ecrire_tag($image, array('src' => $dest, 'width' => ($x_i +
$niveau), 'height' => ($y_i +
$niveau)));
1244 // https://code.spip.net/@image_RotateBicubic
1245 function image_RotateBicubic($src_img, $angle, $bicubic = 0) {
1246 include_spip('filtres/images_lib');
1248 if (round($angle / 90) * 90 == $angle) {
1250 if (round($angle / 180) * 180 == $angle) {
1259 // convert degrees to radians
1260 $angle = $angle +
180;
1261 $angle = deg2rad($angle);
1264 $src_x = imagesx($src_img);
1265 $src_y = imagesy($src_img);
1268 $center_x = floor(($src_x - 1) / 2);
1269 $center_y = floor(($src_y - 1) / 2);
1271 $cosangle = cos($angle);
1272 $sinangle = sin($angle);
1274 // calculer dimensions en simplifiant angles droits, ce qui evite "floutage"
1275 // des rotations a angle droit
1277 $corners = array(array(0, 0), array($src_x, 0), array($src_x, $src_y), array(0, $src_y));
1279 foreach ($corners as $key => $value) {
1280 $value[0] -= $center_x; //Translate coords to center for rotation
1281 $value[1] -= $center_y;
1283 $temp[0] = $value[0] * $cosangle +
$value[1] * $sinangle;
1284 $temp[1] = $value[1] * $cosangle - $value[0] * $sinangle;
1285 $corners[$key] = $temp;
1288 $min_x = 1000000000000000;
1289 $max_x = -1000000000000000;
1290 $min_y = 1000000000000000;
1291 $max_y = -1000000000000000;
1293 foreach ($corners as $key => $value) {
1294 if ($value[0] < $min_x) {
1297 if ($value[0] > $max_x) {
1301 if ($value[1] < $min_y) {
1304 if ($value[1] > $max_y) {
1309 $rotate_width = ceil($max_x - $min_x);
1310 $rotate_height = ceil($max_y - $min_y);
1313 $rotate_height = $src_y;
1314 $rotate_width = $src_x;
1316 $rotate_height = $src_x;
1317 $rotate_width = $src_y;
1323 $rotate = imagecreatetruecolor($rotate_width, $rotate_height);
1324 imagealphablending($rotate, false);
1325 imagesavealpha($rotate, true);
1327 $cosangle = cos($angle);
1328 $sinangle = sin($angle);
1330 // arrondir pour rotations angle droit (car cos et sin dans {-1,0,1})
1332 $cosangle = round($cosangle);
1333 $sinangle = round($sinangle);
1336 $newcenter_x = ($rotate_width - 1) / 2;
1337 $newcenter_y = ($rotate_height - 1) / 2;
1340 for ($y = 0; $y < $rotate_height; $y++
) {
1341 for ($x = 0; $x < $rotate_width; $x++
) {
1343 $old_x = ((($newcenter_x - $x) * $cosangle +
($newcenter_y - $y) * $sinangle))
1345 $old_y = ((($newcenter_y - $y) * $cosangle - ($newcenter_x - $x) * $sinangle))
1348 $old_x = ceil($old_x);
1349 $old_y = ceil($old_y);
1351 if ($old_x >= 0 && $old_x < $src_x
1352 && $old_y >= 0 && $old_y < $src_y
1354 if ($bicubic == true) {
1362 // on prend chaque point, mais on pondere en fonction de la distance
1363 $rgb = ImageColorAt($src_img, $x0, $y0);
1364 $a1 = ($rgb >> 24) & 0xFF;
1365 $r1 = ($rgb >> 16) & 0xFF;
1366 $g1 = ($rgb >> 8) & 0xFF;
1368 $d1 = _image_distance_pixel($xo, $yo, $x0, $y0);
1370 $rgb = ImageColorAt($src_img, $x1, $y0);
1371 $a2 = ($rgb >> 24) & 0xFF;
1372 $r2 = ($rgb >> 16) & 0xFF;
1373 $g2 = ($rgb >> 8) & 0xFF;
1375 $d2 = _image_distance_pixel($xo, $yo, $x1, $y0);
1377 $rgb = ImageColorAt($src_img, $x0, $y1);
1378 $a3 = ($rgb >> 24) & 0xFF;
1379 $r3 = ($rgb >> 16) & 0xFF;
1380 $g3 = ($rgb >> 8) & 0xFF;
1382 $d3 = _image_distance_pixel($xo, $yo, $x0, $y1);
1384 $rgb = ImageColorAt($src_img, $x1, $y1);
1385 $a4 = ($rgb >> 24) & 0xFF;
1386 $r4 = ($rgb >> 16) & 0xFF;
1387 $g4 = ($rgb >> 8) & 0xFF;
1389 $d4 = _image_distance_pixel($xo, $yo, $x1, $y1);
1391 $ac1 = ((127 - $a1) / 127);
1392 $ac2 = ((127 - $a2) / 127);
1393 $ac3 = ((127 - $a3) / 127);
1394 $ac4 = ((127 - $a4) / 127);
1396 // limiter impact des couleurs transparentes,
1397 // mais attention tout transp: division par 0
1398 if ($ac1 * $d1 +
$ac2 * $d2 +
$ac3 +
$d3 +
$ac4 +
$d4 > 0) {
1413 $tot = $d1 +
$d2 +
$d3 +
$d4;
1415 $r = round((($d1 * $r1) +
($d2 * $r2) +
($d3 * $r3) +
($d4 * $r4)) / $tot);
1416 $g = round((($d1 * $g1 +
($d2 * $g2) +
$d3 * $g3 +
$d4 * $g4)) / $tot);
1417 $b = round((($d1 * $b1 +
($d2 * $b2) +
$d3 * $b3 +
$d4 * $b4)) / $tot);
1418 $a = round((($d1 * $a1 +
($d2 * $a2) +
$d3 * $a3 +
$d4 * $a4)) / $tot);
1419 $color = imagecolorallocatealpha($src_img, $r, $g, $b, $a);
1421 $color = imagecolorat($src_img, round($old_x), round($old_y));
1424 // this line sets the background colour
1425 $color = imagecolorallocatealpha($src_img, 255, 255, 255, 127);
1427 @imagesetpixel
($rotate, $x, $y, $color);
1434 // permet de faire tourner une image d'un angle quelconque
1435 // la fonction "crop" n'est pas implementee...
1436 // https://code.spip.net/@image_rotation
1437 function image_rotation($im, $angle, $crop = false) {
1438 $fonction = array('image_rotation', func_get_args());
1439 $image = _image_valeurs_trans($im, "rot-$angle-$crop", "png", $fonction);
1444 $im = $image["fichier"];
1445 $dest = $image["fichier_dest"];
1447 $creer = $image["creer"];
1450 $effectuer_gd = true;
1452 if (method_exists('Imagick', 'rotateImage')) {
1453 $imagick = new Imagick();
1454 $imagick->readImage($im);
1455 $imagick->rotateImage(new ImagickPixel('none'), $angle);
1456 $imagick->writeImage($dest);
1457 $effectuer_gd = false;
1459 if ($GLOBALS['meta']['image_process'] == "convert") {
1460 if (_CONVERT_COMMAND
!= '') {
1461 @define
('_CONVERT_COMMAND', 'convert');
1462 @define
('_ROTATE_COMMAND', _CONVERT_COMMAND
. ' -background none -rotate %t %src %dest');
1464 @define
('_ROTATE_COMMAND', '');
1466 if (_ROTATE_COMMAND
!== '') {
1467 $commande = str_replace(
1468 array('%t', '%src', '%dest'),
1471 escapeshellcmd($im),
1472 escapeshellcmd($dest)
1475 spip_log($commande);
1477 if (file_exists($dest)) // precaution
1479 $effectuer_gd = false;
1483 // cette variante genere-t-elle un fond transparent
1484 // dans les coins vide issus de la rotation ?
1485 elseif (function_exists('imagick_rotate')) {
1486 $handle = imagick_readimage($im);
1487 if ($handle && imagick_isopaqueimage($handle)) {
1488 imagick_setfillcolor($handle, 'transparent');
1489 imagick_rotate($handle, $angle);
1490 imagick_writeimage($handle, $dest);
1491 $effectuer_gd = false;
1495 if ($effectuer_gd) {
1496 // Creation de l'image en deux temps
1497 // de facon a conserver les GIF transparents
1498 $im = $image["fonction_imagecreatefrom"]($im);
1499 imagepalettetotruecolor($im);
1500 $im = image_RotateBicubic($im, $angle, true);
1501 _image_gd_output($im, $image);
1505 list($src_y, $src_x) = taille_image($dest);
1507 return _image_ecrire_tag($image, array('src' => $dest, 'width' => $src_x, 'height' => $src_y));
1510 // Permet d'appliquer un filtre php_imagick a une image
1511 // par exemple: [(#LOGO_ARTICLE|image_imagick{imagick_wave,20,60})]
1512 // liste des fonctions: http://www.linux-nantes.org/~fmonnier/doc/imagick/
1513 // https://code.spip.net/@image_imagick
1514 function image_imagick() {
1515 $tous = func_get_args();
1519 $tous_var = join($tous, "-");
1521 $fonction = array('image_imagick', func_get_args());
1522 $image = _image_valeurs_trans($img, "$tous_var", "png", $fonction);
1527 $im = $image["fichier"];
1528 $dest = $image["fichier_dest"];
1530 $creer = $image["creer"];
1533 if (function_exists($fonc)) {
1535 $handle = imagick_readimage($im);
1537 for ($i = 2; $i < count($tous); $i++
) {
1540 call_user_func_array($fonc, $arr);
1541 // Creer image dans fichier temporaire, puis renommer vers "bon" fichier
1542 // de facon a eviter time_out pendant creation de l'image definitive
1543 $tmp = preg_replace(",[.]png$,i", "-tmp.png", $dest);
1544 imagick_writeimage($handle, $tmp);
1545 rename($tmp, $dest);
1546 ecrire_fichier($dest . ".src", serialize($image));
1549 list($src_y, $src_x) = taille_image($dest);
1551 return _image_ecrire_tag($image, array('src' => $dest, 'width' => $src_x, 'height' => $src_y));
1555 // Permet de rendre une image
1556 // plus claire (gamma > 0)
1557 // ou plus foncee (gamma < 0)
1558 // https://code.spip.net/@image_gamma
1559 function image_gamma($im, $gamma = 0) {
1560 include_spip('filtres/images_lib');
1561 $fonction = array('image_gamma', func_get_args());
1562 $image = _image_valeurs_trans($im, "gamma-$gamma", false, $fonction);
1567 $x_i = $image["largeur"];
1568 $y_i = $image["hauteur"];
1570 $im = $image["fichier"];
1571 $dest = $image["fichier_dest"];
1573 $creer = $image["creer"];
1576 // Creation de l'image en deux temps
1577 // de facon a conserver les GIF transparents
1578 $im = $image["fonction_imagecreatefrom"]($im);
1579 imagepalettetotruecolor($im);
1580 $im_ = imagecreatetruecolor($x_i, $y_i);
1581 @imagealphablending
($im_, false);
1582 @imagesavealpha
($im_, true);
1583 $color_t = ImageColorAllocateAlpha($im_, 255, 255, 255, 127);
1584 imagefill($im_, 0, 0, $color_t);
1585 imagecopy($im_, $im, 0, 0, 0, 0, $x_i, $y_i);
1587 for ($x = 0; $x < $x_i; $x++
) {
1588 for ($y = 0; $y < $y_i; $y++
) {
1589 $rgb = ImageColorAt($im_, $x, $y);
1590 $a = ($rgb >> 24) & 0xFF;
1591 $r = ($rgb >> 16) & 0xFF;
1592 $g = ($rgb >> 8) & 0xFF;
1595 $r = _image_decale_composante($r, $gamma);
1596 $g = _image_decale_composante($g, $gamma);
1597 $b = _image_decale_composante($b, $gamma);
1599 $color = ImageColorAllocateAlpha($im_, $r, $g, $b, $a);
1600 imagesetpixel($im_, $x, $y, $color);
1603 _image_gd_output($im_, $image);
1606 return _image_ecrire_tag($image, array('src' => $dest));
1609 // Passe l'image en "sepia"
1610 // On peut fixer les valeurs RGB
1611 // de la couleur "complementaire" pour forcer une dominante
1612 //function image_sepia($im, $dr = 137, $dv = 111, $db = 94)
1613 // https://code.spip.net/@image_sepia
1614 function image_sepia($im, $rgb = "896f5e") {
1615 include_spip('filtres/images_lib');
1617 if (!function_exists("imagecreatetruecolor")) {
1621 $couleurs = _couleur_hex_to_dec($rgb);
1622 $dr = $couleurs["red"];
1623 $dv = $couleurs["green"];
1624 $db = $couleurs["blue"];
1626 $fonction = array('image_sepia', func_get_args());
1627 $image = _image_valeurs_trans($im, "sepia-$dr-$dv-$db", false, $fonction);
1632 $x_i = $image["largeur"];
1633 $y_i = $image["hauteur"];
1635 $im = $image["fichier"];
1636 $dest = $image["fichier_dest"];
1638 $creer = $image["creer"];
1641 // Creation de l'image en deux temps
1642 // de facon a conserver les GIF transparents
1643 $im = $image["fonction_imagecreatefrom"]($im);
1644 imagepalettetotruecolor($im);
1645 $im_ = imagecreatetruecolor($x_i, $y_i);
1646 @imagealphablending
($im_, false);
1647 @imagesavealpha
($im_, true);
1648 $color_t = ImageColorAllocateAlpha($im_, 255, 255, 255, 127);
1649 imagefill($im_, 0, 0, $color_t);
1650 imagecopy($im_, $im, 0, 0, 0, 0, $x_i, $y_i);
1652 for ($x = 0; $x < $x_i; $x++
) {
1653 for ($y = 0; $y < $y_i; $y++
) {
1654 $rgb = ImageColorAt($im_, $x, $y);
1655 $a = ($rgb >> 24) & 0xFF;
1656 $r = ($rgb >> 16) & 0xFF;
1657 $g = ($rgb >> 8) & 0xFF;
1660 $r = round(.299 * $r +
.587 * $g +
.114 * $b);
1665 $r = _image_decale_composante_127($r, $dr);
1666 $g = _image_decale_composante_127($g, $dv);
1667 $b = _image_decale_composante_127($b, $db);
1669 $color = ImageColorAllocateAlpha($im_, $r, $g, $b, $a);
1670 imagesetpixel($im_, $x, $y, $color);
1673 _image_gd_output($im_, $image);
1678 return _image_ecrire_tag($image, array('src' => $dest));
1683 * Renforcer la netteté d'une image
1686 * Code HTML de l'image
1688 * Niveau de renforcement (entre 0 et 1)
1689 * @return string Code HTML de l'image
1691 function image_renforcement($im, $k = 0.5) {
1692 $fonction = array('image_flou', func_get_args());
1693 $image = _image_valeurs_trans($im, "renforcement-$k", false, $fonction);
1698 $x_i = $image["largeur"];
1699 $y_i = $image["hauteur"];
1700 $im = $image["fichier"];
1701 $dest = $image["fichier_dest"];
1702 $creer = $image["creer"];
1705 $im = $image["fonction_imagecreatefrom"]($im);
1706 imagepalettetotruecolor($im);
1707 $im_ = imagecreatetruecolor($x_i, $y_i);
1708 @imagealphablending
($im_, false);
1709 @imagesavealpha
($im_, true);
1710 $color_t = ImageColorAllocateAlpha($im_, 255, 255, 255, 127);
1711 imagefill($im_, 0, 0, $color_t);
1713 for ($x = 0; $x < $x_i; $x++
) {
1714 for ($y = 0; $y < $y_i; $y++
) {
1716 $rgb[1][0] = @imagecolorat
($im, $x, $y - 1);
1717 $rgb[0][1] = @imagecolorat
($im, $x - 1, $y);
1718 $rgb[1][1] = @imagecolorat
($im, $x, $y);
1719 $rgb[2][1] = @imagecolorat
($im, $x +
1, $y);
1720 $rgb[1][2] = @imagecolorat
($im, $x, $y +
1);
1723 $rgb[0][1] = $rgb[1][1];
1726 $rgb[1][0] = $rgb[1][1];
1728 if ($x +
1 == $x_i) {
1729 $rgb[2][1] = $rgb[1][1];
1731 if ($y +
1 == $y_i) {
1732 $rgb[1][2] = $rgb[1][1];
1735 $a = ($rgb[1][1] >> 24) & 0xFF;
1736 $r = -$k * (($rgb[1][0] >> 16) & 0xFF) +
1737 -$k * (($rgb[0][1] >> 16) & 0xFF) +
1738 (1 +
4 * $k) * (($rgb[1][1] >> 16) & 0xFF) +
1739 -$k * (($rgb[2][1] >> 16) & 0xFF) +
1740 -$k * (($rgb[1][2] >> 16) & 0xFF);
1742 $g = -$k * (($rgb[1][0] >> 8) & 0xFF) +
1743 -$k * (($rgb[0][1] >> 8) & 0xFF) +
1744 (1 +
4 * $k) * (($rgb[1][1] >> 8) & 0xFF) +
1745 -$k * (($rgb[2][1] >> 8) & 0xFF) +
1746 -$k * (($rgb[1][2] >> 8) & 0xFF);
1748 $b = -$k * ($rgb[1][0] & 0xFF) +
1749 -$k * ($rgb[0][1] & 0xFF) +
1750 (1 +
4 * $k) * ($rgb[1][1] & 0xFF) +
1751 -$k * ($rgb[2][1] & 0xFF) +
1752 -$k * ($rgb[1][2] & 0xFF);
1754 $r = min(255, max(0, $r));
1755 $g = min(255, max(0, $g));
1756 $b = min(255, max(0, $b));
1759 $color = ImageColorAllocateAlpha($im_, $r, $g, $b, $a);
1760 imagesetpixel($im_, $x, $y, $color);
1763 _image_gd_output($im_, $image);
1766 return _image_ecrire_tag($image, array('src' => $dest));
1771 * Transforme la couleur de fond de l'image en transparence
1772 * Le filtre ne gere pas la notion de contiguite aux bords, et affectera tous les pixels de l'image dans la couleur visee
1773 * $background_color : couleur cible
1774 * $tolerance : distance L1 dans l'espace RGB des couleur autour de la couleur $background_color pour lequel la transparence sera appliquee
1775 * $alpha : transparence a appliquer pour les pixels de la couleur cibles avec la tolerance ci-dessus
1776 * $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
1779 * @param string $background_color
1780 * @param int $tolerance
1782 * alpha = 0: aucune transparence
1783 * alpha = 127: completement transparent
1784 * @param int $coeff_lissage
1785 * @return mixed|null|string
1787 function image_fond_transparent($im, $background_color, $tolerance = 12, $alpha = 127, $coeff_lissage = 7) {
1788 $fonction = array('image_fond_transparent', func_get_args());
1789 $image = _image_valeurs_trans($im, "fond_transparent-$background_color-$tolerance-$coeff_lissage-$alpha", "png",
1795 $x_i = $image["largeur"];
1796 $y_i = $image["hauteur"];
1798 $im = $image["fichier"];
1799 $dest = $image["fichier_dest"];
1801 $creer = $image["creer"];
1804 $bg = _couleur_hex_to_dec($background_color);
1806 $bg_g = $bg['green'];
1807 $bg_b = $bg['blue'];
1809 // Creation de l'image en deux temps
1810 // de facon a conserver les GIF transparents
1811 $im = $image["fonction_imagecreatefrom"]($im);
1812 imagepalettetotruecolor($im);
1813 $im2 = imagecreatetruecolor($x_i, $y_i);
1814 @imagealphablending
($im2, false);
1815 @imagesavealpha
($im2, true);
1816 $color_t = ImageColorAllocateAlpha($im2, 255, 255, 255, 127);
1817 imagefill($im2, 0, 0, $color_t);
1818 imagecopy($im2, $im, 0, 0, 0, 0, $x_i, $y_i);
1820 $im_ = imagecreatetruecolor($x_i, $y_i);
1821 imagealphablending($im_, false);
1822 imagesavealpha($im_, true);
1823 $color_f = ImageColorAllocateAlpha($im_, 255, 255, 255, $alpha);
1825 for ($x = 0; $x < $x_i; $x++
) {
1826 for ($y = 0; $y < $y_i; $y++
) {
1827 $rgb = ImageColorAt($im2, $x, $y);
1828 $r = ($rgb >> 16) & 0xFF;
1829 $g = ($rgb >> 8) & 0xFF;
1831 if ((($d = abs($r - $bg_r) +
abs($g - $bg_g) +
abs($b - $bg_b)) <= $tolerance)) {
1832 imagesetpixel($im_, $x, $y, $color_f);
1833 } elseif ($tolerance and $d <= ($coeff_lissage +
1) * $tolerance) {
1834 $transp = round($alpha * (1 - ($d - $tolerance) / ($coeff_lissage * $tolerance)));
1835 $color_p = ImageColorAllocateAlpha($im_, $r, $g, $b, $transp);
1836 imagesetpixel($im_, $x, $y, $color_p);
1838 imagesetpixel($im_, $x, $y, $rgb);
1842 _image_gd_output($im_, $image);
1848 return _image_ecrire_tag($image, array('src' => $dest));