1 | <?php |
---|
2 | /***************************************************************************\ |
---|
3 | * SPIP, Systeme de publication pour l'internet * |
---|
4 | * * |
---|
5 | * Copyright (c) 2001-2015 * |
---|
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 | * @package SPIP\FiltresImages\ImagesTransforme |
---|
19 | */ |
---|
20 | |
---|
21 | if (!defined('_ECRIRE_INC_VERSION')) { |
---|
22 | return; |
---|
23 | } |
---|
24 | |
---|
25 | // librairie de base du core |
---|
26 | include_spip('inc/filtres_images_mini'); |
---|
27 | |
---|
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 | // http://code.spip.net/@image_aplatir |
---|
36 | // 3/ $transparence a "true" permet de conserver la transparence (utile pour conversion GIF) |
---|
37 | // http://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') { |
---|
43 | $qualite = 0; |
---|
44 | } else { |
---|
45 | $qualite = 128; |
---|
46 | } |
---|
47 | } |
---|
48 | $fonction = array('image_aplatir', func_get_args()); |
---|
49 | $image = _image_valeurs_trans($im, "aplatir-$format-$coul-$qualite-$transparence", $format, $fonction); |
---|
50 | |
---|
51 | if (!$image) { |
---|
52 | return (""); |
---|
53 | } |
---|
54 | |
---|
55 | include_spip('inc/filtres'); |
---|
56 | $couleurs = _couleur_hex_to_dec($coul); |
---|
57 | $dr = $couleurs["red"]; |
---|
58 | $dv = $couleurs["green"]; |
---|
59 | $db = $couleurs["blue"]; |
---|
60 | |
---|
61 | $x_i = $image["largeur"]; |
---|
62 | $y_i = $image["hauteur"]; |
---|
63 | |
---|
64 | $im = $image["fichier"]; |
---|
65 | $dest = $image["fichier_dest"]; |
---|
66 | |
---|
67 | $creer = $image["creer"]; |
---|
68 | |
---|
69 | if ($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); |
---|
81 | } |
---|
82 | @ImageCopyResampled($im_, $im, 0, 0, 0, 0, $x_i, $y_i, $x_i, $y_i); |
---|
83 | imagedestroy($im); |
---|
84 | $im = $im_; |
---|
85 | } |
---|
86 | |
---|
87 | // allouer la couleur de fond |
---|
88 | if ($transparence) { |
---|
89 | @imagealphablending($im_, false); |
---|
90 | @imagesavealpha($im_, true); |
---|
91 | $color_t = imagecolorallocatealpha($im_, $dr, $dv, $db, 127); |
---|
92 | } else { |
---|
93 | $color_t = ImageColorAllocate($im_, $dr, $dv, $db); |
---|
94 | } |
---|
95 | |
---|
96 | imagefill($im_, 0, 0, $color_t); |
---|
97 | |
---|
98 | //?? |
---|
99 | //$dist = abs($trait); |
---|
100 | |
---|
101 | $transp_x = false; |
---|
102 | |
---|
103 | if ($image["format_source"] == "jpg") { |
---|
104 | $im_ = &$im; |
---|
105 | } else { |
---|
106 | for ($x = 0; $x < $x_i; $x++) { |
---|
107 | for ($y = 0; $y < $y_i; $y++) { |
---|
108 | |
---|
109 | $rgb = ImageColorAt($im, $x, $y); |
---|
110 | $a = ($rgb >> 24) & 0xFF; |
---|
111 | $r = ($rgb >> 16) & 0xFF; |
---|
112 | $g = ($rgb >> 8) & 0xFF; |
---|
113 | $b = $rgb & 0xFF; |
---|
114 | |
---|
115 | $a = (127-$a)/127; |
---|
116 | |
---|
117 | if ($a == 1) { // Limiter calculs |
---|
118 | $r = $r; |
---|
119 | $g = $g; |
---|
120 | $b = $b; |
---|
121 | } else { |
---|
122 | if ($a == 0) { // Limiter calculs |
---|
123 | $r = $dr; |
---|
124 | $g = $dv; |
---|
125 | $b = $db; |
---|
126 | |
---|
127 | $transp_x = $x; // Memoriser un point transparent |
---|
128 | $transp_y = $y; |
---|
129 | |
---|
130 | } else { |
---|
131 | $r = round($a*$r+$dr*(1-$a)); |
---|
132 | $g = round($a*$g+$dv*(1-$a)); |
---|
133 | $b = round($a*$b+$db*(1-$a)); |
---|
134 | } |
---|
135 | } |
---|
136 | $a = (1-$a)*127; |
---|
137 | $color = ImageColorAllocateAlpha($im_, $r, $g, $b, $a); |
---|
138 | imagesetpixel($im_, $x, $y, $color); |
---|
139 | } |
---|
140 | } |
---|
141 | } |
---|
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) |
---|
146 | if ($im === $im_) { |
---|
147 | $im = imagecreatetruecolor($x_i, $y_i); |
---|
148 | } |
---|
149 | |
---|
150 | @imagetruecolortopalette($im, true, $qualite); |
---|
151 | |
---|
152 | |
---|
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); |
---|
160 | } |
---|
161 | |
---|
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); |
---|
166 | } |
---|
167 | } |
---|
168 | |
---|
169 | |
---|
170 | // produire le resultat |
---|
171 | _image_gd_output($im, $image, $qualite); |
---|
172 | } else { |
---|
173 | _image_gd_output($im_, $image, $qualite); |
---|
174 | } |
---|
175 | if ($im !== $im_) { |
---|
176 | imagedestroy($im); |
---|
177 | } |
---|
178 | imagedestroy($im_); |
---|
179 | } |
---|
180 | |
---|
181 | return _image_ecrire_tag($image, array('src' => $dest)); |
---|
182 | } |
---|
183 | |
---|
184 | |
---|
185 | // Enregistrer une image dans un format donne |
---|
186 | // (conserve la transparence gif, png, ico) |
---|
187 | // utilise [->@image_aplatir] |
---|
188 | // http://code.spip.net/@image_format |
---|
189 | function image_format($img, $format = 'png') { |
---|
190 | $qualite = null; |
---|
191 | if ($format == 'png8') { |
---|
192 | $format = 'png'; |
---|
193 | $qualite = 128; |
---|
194 | } |
---|
195 | |
---|
196 | return image_aplatir($img, $format, 'cccccc', $qualite, true); |
---|
197 | } |
---|
198 | |
---|
199 | |
---|
200 | // Transforme l'image en PNG transparent |
---|
201 | // alpha = 0: aucune transparence |
---|
202 | // alpha = 127: completement transparent |
---|
203 | // http://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); |
---|
207 | if (!$image) { |
---|
208 | return (""); |
---|
209 | } |
---|
210 | |
---|
211 | $x_i = $image["largeur"]; |
---|
212 | $y_i = $image["hauteur"]; |
---|
213 | |
---|
214 | $im = $image["fichier"]; |
---|
215 | $dest = $image["fichier_dest"]; |
---|
216 | |
---|
217 | $creer = $image["creer"]; |
---|
218 | |
---|
219 | if ($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); |
---|
230 | |
---|
231 | $im_ = imagecreatetruecolor($x_i, $y_i); |
---|
232 | imagealphablending($im_, false); |
---|
233 | imagesavealpha($im_, true); |
---|
234 | |
---|
235 | |
---|
236 | for ($x = 0; $x < $x_i; $x++) { |
---|
237 | for ($y = 0; $y < $y_i; $y++) { |
---|
238 | $rgb = ImageColorAt($im2, $x, $y); |
---|
239 | |
---|
240 | if (function_exists('imagecolorallocatealpha')) { |
---|
241 | $a = ($rgb >> 24) & 0xFF; |
---|
242 | $r = ($rgb >> 16) & 0xFF; |
---|
243 | $g = ($rgb >> 8) & 0xFF; |
---|
244 | $b = $rgb & 0xFF; |
---|
245 | |
---|
246 | |
---|
247 | $a_ = $alpha+$a-round($a*$alpha/127); |
---|
248 | $rgb = imagecolorallocatealpha($im_, $r, $g, $b, $a_); |
---|
249 | } |
---|
250 | imagesetpixel($im_, $x, $y, $rgb); |
---|
251 | } |
---|
252 | } |
---|
253 | _image_gd_output($im_, $image); |
---|
254 | imagedestroy($im_); |
---|
255 | imagedestroy($im); |
---|
256 | imagedestroy($im2); |
---|
257 | } |
---|
258 | |
---|
259 | return _image_ecrire_tag($image, array('src' => $dest)); |
---|
260 | } |
---|
261 | |
---|
262 | /** |
---|
263 | * Recadre (rogne) une image en indiquant la taille de la découpe souhaitée |
---|
264 | * |
---|
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. |
---|
267 | * |
---|
268 | * @example |
---|
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})]` |
---|
277 | * |
---|
278 | * @filtre |
---|
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 http://www.spip.net/5786 |
---|
283 | * |
---|
284 | * @param string $im |
---|
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 |
---|
300 | * @return string |
---|
301 | * balise image recadrée |
---|
302 | */ |
---|
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); |
---|
306 | |
---|
307 | if (!$image) { |
---|
308 | return (""); |
---|
309 | } |
---|
310 | |
---|
311 | $x_i = $image["largeur"]; |
---|
312 | $y_i = $image["hauteur"]; |
---|
313 | |
---|
314 | if (_IMG_GD_MAX_PIXELS && $x_i*$y_i > _IMG_GD_MAX_PIXELS) { |
---|
315 | spip_log("image_recadre impossible sur $im : " . $srcWidth*$srcHeight . "pixels"); |
---|
316 | |
---|
317 | // on se rabat sur une reduction CSS |
---|
318 | return _image_tag_changer_taille($im, $width, $height); |
---|
319 | } |
---|
320 | |
---|
321 | // on recadre pour respecter un ratio ? |
---|
322 | // width : "16:9" |
---|
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)) { |
---|
329 | $width = $x_i; |
---|
330 | $height = $hm; |
---|
331 | } else { |
---|
332 | $width = $ym; |
---|
333 | $height = $y_i; |
---|
334 | } |
---|
335 | } |
---|
336 | |
---|
337 | if ($width == 0) { |
---|
338 | $width = $x_i; |
---|
339 | } |
---|
340 | if ($height == 0) { |
---|
341 | $height = $y_i; |
---|
342 | } |
---|
343 | |
---|
344 | $offset_width = $x_i-$width; |
---|
345 | $offset_height = $y_i-$height; |
---|
346 | $position = strtolower($position); |
---|
347 | |
---|
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); |
---|
353 | if ($positionner) { |
---|
354 | $position = $positionner($im, $width, $height); |
---|
355 | } |
---|
356 | } |
---|
357 | } |
---|
358 | |
---|
359 | if (strpos($position, 'left') !== false) { |
---|
360 | if (preg_match(';left=(\d{1}\d+);', $position, $left)) { |
---|
361 | $offset_width = $left[1]; |
---|
362 | } else { |
---|
363 | $offset_width = 0; |
---|
364 | } |
---|
365 | } elseif (strpos($position, 'right') !== false) { |
---|
366 | $offset_width = $offset_width; |
---|
367 | } else { |
---|
368 | $offset_width = intval(ceil($offset_width/2)); |
---|
369 | } |
---|
370 | |
---|
371 | if (strpos($position, 'top') !== false) { |
---|
372 | if (preg_match(';top=(\d{1}\d+);', $position, $top)) { |
---|
373 | $offset_height = $top[1]; |
---|
374 | } else { |
---|
375 | $offset_height = 0; |
---|
376 | } |
---|
377 | } elseif (strpos($position, 'bottom') !== false) { |
---|
378 | $offset_height = $offset_height; |
---|
379 | } else { |
---|
380 | $offset_height = intval(ceil($offset_height/2)); |
---|
381 | } |
---|
382 | |
---|
383 | $im = $image["fichier"]; |
---|
384 | $dest = $image["fichier_dest"]; |
---|
385 | |
---|
386 | $creer = $image["creer"]; |
---|
387 | |
---|
388 | if ($creer) { |
---|
389 | $im = $image["fonction_imagecreatefrom"]($im); |
---|
390 | imagepalettetotruecolor($im); |
---|
391 | $im_ = imagecreatetruecolor($width, $height); |
---|
392 | @imagealphablending($im_, false); |
---|
393 | @imagesavealpha($im_, true); |
---|
394 | |
---|
395 | if ($background_color == 'transparent') { |
---|
396 | $color_t = imagecolorallocatealpha($im_, 255, 255, 255, 127); |
---|
397 | } else { |
---|
398 | $bg = _couleur_hex_to_dec($background_color); |
---|
399 | $color_t = imagecolorallocate($im_, $bg['red'], $bg['green'], $bg['blue']); |
---|
400 | } |
---|
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)); |
---|
404 | |
---|
405 | _image_gd_output($im_, $image); |
---|
406 | imagedestroy($im_); |
---|
407 | imagedestroy($im); |
---|
408 | } |
---|
409 | |
---|
410 | return _image_ecrire_tag($image, array('src' => $dest, 'width' => $width, 'height' => $height)); |
---|
411 | } |
---|
412 | |
---|
413 | |
---|
414 | /** |
---|
415 | * Recadrer une image dans le rectangle le plus petit possible sans perte |
---|
416 | * de pixels non transparent |
---|
417 | * |
---|
418 | * @param string $im |
---|
419 | * @return string |
---|
420 | */ |
---|
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); |
---|
424 | |
---|
425 | if (!$image) { |
---|
426 | return (""); |
---|
427 | } |
---|
428 | |
---|
429 | $width = $image["largeur"]; |
---|
430 | $height = $image["hauteur"]; |
---|
431 | |
---|
432 | $im = $image["fichier"]; |
---|
433 | $dest = $image["fichier_dest"]; |
---|
434 | |
---|
435 | $creer = $image["creer"]; |
---|
436 | if ($creer) { |
---|
437 | $im = $image["fonction_imagecreatefrom"]($im); |
---|
438 | imagepalettetotruecolor($im); |
---|
439 | |
---|
440 | // trouver le rectangle mini qui contient des infos de couleur |
---|
441 | // recherche optimisee qui ne balaye que par zone |
---|
442 | $min_x = $width; |
---|
443 | $min_y = $height; |
---|
444 | $max_y = $max_x = 0; |
---|
445 | $yy = 0; |
---|
446 | while ($yy <= $height/2 AND $max_y <= $min_y) { |
---|
447 | if ($yy < $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); |
---|
454 | break; |
---|
455 | } |
---|
456 | } |
---|
457 | } |
---|
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); |
---|
465 | break; |
---|
466 | } |
---|
467 | } |
---|
468 | } |
---|
469 | $yy++; |
---|
470 | } |
---|
471 | $min_y = min($max_y, $min_y); // tout a 0 aucun pixel trouve |
---|
472 | |
---|
473 | $xx = 0; |
---|
474 | while ($xx <= $width/2 AND $max_x <= $min_x) { |
---|
475 | if ($xx < $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 |
---|
483 | } |
---|
484 | } |
---|
485 | } |
---|
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 |
---|
494 | } |
---|
495 | } |
---|
496 | } |
---|
497 | $xx++; |
---|
498 | } |
---|
499 | $min_x = min($max_x, $min_x); // tout a 0 aucun pixel trouve |
---|
500 | |
---|
501 | $width = $max_x-$min_x+1; |
---|
502 | $height = $max_y-$min_y+1; |
---|
503 | |
---|
504 | $im_ = imagecreatetruecolor($width, $height); |
---|
505 | @imagealphablending($im_, false); |
---|
506 | @imagesavealpha($im_, true); |
---|
507 | |
---|
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); |
---|
511 | |
---|
512 | _image_gd_output($im_, $image); |
---|
513 | imagedestroy($im_); |
---|
514 | imagedestroy($im); |
---|
515 | } else { |
---|
516 | list ($height, $width) = taille_image($image['fichier_dest']); |
---|
517 | } |
---|
518 | |
---|
519 | return _image_ecrire_tag($image, array('src' => $dest, 'width' => $width, 'height' => $height)); |
---|
520 | } |
---|
521 | |
---|
522 | |
---|
523 | // http://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); |
---|
527 | if (!$image) { |
---|
528 | return (""); |
---|
529 | } |
---|
530 | |
---|
531 | $x_i = $image["largeur"]; |
---|
532 | $y_i = $image["hauteur"]; |
---|
533 | |
---|
534 | $im = $image["fichier"]; |
---|
535 | $dest = $image["fichier_dest"]; |
---|
536 | |
---|
537 | $creer = $image["creer"]; |
---|
538 | |
---|
539 | if ($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); |
---|
545 | |
---|
546 | $color_t = ImageColorAllocateAlpha($im_, 255, 255, 255, 127); |
---|
547 | imagefill($im_, 0, 0, $color_t); |
---|
548 | |
---|
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); |
---|
552 | } |
---|
553 | } |
---|
554 | |
---|
555 | _image_gd_output($im_, $image); |
---|
556 | imagedestroy($im_); |
---|
557 | imagedestroy($im); |
---|
558 | } |
---|
559 | |
---|
560 | return _image_ecrire_tag($image, array('src' => $dest)); |
---|
561 | } |
---|
562 | |
---|
563 | // http://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); |
---|
567 | if (!$image) { |
---|
568 | return (""); |
---|
569 | } |
---|
570 | |
---|
571 | $x_i = $image["largeur"]; |
---|
572 | $y_i = $image["hauteur"]; |
---|
573 | |
---|
574 | $im = $image["fichier"]; |
---|
575 | $dest = $image["fichier_dest"]; |
---|
576 | |
---|
577 | $creer = $image["creer"]; |
---|
578 | |
---|
579 | if ($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); |
---|
585 | |
---|
586 | $color_t = ImageColorAllocateAlpha($im_, 255, 255, 255, 127); |
---|
587 | imagefill($im_, 0, 0, $color_t); |
---|
588 | |
---|
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); |
---|
592 | } |
---|
593 | } |
---|
594 | _image_gd_output($im_, $image); |
---|
595 | imagedestroy($im_); |
---|
596 | imagedestroy($im); |
---|
597 | } |
---|
598 | |
---|
599 | return _image_ecrire_tag($image, array('src' => $dest)); |
---|
600 | } |
---|
601 | |
---|
602 | // http://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%. |
---|
609 | // |
---|
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. |
---|
612 | // |
---|
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 |
---|
616 | // |
---|
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) |
---|
620 | // |
---|
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 |
---|
635 | |
---|
636 | $mode = "masque"; |
---|
637 | |
---|
638 | $numargs = func_num_args(); |
---|
639 | $arg_list = func_get_args(); |
---|
640 | $variable = array(); |
---|
641 | |
---|
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; |
---|
649 | } |
---|
650 | } |
---|
651 | if (isset($defini["mode"]) and $defini["mode"]) { |
---|
652 | $mode = $variable["mode"]; |
---|
653 | } |
---|
654 | |
---|
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); |
---|
659 | if (!$mask) { |
---|
660 | return (""); |
---|
661 | } |
---|
662 | $masque = $mask['fichier']; |
---|
663 | |
---|
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); |
---|
667 | if (!$image) { |
---|
668 | return (""); |
---|
669 | } |
---|
670 | |
---|
671 | $x_i = $image["largeur"]; |
---|
672 | $y_i = $image["hauteur"]; |
---|
673 | |
---|
674 | $im = $image["fichier"]; |
---|
675 | $dest = $image["fichier_dest"]; |
---|
676 | |
---|
677 | $creer = $image["creer"]; |
---|
678 | |
---|
679 | // doit-on positionner l'image ? |
---|
680 | $placer = false; |
---|
681 | foreach (array("right", "left", "bottom", "top", "text-align", "vertical-align") as $pl) { |
---|
682 | if (isset($defini[$pl]) and $defini[$pl]) { |
---|
683 | $placer = true; |
---|
684 | break; |
---|
685 | } |
---|
686 | } |
---|
687 | |
---|
688 | if ($creer) { |
---|
689 | |
---|
690 | $im_m = $mask["fichier"]; |
---|
691 | $x_m = $mask["largeur"]; |
---|
692 | $y_m = $mask["hauteur"]; |
---|
693 | |
---|
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); |
---|
702 | } |
---|
703 | @imagealphablending($im2_, false); |
---|
704 | @imagesavealpha($im2_, true); |
---|
705 | @ImageCopyResampled($im2_, $im2, 0, 0, 0, 0, $x_m, $y_m, $x_m, $y_m); |
---|
706 | imagedestroy($im2); |
---|
707 | $im2 = $im2_; |
---|
708 | } |
---|
709 | |
---|
710 | if ($placer) { |
---|
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 |
---|
715 | |
---|
716 | $dx = 0; |
---|
717 | $dy = 0; |
---|
718 | |
---|
719 | if (isset($defini["right"]) and $defini["right"]) { |
---|
720 | $right = $variable["right"]; |
---|
721 | $dx = ($x_i-$x_m)-$right; |
---|
722 | } |
---|
723 | if (isset($defini["bottom"]) and $defini["bottom"]) { |
---|
724 | $bottom = $variable["bottom"]; |
---|
725 | $dy = ($y_i-$y_m)-$bottom; |
---|
726 | } |
---|
727 | if (isset($defini["top"]) and $defini["top"]) { |
---|
728 | $top = $variable["top"]; |
---|
729 | $dy = $top; |
---|
730 | } |
---|
731 | if (isset($defini["left"]) and $defini["left"]) { |
---|
732 | $left = $variable["left"]; |
---|
733 | $dx = $left; |
---|
734 | } |
---|
735 | if (isset($defini["text-align"]) and $defini["text-align"]) { |
---|
736 | $align = $variable["text-align"]; |
---|
737 | if ($align == "right") { |
---|
738 | $right = 0; |
---|
739 | $dx = ($x_i-$x_m); |
---|
740 | } else { |
---|
741 | if ($align == "left") { |
---|
742 | $left = 0; |
---|
743 | $dx = 0; |
---|
744 | } else { |
---|
745 | if ($align = "center") { |
---|
746 | $dx = round(($x_i-$x_m)/2); |
---|
747 | } |
---|
748 | } |
---|
749 | } |
---|
750 | } |
---|
751 | if (isset($defini["vertical-align"]) and $defini["vertical-align"]) { |
---|
752 | $valign = $variable["vertical-align"]; |
---|
753 | if ($valign == "bottom") { |
---|
754 | $bottom = 0; |
---|
755 | $dy = ($y_i-$y_m); |
---|
756 | } else { |
---|
757 | if ($valign == "top") { |
---|
758 | $top = 0; |
---|
759 | $dy = 0; |
---|
760 | } else { |
---|
761 | if ($valign = "middle") { |
---|
762 | $dy = round(($y_i-$y_m)/2); |
---|
763 | } |
---|
764 | } |
---|
765 | } |
---|
766 | } |
---|
767 | |
---|
768 | |
---|
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); |
---|
774 | } else { |
---|
775 | $color_t = ImageColorAllocateAlpha($im3, 128, 128, 128, 127); |
---|
776 | } |
---|
777 | imagefill($im3, 0, 0, $color_t); |
---|
778 | |
---|
779 | |
---|
780 | imagecopy($im3, $im2, $dx, $dy, 0, 0, $x_m, $y_m); |
---|
781 | |
---|
782 | imagedestroy($im2); |
---|
783 | $im2 = imagecreatetruecolor($x_i, $y_i); |
---|
784 | @imagealphablending($im2, false); |
---|
785 | @imagesavealpha($im2, true); |
---|
786 | |
---|
787 | imagecopy($im2, $im3, 0, 0, 0, 0, $x_i, $y_i); |
---|
788 | imagedestroy($im3); |
---|
789 | $x_m = $x_i; |
---|
790 | $y_m = $y_i; |
---|
791 | } |
---|
792 | |
---|
793 | |
---|
794 | $rapport = $x_i/$x_m; |
---|
795 | if (($y_i/$y_m) < $rapport) { |
---|
796 | $rapport = $y_i/$y_m; |
---|
797 | } |
---|
798 | |
---|
799 | $x_d = ceil($x_i/$rapport); |
---|
800 | $y_d = ceil($y_i/$rapport); |
---|
801 | |
---|
802 | |
---|
803 | if ($x_i < $x_m OR $y_i < $y_m) { |
---|
804 | $x_dest = $x_i; |
---|
805 | $y_dest = $y_i; |
---|
806 | $x_dec = 0; |
---|
807 | $y_dec = 0; |
---|
808 | } else { |
---|
809 | $x_dest = $x_m; |
---|
810 | $y_dest = $y_m; |
---|
811 | $x_dec = round(($x_d-$x_m)/2); |
---|
812 | $y_dec = round(($y_d-$y_m)/2); |
---|
813 | } |
---|
814 | |
---|
815 | |
---|
816 | $nouveau = _image_valeurs_trans(image_reduire($im, $x_d, $y_d), ""); |
---|
817 | if (!is_array($nouveau)) { |
---|
818 | return (""); |
---|
819 | } |
---|
820 | $im_n = $nouveau["fichier"]; |
---|
821 | |
---|
822 | |
---|
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); |
---|
832 | } |
---|
833 | @imagealphablending($im_, false); |
---|
834 | @imagesavealpha($im_, true); |
---|
835 | @ImageCopyResampled($im_, $im, 0, 0, 0, 0, $x_dest, $y_dest, $x_dest, $y_dest); |
---|
836 | imagedestroy($im); |
---|
837 | $im = $im_; |
---|
838 | } |
---|
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); |
---|
844 | |
---|
845 | |
---|
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; |
---|
853 | $b = $rgb & 0xFF; |
---|
854 | |
---|
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; |
---|
859 | $b2 = $rgb2 & 0xFF; |
---|
860 | |
---|
861 | if ($mode == "normal") { |
---|
862 | $v = (127-$a)/127; |
---|
863 | if ($v == 1) { |
---|
864 | $r_ = $r; |
---|
865 | $g_ = $g; |
---|
866 | $b_ = $b; |
---|
867 | } else { |
---|
868 | $v2 = (127-$a2)/127; |
---|
869 | if ($v+$v2 == 0) { |
---|
870 | $r_ = $r2; |
---|
871 | $g_ = $g2; |
---|
872 | $b_ = $b2; |
---|
873 | } else { |
---|
874 | if ($v2 == 0) { |
---|
875 | $r_ = $r; |
---|
876 | $g_ = $g; |
---|
877 | $b_ = $b; |
---|
878 | } else { |
---|
879 | if ($v == 0) { |
---|
880 | $r_ = $r2; |
---|
881 | $g_ = $g2; |
---|
882 | $b_ = $b2; |
---|
883 | } else { |
---|
884 | $r_ = $r+(($r2-$r)*$v2*(1-$v)); |
---|
885 | $g_ = $g+(($g2-$g)*$v2*(1-$v)); |
---|
886 | $b_ = $b+(($b2-$b)*$v2*(1-$v)); |
---|
887 | } |
---|
888 | } |
---|
889 | } |
---|
890 | } |
---|
891 | $a_ = min($a, $a2); |
---|
892 | |
---|
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") { |
---|
899 | $r = abs($r-$r2); |
---|
900 | $g = abs($g-$g2); |
---|
901 | $b = abs($b-$b2); |
---|
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); |
---|
914 | } |
---|
915 | $r = max(0, min($r, 255)); |
---|
916 | $g = max(0, min($g, 255)); |
---|
917 | $b = max(0, min($b, 255)); |
---|
918 | |
---|
919 | // melange en fonction de la transparence du masque |
---|
920 | $v = (127-$a)/127; |
---|
921 | if ($v == 1) { // melange complet |
---|
922 | $r_ = $r; |
---|
923 | $g_ = $g; |
---|
924 | $b_ = $b; |
---|
925 | } else { |
---|
926 | $v2 = (127-$a2)/127; |
---|
927 | if ($v+$v2 == 0) { // ?? |
---|
928 | $r_ = $r2; |
---|
929 | $g_ = $g2; |
---|
930 | $b_ = $b2; |
---|
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)); |
---|
935 | } |
---|
936 | } |
---|
937 | $a_ = $a2; |
---|
938 | |
---|
939 | } elseif ($mode == "eclaircir" OR $mode == "obscurcir") { |
---|
940 | $v = (127-$a)/127; |
---|
941 | if ($v == 1) { |
---|
942 | $r_ = $r; |
---|
943 | $g_ = $g; |
---|
944 | $b_ = $b; |
---|
945 | } else { |
---|
946 | $v2 = (127-$a2)/127; |
---|
947 | if ($v+$v2 == 0) { |
---|
948 | $r_ = $r2; |
---|
949 | $g_ = $g2; |
---|
950 | $b_ = $b2; |
---|
951 | } else { |
---|
952 | $r_ = $r+(($r2-$r)*$v2*(1-$v)); |
---|
953 | $g_ = $g+(($g2-$g)*$v2*(1-$v)); |
---|
954 | $b_ = $b+(($b2-$b)*$v2*(1-$v)); |
---|
955 | } |
---|
956 | } |
---|
957 | if ($mode == "eclaircir") { |
---|
958 | $r_ = max($r_, $r2); |
---|
959 | $g_ = max($g_, $g2); |
---|
960 | $b_ = max($b_, $b2); |
---|
961 | } else { |
---|
962 | $r_ = min($r_, $r2); |
---|
963 | $g_ = min($g_, $g2); |
---|
964 | $b_ = min($b_, $b2); |
---|
965 | } |
---|
966 | $a_ = min($a, $a2); |
---|
967 | |
---|
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 |
---|
971 | $h = $hsv["h"]; |
---|
972 | $s = $hsv["s"]; |
---|
973 | $v = $hsv["v"]; |
---|
974 | $hsv2 = _couleur_rgb2hsv($r2, $g2, $b2); // image en dessous |
---|
975 | $h2 = $hsv2["h"]; |
---|
976 | $s2 = $hsv2["s"]; |
---|
977 | $v2 = $hsv2["v"]; |
---|
978 | switch ($mode) { |
---|
979 | case "teinte"; |
---|
980 | $rgb3 = _couleur_hsv2rgb($h, $s2, $v2); |
---|
981 | break; |
---|
982 | case "saturation"; |
---|
983 | $rgb3 = _couleur_hsv2rgb($h2, $s, $v2); |
---|
984 | break; |
---|
985 | case "valeur"; |
---|
986 | $rgb3 = _couleur_hsv2rgb($h2, $s2, $v); |
---|
987 | break; |
---|
988 | } |
---|
989 | $r = $rgb3["r"]; |
---|
990 | $g = $rgb3["g"]; |
---|
991 | $b = $rgb3["b"]; |
---|
992 | |
---|
993 | // melange en fonction de la transparence du masque |
---|
994 | $v = (127-$a)/127; |
---|
995 | if ($v == 1) { // melange complet |
---|
996 | $r_ = $r; |
---|
997 | $g_ = $g; |
---|
998 | $b_ = $b; |
---|
999 | } else { |
---|
1000 | $v2 = (127-$a2)/127; |
---|
1001 | if ($v+$v2 == 0) { // ?? |
---|
1002 | $r_ = $r2; |
---|
1003 | $g_ = $g2; |
---|
1004 | $b_ = $b2; |
---|
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)); |
---|
1009 | } |
---|
1010 | } |
---|
1011 | $a_ = $a2; |
---|
1012 | |
---|
1013 | } else { |
---|
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); |
---|
1021 | } |
---|
1022 | |
---|
1023 | $color = ImageColorAllocateAlpha($im_, $r_, $g_, $b_, $a_); |
---|
1024 | imagesetpixel($im_, $x, $y, $color); |
---|
1025 | } |
---|
1026 | } |
---|
1027 | |
---|
1028 | _image_gd_output($im_, $image); |
---|
1029 | imagedestroy($im_); |
---|
1030 | imagedestroy($im); |
---|
1031 | imagedestroy($im2); |
---|
1032 | |
---|
1033 | } |
---|
1034 | $x_dest = largeur($dest); |
---|
1035 | $y_dest = hauteur($dest); |
---|
1036 | |
---|
1037 | return _image_ecrire_tag($image, array('src' => $dest, 'width' => $x_dest, 'height' => $y_dest)); |
---|
1038 | } |
---|
1039 | |
---|
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 | // http://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); |
---|
1048 | if (!$image) { |
---|
1049 | return (""); |
---|
1050 | } |
---|
1051 | |
---|
1052 | $x_i = $image["largeur"]; |
---|
1053 | $y_i = $image["hauteur"]; |
---|
1054 | |
---|
1055 | $im = $image["fichier"]; |
---|
1056 | $dest = $image["fichier_dest"]; |
---|
1057 | |
---|
1058 | $creer = $image["creer"]; |
---|
1059 | |
---|
1060 | // Methode precise |
---|
1061 | // resultat plus beau, mais tres lourd |
---|
1062 | // Et: indispensable pour preserver transparence! |
---|
1063 | |
---|
1064 | if ($creer) { |
---|
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); |
---|
1075 | |
---|
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; |
---|
1082 | $b = $rgb & 0xFF; |
---|
1083 | |
---|
1084 | $c = round(($val_r*$r/1000)+($val_g*$g/1000)+($val_b*$b/1000)); |
---|
1085 | if ($c < 0) { |
---|
1086 | $c = 0; |
---|
1087 | } |
---|
1088 | if ($c > 254) { |
---|
1089 | $c = 254; |
---|
1090 | } |
---|
1091 | |
---|
1092 | |
---|
1093 | $color = ImageColorAllocateAlpha($im_, $c, $c, $c, $a); |
---|
1094 | imagesetpixel($im_, $x, $y, $color); |
---|
1095 | } |
---|
1096 | } |
---|
1097 | _image_gd_output($im_, $image); |
---|
1098 | imagedestroy($im_); |
---|
1099 | imagedestroy($im); |
---|
1100 | } |
---|
1101 | |
---|
1102 | return _image_ecrire_tag($image, array('src' => $dest)); |
---|
1103 | } |
---|
1104 | |
---|
1105 | // http://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 |
---|
1110 | $coeffs = array( |
---|
1111 | array(1), |
---|
1112 | array(1, 1), |
---|
1113 | array(1, 2, 1), |
---|
1114 | array(1, 3, 3, 1), |
---|
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) |
---|
1123 | ); |
---|
1124 | |
---|
1125 | $fonction = array('image_flou', func_get_args()); |
---|
1126 | $image = _image_valeurs_trans($im, "flou-$niveau", false, $fonction); |
---|
1127 | if (!$image) { |
---|
1128 | return (""); |
---|
1129 | } |
---|
1130 | |
---|
1131 | $x_i = $image["largeur"]; |
---|
1132 | $y_i = $image["hauteur"]; |
---|
1133 | $sum = pow(2, $niveau); |
---|
1134 | |
---|
1135 | $im = $image["fichier"]; |
---|
1136 | $dest = $image["fichier_dest"]; |
---|
1137 | |
---|
1138 | $creer = $image["creer"]; |
---|
1139 | |
---|
1140 | // Methode precise |
---|
1141 | // resultat plus beau, mais tres lourd |
---|
1142 | // Et: indispensable pour preserver transparence! |
---|
1143 | |
---|
1144 | if ($creer) { |
---|
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); |
---|
1151 | |
---|
1152 | @imagealphablending($temp1, false); |
---|
1153 | @imagesavealpha($temp1, true); |
---|
1154 | @imagealphablending($temp2, false); |
---|
1155 | @imagesavealpha($temp2, true); |
---|
1156 | |
---|
1157 | |
---|
1158 | for ($i = 0; $i < $x_i+$niveau; $i++) { |
---|
1159 | for ($j = 0; $j < $y_i; $j++) { |
---|
1160 | $suma = 0; |
---|
1161 | $sumr = 0; |
---|
1162 | $sumg = 0; |
---|
1163 | $sumb = 0; |
---|
1164 | $sum = 0; |
---|
1165 | $sum_ = 0; |
---|
1166 | for ($k = 0; $k <= $niveau; ++$k) { |
---|
1167 | $color = imagecolorat($im, $i_ = ($i-$niveau)+$k, $j); |
---|
1168 | |
---|
1169 | $a = ($color >> 24) & 0xFF; |
---|
1170 | $r = ($color >> 16) & 0xFF; |
---|
1171 | $g = ($color >> 8) & 0xFF; |
---|
1172 | $b = ($color) & 0xFF; |
---|
1173 | |
---|
1174 | if ($i_ < 0 OR $i_ >= $x_i) { |
---|
1175 | $a = 127; |
---|
1176 | } |
---|
1177 | |
---|
1178 | $coef = $coeffs[$niveau][$k]; |
---|
1179 | $suma += $a*$coef; |
---|
1180 | $ac = ((127-$a)/127); |
---|
1181 | |
---|
1182 | $ac = $ac*$ac; |
---|
1183 | |
---|
1184 | $sumr += $r*$coef*$ac; |
---|
1185 | $sumg += $g*$coef*$ac; |
---|
1186 | $sumb += $b*$coef*$ac; |
---|
1187 | $sum += $coef*$ac; |
---|
1188 | $sum_ += $coef; |
---|
1189 | } |
---|
1190 | if ($sum > 0) { |
---|
1191 | $color = ImageColorAllocateAlpha($temp1, $sumr/$sum, $sumg/$sum, $sumb/$sum, $suma/$sum_); |
---|
1192 | } else { |
---|
1193 | $color = ImageColorAllocateAlpha($temp1, 255, 255, 255, 127); |
---|
1194 | } |
---|
1195 | imagesetpixel($temp1, $i, $j, $color); |
---|
1196 | } |
---|
1197 | } |
---|
1198 | imagedestroy($im); |
---|
1199 | for ($i = 0; $i < $x_i+$niveau; $i++) { |
---|
1200 | for ($j = 0; $j < $y_i+$niveau; $j++) { |
---|
1201 | $suma = 0; |
---|
1202 | $sumr = 0; |
---|
1203 | $sumg = 0; |
---|
1204 | $sumb = 0; |
---|
1205 | $sum = 0; |
---|
1206 | $sum_ = 0; |
---|
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) { |
---|
1214 | $a = 127; |
---|
1215 | } |
---|
1216 | |
---|
1217 | $suma += $a*$coeffs[$niveau][$k]; |
---|
1218 | $ac = ((127-$a)/127); |
---|
1219 | |
---|
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]; |
---|
1225 | |
---|
1226 | } |
---|
1227 | if ($sum > 0) { |
---|
1228 | $color = ImageColorAllocateAlpha($temp2, $sumr/$sum, $sumg/$sum, $sumb/$sum, $suma/$sum_); |
---|
1229 | } else { |
---|
1230 | $color = ImageColorAllocateAlpha($temp2, 255, 255, 255, 127); |
---|
1231 | } |
---|
1232 | imagesetpixel($temp2, $i, $j, $color); |
---|
1233 | } |
---|
1234 | } |
---|
1235 | |
---|
1236 | _image_gd_output($temp2, $image); |
---|
1237 | imagedestroy($temp1); |
---|
1238 | imagedestroy($temp2); |
---|
1239 | } |
---|
1240 | |
---|
1241 | return _image_ecrire_tag($image, array('src' => $dest, 'width' => ($x_i+$niveau), 'height' => ($y_i+$niveau))); |
---|
1242 | } |
---|
1243 | |
---|
1244 | // http://code.spip.net/@image_RotateBicubic |
---|
1245 | function image_RotateBicubic($src_img, $angle, $bicubic = 0) { |
---|
1246 | include_spip('filtres/images_lib'); |
---|
1247 | |
---|
1248 | if (round($angle/90)*90 == $angle) { |
---|
1249 | $droit = true; |
---|
1250 | if (round($angle/180)*180 == $angle) { |
---|
1251 | $rot = 180; |
---|
1252 | } else { |
---|
1253 | $rot = 90; |
---|
1254 | } |
---|
1255 | } else { |
---|
1256 | $droit = false; |
---|
1257 | } |
---|
1258 | |
---|
1259 | // convert degrees to radians |
---|
1260 | $angle = $angle+180; |
---|
1261 | $angle = deg2rad($angle); |
---|
1262 | |
---|
1263 | |
---|
1264 | $src_x = imagesx($src_img); |
---|
1265 | $src_y = imagesy($src_img); |
---|
1266 | |
---|
1267 | |
---|
1268 | $center_x = floor(($src_x-1)/2); |
---|
1269 | $center_y = floor(($src_y-1)/2); |
---|
1270 | |
---|
1271 | $cosangle = cos($angle); |
---|
1272 | $sinangle = sin($angle); |
---|
1273 | |
---|
1274 | // calculer dimensions en simplifiant angles droits, ce qui evite "floutage" |
---|
1275 | // des rotations a angle droit |
---|
1276 | if (!$droit) { |
---|
1277 | $corners = array(array(0, 0), array($src_x, 0), array($src_x, $src_y), array(0, $src_y)); |
---|
1278 | |
---|
1279 | foreach ($corners as $key => $value) { |
---|
1280 | $value[0] -= $center_x; //Translate coords to center for rotation |
---|
1281 | $value[1] -= $center_y; |
---|
1282 | $temp = array(); |
---|
1283 | $temp[0] = $value[0]*$cosangle+$value[1]*$sinangle; |
---|
1284 | $temp[1] = $value[1]*$cosangle-$value[0]*$sinangle; |
---|
1285 | $corners[$key] = $temp; |
---|
1286 | } |
---|
1287 | |
---|
1288 | $min_x = 1000000000000000; |
---|
1289 | $max_x = -1000000000000000; |
---|
1290 | $min_y = 1000000000000000; |
---|
1291 | $max_y = -1000000000000000; |
---|
1292 | |
---|
1293 | foreach ($corners as $key => $value) { |
---|
1294 | if ($value[0] < $min_x) { |
---|
1295 | $min_x = $value[0]; |
---|
1296 | } |
---|
1297 | if ($value[0] > $max_x) { |
---|
1298 | $max_x = $value[0]; |
---|
1299 | } |
---|
1300 | |
---|
1301 | if ($value[1] < $min_y) { |
---|
1302 | $min_y = $value[1]; |
---|
1303 | } |
---|
1304 | if ($value[1] > $max_y) { |
---|
1305 | $max_y = $value[1]; |
---|
1306 | } |
---|
1307 | } |
---|
1308 | |
---|
1309 | $rotate_width = ceil($max_x-$min_x); |
---|
1310 | $rotate_height = ceil($max_y-$min_y); |
---|
1311 | } else { |
---|
1312 | if ($rot == 180) { |
---|
1313 | $rotate_height = $src_y; |
---|
1314 | $rotate_width = $src_x; |
---|
1315 | } else { |
---|
1316 | $rotate_height = $src_x; |
---|
1317 | $rotate_width = $src_y; |
---|
1318 | } |
---|
1319 | $bicubic = false; |
---|
1320 | } |
---|
1321 | |
---|
1322 | |
---|
1323 | $rotate = imagecreatetruecolor($rotate_width, $rotate_height); |
---|
1324 | imagealphablending($rotate, false); |
---|
1325 | imagesavealpha($rotate, true); |
---|
1326 | |
---|
1327 | $cosangle = cos($angle); |
---|
1328 | $sinangle = sin($angle); |
---|
1329 | |
---|
1330 | // arrondir pour rotations angle droit (car cos et sin dans {-1,0,1}) |
---|
1331 | if ($droit) { |
---|
1332 | $cosangle = round($cosangle); |
---|
1333 | $sinangle = round($sinangle); |
---|
1334 | } |
---|
1335 | |
---|
1336 | $newcenter_x = ($rotate_width-1)/2; |
---|
1337 | $newcenter_y = ($rotate_height-1)/2; |
---|
1338 | |
---|
1339 | |
---|
1340 | for ($y = 0; $y < $rotate_height; $y++) { |
---|
1341 | for ($x = 0; $x < $rotate_width; $x++) { |
---|
1342 | // rotate... |
---|
1343 | $old_x = ((($newcenter_x-$x)*$cosangle+($newcenter_y-$y)*$sinangle)) |
---|
1344 | +$center_x; |
---|
1345 | $old_y = ((($newcenter_y-$y)*$cosangle-($newcenter_x-$x)*$sinangle)) |
---|
1346 | +$center_y; |
---|
1347 | |
---|
1348 | $old_x = ceil($old_x); |
---|
1349 | $old_y = ceil($old_y); |
---|
1350 | |
---|
1351 | if ($old_x >= 0 && $old_x < $src_x |
---|
1352 | && $old_y >= 0 && $old_y < $src_y |
---|
1353 | ) { |
---|
1354 | if ($bicubic == true) { |
---|
1355 | $xo = $old_x; |
---|
1356 | $x0 = floor($xo); |
---|
1357 | $x1 = ceil($xo); |
---|
1358 | $yo = $old_y; |
---|
1359 | $y0 = floor($yo); |
---|
1360 | $y1 = ceil($yo); |
---|
1361 | |
---|
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; |
---|
1367 | $b1 = $rgb & 0xFF; |
---|
1368 | $d1 = _image_distance_pixel($xo, $yo, $x0, $y0); |
---|
1369 | |
---|
1370 | $rgb = ImageColorAt($src_img, $x1, $y0); |
---|
1371 | $a2 = ($rgb >> 24) & 0xFF; |
---|
1372 | $r2 = ($rgb >> 16) & 0xFF; |
---|
1373 | $g2 = ($rgb >> 8) & 0xFF; |
---|
1374 | $b2 = $rgb & 0xFF; |
---|
1375 | $d2 = _image_distance_pixel($xo, $yo, $x1, $y0); |
---|
1376 | |
---|
1377 | $rgb = ImageColorAt($src_img, $x0, $y1); |
---|
1378 | $a3 = ($rgb >> 24) & 0xFF; |
---|
1379 | $r3 = ($rgb >> 16) & 0xFF; |
---|
1380 | $g3 = ($rgb >> 8) & 0xFF; |
---|
1381 | $b3 = $rgb & 0xFF; |
---|
1382 | $d3 = _image_distance_pixel($xo, $yo, $x0, $y1); |
---|
1383 | |
---|
1384 | $rgb = ImageColorAt($src_img, $x1, $y1); |
---|
1385 | $a4 = ($rgb >> 24) & 0xFF; |
---|
1386 | $r4 = ($rgb >> 16) & 0xFF; |
---|
1387 | $g4 = ($rgb >> 8) & 0xFF; |
---|
1388 | $b4 = $rgb & 0xFF; |
---|
1389 | $d4 = _image_distance_pixel($xo, $yo, $x1, $y1); |
---|
1390 | |
---|
1391 | $ac1 = ((127-$a1)/127); |
---|
1392 | $ac2 = ((127-$a2)/127); |
---|
1393 | $ac3 = ((127-$a3)/127); |
---|
1394 | $ac4 = ((127-$a4)/127); |
---|
1395 | |
---|
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) { |
---|
1399 | if ($ac1 > 0) { |
---|
1400 | $d1 = $d1*$ac1; |
---|
1401 | } |
---|
1402 | if ($ac2 > 0) { |
---|
1403 | $d2 = $d2*$ac2; |
---|
1404 | } |
---|
1405 | if ($ac3 > 0) { |
---|
1406 | $d3 = $d3*$ac3; |
---|
1407 | } |
---|
1408 | if ($ac4 > 0) { |
---|
1409 | $d4 = $d4*$ac4; |
---|
1410 | } |
---|
1411 | } |
---|
1412 | |
---|
1413 | $tot = $d1+$d2+$d3+$d4; |
---|
1414 | |
---|
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); |
---|
1420 | } else { |
---|
1421 | $color = imagecolorat($src_img, round($old_x), round($old_y)); |
---|
1422 | } |
---|
1423 | } else { |
---|
1424 | // this line sets the background colour |
---|
1425 | $color = imagecolorallocatealpha($src_img, 255, 255, 255, 127); |
---|
1426 | } |
---|
1427 | @imagesetpixel($rotate, $x, $y, $color); |
---|
1428 | } |
---|
1429 | } |
---|
1430 | |
---|
1431 | return $rotate; |
---|
1432 | } |
---|
1433 | |
---|
1434 | // permet de faire tourner une image d'un angle quelconque |
---|
1435 | // la fonction "crop" n'est pas implementee... |
---|
1436 | // http://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); |
---|
1440 | if (!$image) { |
---|
1441 | return (""); |
---|
1442 | } |
---|
1443 | |
---|
1444 | $im = $image["fichier"]; |
---|
1445 | $dest = $image["fichier_dest"]; |
---|
1446 | |
---|
1447 | $creer = $image["creer"]; |
---|
1448 | |
---|
1449 | if ($creer) { |
---|
1450 | $effectuer_gd = true; |
---|
1451 | |
---|
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; |
---|
1458 | } else { |
---|
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'); |
---|
1463 | } else { |
---|
1464 | @define('_ROTATE_COMMAND', ''); |
---|
1465 | } |
---|
1466 | if (_ROTATE_COMMAND !== '') { |
---|
1467 | $commande = str_replace( |
---|
1468 | array('%t', '%src', '%dest'), |
---|
1469 | array( |
---|
1470 | $angle, |
---|
1471 | escapeshellcmd($im), |
---|
1472 | escapeshellcmd($dest) |
---|
1473 | ), |
---|
1474 | _ROTATE_COMMAND); |
---|
1475 | spip_log($commande); |
---|
1476 | exec($commande); |
---|
1477 | if (file_exists($dest)) // precaution |
---|
1478 | { |
---|
1479 | $effectuer_gd = false; |
---|
1480 | } |
---|
1481 | } |
---|
1482 | } |
---|
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; |
---|
1492 | } |
---|
1493 | } |
---|
1494 | } |
---|
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); |
---|
1502 | imagedestroy($im); |
---|
1503 | } |
---|
1504 | } |
---|
1505 | list ($src_y, $src_x) = taille_image($dest); |
---|
1506 | |
---|
1507 | return _image_ecrire_tag($image, array('src' => $dest, 'width' => $src_x, 'height' => $src_y)); |
---|
1508 | } |
---|
1509 | |
---|
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 | // http://code.spip.net/@image_imagick |
---|
1514 | function image_imagick() { |
---|
1515 | $tous = func_get_args(); |
---|
1516 | $img = $tous[0]; |
---|
1517 | $fonc = $tous[1]; |
---|
1518 | $tous[0] = ""; |
---|
1519 | $tous_var = join($tous, "-"); |
---|
1520 | |
---|
1521 | $fonction = array('image_imagick', func_get_args()); |
---|
1522 | $image = _image_valeurs_trans($img, "$tous_var", "png", $fonction); |
---|
1523 | if (!$image) { |
---|
1524 | return (""); |
---|
1525 | } |
---|
1526 | |
---|
1527 | $im = $image["fichier"]; |
---|
1528 | $dest = $image["fichier_dest"]; |
---|
1529 | |
---|
1530 | $creer = $image["creer"]; |
---|
1531 | |
---|
1532 | if ($creer) { |
---|
1533 | if (function_exists($fonc)) { |
---|
1534 | |
---|
1535 | $handle = imagick_readimage($im); |
---|
1536 | $arr[0] = $handle; |
---|
1537 | for ($i = 2; $i < count($tous); $i++) { |
---|
1538 | $arr[] = $tous[$i]; |
---|
1539 | } |
---|
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)); |
---|
1547 | } |
---|
1548 | } |
---|
1549 | list ($src_y, $src_x) = taille_image($dest); |
---|
1550 | |
---|
1551 | return _image_ecrire_tag($image, array('src' => $dest, 'width' => $src_x, 'height' => $src_y)); |
---|
1552 | |
---|
1553 | } |
---|
1554 | |
---|
1555 | // Permet de rendre une image |
---|
1556 | // plus claire (gamma > 0) |
---|
1557 | // ou plus foncee (gamma < 0) |
---|
1558 | // http://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); |
---|
1563 | if (!$image) { |
---|
1564 | return (""); |
---|
1565 | } |
---|
1566 | |
---|
1567 | $x_i = $image["largeur"]; |
---|
1568 | $y_i = $image["hauteur"]; |
---|
1569 | |
---|
1570 | $im = $image["fichier"]; |
---|
1571 | $dest = $image["fichier_dest"]; |
---|
1572 | |
---|
1573 | $creer = $image["creer"]; |
---|
1574 | |
---|
1575 | if ($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); |
---|
1586 | |
---|
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; |
---|
1593 | $b = $rgb & 0xFF; |
---|
1594 | |
---|
1595 | $r = _image_decale_composante($r, $gamma); |
---|
1596 | $g = _image_decale_composante($g, $gamma); |
---|
1597 | $b = _image_decale_composante($b, $gamma); |
---|
1598 | |
---|
1599 | $color = ImageColorAllocateAlpha($im_, $r, $g, $b, $a); |
---|
1600 | imagesetpixel($im_, $x, $y, $color); |
---|
1601 | } |
---|
1602 | } |
---|
1603 | _image_gd_output($im_, $image); |
---|
1604 | } |
---|
1605 | |
---|
1606 | return _image_ecrire_tag($image, array('src' => $dest)); |
---|
1607 | } |
---|
1608 | |
---|
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 | // http://code.spip.net/@image_sepia |
---|
1614 | function image_sepia($im, $rgb = "896f5e") { |
---|
1615 | include_spip('filtres/images_lib'); |
---|
1616 | |
---|
1617 | if (!function_exists("imagecreatetruecolor")) { |
---|
1618 | return $im; |
---|
1619 | } |
---|
1620 | |
---|
1621 | $couleurs = _couleur_hex_to_dec($rgb); |
---|
1622 | $dr = $couleurs["red"]; |
---|
1623 | $dv = $couleurs["green"]; |
---|
1624 | $db = $couleurs["blue"]; |
---|
1625 | |
---|
1626 | $fonction = array('image_sepia', func_get_args()); |
---|
1627 | $image = _image_valeurs_trans($im, "sepia-$dr-$dv-$db", false, $fonction); |
---|
1628 | if (!$image) { |
---|
1629 | return (""); |
---|
1630 | } |
---|
1631 | |
---|
1632 | $x_i = $image["largeur"]; |
---|
1633 | $y_i = $image["hauteur"]; |
---|
1634 | |
---|
1635 | $im = $image["fichier"]; |
---|
1636 | $dest = $image["fichier_dest"]; |
---|
1637 | |
---|
1638 | $creer = $image["creer"]; |
---|
1639 | |
---|
1640 | if ($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); |
---|
1651 | |
---|
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; |
---|
1658 | $b = $rgb & 0xFF; |
---|
1659 | |
---|
1660 | $r = round(.299*$r+.587*$g+.114*$b); |
---|
1661 | $g = $r; |
---|
1662 | $b = $r; |
---|
1663 | |
---|
1664 | |
---|
1665 | $r = _image_decale_composante_127($r, $dr); |
---|
1666 | $g = _image_decale_composante_127($g, $dv); |
---|
1667 | $b = _image_decale_composante_127($b, $db); |
---|
1668 | |
---|
1669 | $color = ImageColorAllocateAlpha($im_, $r, $g, $b, $a); |
---|
1670 | imagesetpixel($im_, $x, $y, $color); |
---|
1671 | } |
---|
1672 | } |
---|
1673 | _image_gd_output($im_, $image); |
---|
1674 | imagedestroy($im_); |
---|
1675 | imagedestroy($im); |
---|
1676 | } |
---|
1677 | |
---|
1678 | return _image_ecrire_tag($image, array('src' => $dest)); |
---|
1679 | } |
---|
1680 | |
---|
1681 | |
---|
1682 | /** |
---|
1683 | * Renforcer la netteté d'une image |
---|
1684 | * |
---|
1685 | * @param string $im |
---|
1686 | * Code HTML de l'image |
---|
1687 | * @param float $k |
---|
1688 | * Niveau de renforcement (entre 0 et 1) |
---|
1689 | * @return string Code HTML de l'image |
---|
1690 | **/ |
---|
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); |
---|
1694 | if (!$image) { |
---|
1695 | return (""); |
---|
1696 | } |
---|
1697 | |
---|
1698 | $x_i = $image["largeur"]; |
---|
1699 | $y_i = $image["hauteur"]; |
---|
1700 | $im = $image["fichier"]; |
---|
1701 | $dest = $image["fichier_dest"]; |
---|
1702 | $creer = $image["creer"]; |
---|
1703 | |
---|
1704 | if ($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); |
---|
1712 | |
---|
1713 | for ($x = 0; $x < $x_i; $x++) { |
---|
1714 | for ($y = 0; $y < $y_i; $y++) { |
---|
1715 | |
---|
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); |
---|
1721 | |
---|
1722 | if ($x-1 < 0) { |
---|
1723 | $rgb[0][1] = $rgb[1][1]; |
---|
1724 | } |
---|
1725 | if ($y-1 < 0) { |
---|
1726 | $rgb[1][0] = $rgb[1][1]; |
---|
1727 | } |
---|
1728 | if ($x+1 == $x_i) { |
---|
1729 | $rgb[2][1] = $rgb[1][1]; |
---|
1730 | } |
---|
1731 | if ($y+1 == $y_i) { |
---|
1732 | $rgb[1][2] = $rgb[1][1]; |
---|
1733 | } |
---|
1734 | |
---|
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); |
---|
1741 | |
---|
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); |
---|
1747 | |
---|
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); |
---|
1753 | |
---|
1754 | $r = min(255, max(0, $r)); |
---|
1755 | $g = min(255, max(0, $g)); |
---|
1756 | $b = min(255, max(0, $b)); |
---|
1757 | |
---|
1758 | |
---|
1759 | $color = ImageColorAllocateAlpha($im_, $r, $g, $b, $a); |
---|
1760 | imagesetpixel($im_, $x, $y, $color); |
---|
1761 | } |
---|
1762 | } |
---|
1763 | _image_gd_output($im_, $image); |
---|
1764 | } |
---|
1765 | |
---|
1766 | return _image_ecrire_tag($image, array('src' => $dest)); |
---|
1767 | } |
---|
1768 | |
---|
1769 | |
---|
1770 | /** |
---|
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 |
---|
1777 | * |
---|
1778 | * @param string $im |
---|
1779 | * @param string $background_color |
---|
1780 | * @param int $tolerance |
---|
1781 | * @param int $alpha |
---|
1782 | * alpha = 0: aucune transparence |
---|
1783 | * alpha = 127: completement transparent |
---|
1784 | * @param int $coeff_lissage |
---|
1785 | * @return mixed|null|string |
---|
1786 | */ |
---|
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", |
---|
1790 | $fonction); |
---|
1791 | if (!$image) { |
---|
1792 | return (""); |
---|
1793 | } |
---|
1794 | |
---|
1795 | $x_i = $image["largeur"]; |
---|
1796 | $y_i = $image["hauteur"]; |
---|
1797 | |
---|
1798 | $im = $image["fichier"]; |
---|
1799 | $dest = $image["fichier_dest"]; |
---|
1800 | |
---|
1801 | $creer = $image["creer"]; |
---|
1802 | |
---|
1803 | if ($creer) { |
---|
1804 | $bg = _couleur_hex_to_dec($background_color); |
---|
1805 | $bg_r = $bg['red']; |
---|
1806 | $bg_g = $bg['green']; |
---|
1807 | $bg_b = $bg['blue']; |
---|
1808 | |
---|
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); |
---|
1819 | |
---|
1820 | $im_ = imagecreatetruecolor($x_i, $y_i); |
---|
1821 | imagealphablending($im_, false); |
---|
1822 | imagesavealpha($im_, true); |
---|
1823 | $color_f = ImageColorAllocateAlpha($im_, 255, 255, 255, $alpha); |
---|
1824 | |
---|
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; |
---|
1830 | $b = $rgb & 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); |
---|
1837 | } else { |
---|
1838 | imagesetpixel($im_, $x, $y, $rgb); |
---|
1839 | } |
---|
1840 | } |
---|
1841 | } |
---|
1842 | _image_gd_output($im_, $image); |
---|
1843 | imagedestroy($im_); |
---|
1844 | imagedestroy($im); |
---|
1845 | imagedestroy($im2); |
---|
1846 | } |
---|
1847 | |
---|
1848 | return _image_ecrire_tag($image, array('src' => $dest)); |
---|
1849 | } |
---|
1850 | |
---|
1851 | ?> |
---|