function image_gd_output($img, $valeurs, $qualite = _IMG_GD_QUALITE) { include_spip('inc/filtres_images_lib'); return _image_gd_output($img, $valeurs, $qualite); }
/** * Crée si possible une miniature d'une image * * @see _image_valeurs_trans() * @uses _image_ratio() * * @param array $valeurs * Description de l'image, telle que retournée par `_image_valeurs_trans()` * @param int $maxWidth * Largeur maximum en px de la miniature à réaliser * @param int $maxHeight * Hauteur maximum en px de la miniateure à réaliser * @param string $process * Librairie graphique à utiliser (gd1, gd2, netpbm, convert, imagick). * AUTO utilise la librairie sélectionnée dans la configuration. * @param bool $force * @return array|null * Description de l'image, sinon null. **/ function _image_creer_vignette($valeurs, $maxWidth, $maxHeight, $process = 'AUTO', $force = false) { // ordre de preference des formats graphiques pour creer les vignettes // le premier format disponible, selon la methode demandee, est utilise $image = $valeurs['fichier']; $format = $valeurs['format_source']; $destdir = dirname($valeurs['fichier_dest']); $destfile = basename($valeurs['fichier_dest'], "." . $valeurs["format_dest"]); $format_sortie = $valeurs['format_dest']; if ($process == 'AUTO' and isset($GLOBALS['meta']['image_process'])) { $process = $GLOBALS['meta']['image_process']; } // liste des formats qu'on sait lire $img = isset($GLOBALS['meta']['formats_graphiques']) ? strpos($GLOBALS['meta']['formats_graphiques'], $format) !== false : false; // si le doc n'est pas une image, refuser if (!$force and !$img) { return; } $destination = "{$destdir}/{$destfile}"; // calculer la taille if (($srcWidth = $valeurs['largeur']) && ($srcHeight = $valeurs['hauteur'])) { if (!($destWidth = $valeurs['largeur_dest']) || !($destHeight = $valeurs['hauteur_dest'])) { list($destWidth, $destHeight) = _image_ratio($valeurs['largeur'], $valeurs['hauteur'], $maxWidth, $maxHeight); } } elseif ($process == 'convert' or $process == 'imagick') { $destWidth = $maxWidth; $destHeight = $maxHeight; } else { spip_log("echec {$process} sur {$image}"); return; } // Si l'image est de la taille demandee (ou plus petite), simplement la retourner if ($srcWidth and $srcWidth <= $maxWidth and $srcHeight <= $maxHeight) { $vignette = $destination . '.' . $format; @copy($image, $vignette); } elseif ($process == 'convert') { if (!defined('_CONVERT_COMMAND')) { define('_CONVERT_COMMAND', 'convert'); } // Securite : mes_options.php peut preciser le chemin absolu define('_RESIZE_COMMAND', _CONVERT_COMMAND . ' -quality ' . _IMG_CONVERT_QUALITE . ' -resize %xx%y! %src %dest'); $vignette = $destination . "." . $format_sortie; $commande = str_replace(array('%x', '%y', '%src', '%dest'), array($destWidth, $destHeight, escapeshellcmd($image), escapeshellcmd($vignette)), _RESIZE_COMMAND); spip_log($commande); exec($commande); if (!@file_exists($vignette)) { spip_log("echec convert sur {$vignette}"); return; // echec commande } } elseif ($process == 'imagick') { $vignette = "{$destination}." . $format_sortie; if (!class_exists('Imagick')) { spip_log("Classe Imagick absente !", _LOG_ERREUR); return; } $imagick = new Imagick(); $imagick->readImage($image); $imagick->resizeImage($destWidth, $destHeight, Imagick::FILTER_LANCZOS, 1); //, IMAGICK_FILTER_LANCZOS, _IMG_IMAGICK_QUALITE / 100); $imagick->writeImage($vignette); if (!@file_exists($vignette)) { spip_log("echec imagick sur {$vignette}"); return; } } elseif ($process == "netpbm") { if (!defined('_PNMSCALE_COMMAND')) { define('_PNMSCALE_COMMAND', 'pnmscale'); } // Securite : mes_options.php peut preciser le chemin absolu if (_PNMSCALE_COMMAND == '') { return; } $vignette = $destination . "." . $format_sortie; $pnmtojpeg_command = str_replace("pnmscale", "pnmtojpeg", _PNMSCALE_COMMAND); if ($format == "jpg") { $jpegtopnm_command = str_replace("pnmscale", "jpegtopnm", _PNMSCALE_COMMAND); exec("{$jpegtopnm_command} {$image} | " . _PNMSCALE_COMMAND . " -width {$destWidth} | {$pnmtojpeg_command} > {$vignette}"); if (!($s = @filesize($vignette))) { spip_unlink($vignette); } if (!@file_exists($vignette)) { spip_log("echec netpbm-jpg sur {$vignette}"); return; } } else { if ($format == "gif") { $giftopnm_command = str_replace("pnmscale", "giftopnm", _PNMSCALE_COMMAND); exec("{$giftopnm_command} {$image} | " . _PNMSCALE_COMMAND . " -width {$destWidth} | {$pnmtojpeg_command} > {$vignette}"); if (!($s = @filesize($vignette))) { spip_unlink($vignette); } if (!@file_exists($vignette)) { spip_log("echec netpbm-gif sur {$vignette}"); return; } } else { if ($format == "png") { $pngtopnm_command = str_replace("pnmscale", "pngtopnm", _PNMSCALE_COMMAND); exec("{$pngtopnm_command} {$image} | " . _PNMSCALE_COMMAND . " -width {$destWidth} | {$pnmtojpeg_command} > {$vignette}"); if (!($s = @filesize($vignette))) { spip_unlink($vignette); } if (!@file_exists($vignette)) { spip_log("echec netpbm-png sur {$vignette}"); return; } } } } } elseif ($process == 'gd1' or $process == 'gd2') { if (!function_exists('gd_info')) { spip_log("Librairie GD absente !", _LOG_ERREUR); return; } if (_IMG_GD_MAX_PIXELS && $srcWidth * $srcHeight > _IMG_GD_MAX_PIXELS) { spip_log("vignette gd1/gd2 impossible : " . $srcWidth * $srcHeight . "pixels"); return; } $destFormat = $format_sortie; if (!$destFormat) { spip_log("pas de format pour {$image}"); return; } $fonction_imagecreatefrom = $valeurs['fonction_imagecreatefrom']; if (!function_exists($fonction_imagecreatefrom)) { return ''; } $srcImage = @$fonction_imagecreatefrom($image); if (!$srcImage) { spip_log("echec gd1/gd2"); return; } // Initialisation de l'image destination $destImage = null; if ($process == 'gd2' and $destFormat != "gif") { $destImage = ImageCreateTrueColor($destWidth, $destHeight); } if (!$destImage) { $destImage = ImageCreate($destWidth, $destHeight); } // Recopie de l'image d'origine avec adaptation de la taille $ok = false; if ($process == 'gd2' and function_exists('ImageCopyResampled')) { if ($format == "gif") { // Si un GIF est transparent, // fabriquer un PNG transparent $transp = imagecolortransparent($srcImage); if ($transp > 0) { $destFormat = "png"; } } if ($destFormat == "png") { // Conserver la transparence if (function_exists("imageAntiAlias")) { imageAntiAlias($destImage, true); } @imagealphablending($destImage, false); @imagesavealpha($destImage, true); } $ok = @ImageCopyResampled($destImage, $srcImage, 0, 0, 0, 0, $destWidth, $destHeight, $srcWidth, $srcHeight); } if (!$ok) { $ok = ImageCopyResized($destImage, $srcImage, 0, 0, 0, 0, $destWidth, $destHeight, $srcWidth, $srcHeight); } // Sauvegarde de l'image destination $valeurs['fichier_dest'] = $vignette = "{$destination}.{$destFormat}"; $valeurs['format_dest'] = $format = $destFormat; _image_gd_output($destImage, $valeurs); if ($srcImage) { ImageDestroy($srcImage); } ImageDestroy($destImage); } $size = @getimagesize($vignette); // Gaffe: en safe mode, pas d'acces a la vignette, // donc risque de balancer "width='0'", ce qui masque l'image sous MSIE if ($size[0] < 1) { $size[0] = $destWidth; } if ($size[1] < 1) { $size[1] = $destHeight; } $retour['width'] = $largeur = $size[0]; $retour['height'] = $hauteur = $size[1]; $retour['fichier'] = $vignette; $retour['format'] = $format; $retour['date'] = @filemtime($vignette); // renvoyer l'image return $retour; }
/** * Transforme la couleur de fond de l'image en transparence * Le filtre ne gere pas la notion de contiguite aux bords, et affectera tous les pixels de l'image dans la couleur visee * $background_color : couleur cible * $tolerance : distance L1 dans l'espace RGB des couleur autour de la couleur $background_color pour lequel la transparence sera appliquee * $alpha : transparence a appliquer pour les pixels de la couleur cibles avec la tolerance ci-dessus * $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 * * @param string $im * @param string $background_color * @param int $tolerance * @param int $alpha * alpha = 0: aucune transparence * alpha = 127: completement transparent * @param int $coeff_lissage * @return mixed|null|string */ function image_fond_transparent($im, $background_color, $tolerance = 12, $alpha = 127, $coeff_lissage = 7) { $fonction = array('image_fond_transparent', func_get_args()); $image = _image_valeurs_trans($im, "fond_transparent-{$background_color}-{$tolerance}-{$coeff_lissage}-{$alpha}", "png", $fonction); if (!$image) { return ""; } $x_i = $image["largeur"]; $y_i = $image["hauteur"]; $im = $image["fichier"]; $dest = $image["fichier_dest"]; $creer = $image["creer"]; if ($creer) { $bg = _couleur_hex_to_dec($background_color); $bg_r = $bg['red']; $bg_g = $bg['green']; $bg_b = $bg['blue']; // Creation de l'image en deux temps // de facon a conserver les GIF transparents $im = $image["fonction_imagecreatefrom"]($im); imagepalettetotruecolor($im); $im2 = imagecreatetruecolor($x_i, $y_i); @imagealphablending($im2, false); @imagesavealpha($im2, true); $color_t = ImageColorAllocateAlpha($im2, 255, 255, 255, 127); imagefill($im2, 0, 0, $color_t); imagecopy($im2, $im, 0, 0, 0, 0, $x_i, $y_i); $im_ = imagecreatetruecolor($x_i, $y_i); imagealphablending($im_, false); imagesavealpha($im_, true); $color_f = ImageColorAllocateAlpha($im_, 255, 255, 255, $alpha); for ($x = 0; $x < $x_i; $x++) { for ($y = 0; $y < $y_i; $y++) { $rgb = ImageColorAt($im2, $x, $y); $r = $rgb >> 16 & 0xff; $g = $rgb >> 8 & 0xff; $b = $rgb & 0xff; if (($d = abs($r - $bg_r) + abs($g - $bg_g) + abs($b - $bg_b)) <= $tolerance) { imagesetpixel($im_, $x, $y, $color_f); } elseif ($tolerance and $d <= ($coeff_lissage + 1) * $tolerance) { $transp = round($alpha * (1 - ($d - $tolerance) / ($coeff_lissage * $tolerance))); $color_p = ImageColorAllocateAlpha($im_, $r, $g, $b, $transp); imagesetpixel($im_, $x, $y, $color_p); } else { imagesetpixel($im_, $x, $y, $rgb); } } } _image_gd_output($im_, $image); imagedestroy($im_); imagedestroy($im); imagedestroy($im2); } return _image_ecrire_tag($image, array('src' => $dest)); }
function produire_image_typo() { /* arguments autorises: $texte : le texte a transformer; attention: c'est toujours le premier argument, et c'est automatique dans les filtres $couleur : la couleur du texte dans l'image - pas de dieze $police: nom du fichier de la police (inclure terminaison) $largeur: la largeur maximale de l'image ; attention, l'image retournee a une largeur inferieure, selon les limites reelles du texte $hauteur_ligne: la hauteur de chaque ligne de texte si texte sur plusieurs lignes (equivalent a "line-height") $padding: forcer de l'espace autour du placement du texte; necessaire pour polices a la con qui "depassent" beaucoup de leur boite $align: alignement left, right, center */ /** * On définit les variables par défaut */ $variables_defaut = array('align' => false, 'police' => '', 'largeur' => 0, 'hauteur_ligne' => 0, 'padding' => 0); // Recuperer les differents arguments $numargs = func_num_args(); $arg_list = func_get_args(); $texte = $arg_list[0]; for ($i = 1; $i < $numargs; $i++) { if (($p = strpos($arg_list[$i], "=")) !== false) { $nom_variable = substr($arg_list[$i], 0, $p); $val_variable = substr($arg_list[$i], $p + 1); $variable["{$nom_variable}"] = $val_variable; } } $variable = array_merge($variables_defaut, $variable); // Construire requete et nom fichier $text = str_replace(" ", "~", $texte); $text = preg_replace(",(\r|\n)+,ms", " ", $text); include_spip('inc/charsets'); $text = html2unicode(strip_tags($text)); if (strlen($text) == 0) { return ""; } $taille = $variable["taille"]; if ($taille < 1) { $taille = 16; } $couleur = couleur_html_to_hex($variable["couleur"]); if (strlen($couleur) < 6) { $couleur = "000000"; } $alt = $texte; $align = $variable["align"]; if (!$variable["align"]) { $align = "left"; } $police = $variable["police"]; if (strlen($police) < 2) { $police = "dustismo.ttf"; } $largeur = $variable["largeur"]; if ($largeur < 5) { $largeur = 600; } if ($variable["hauteur_ligne"] > 0) { $hauteur_ligne = $variable["hauteur_ligne"]; } else { $hauteur_ligne = 0; } if ($variable["padding"] > 0) { $padding = $variable["padding"]; } else { $padding = 0; } $string = "{$text}-{$taille}-{$couleur}-{$align}-{$police}-{$largeur}-{$hauteur_ligne}-{$padding}"; $query = md5($string); $dossier = sous_repertoire(_DIR_VAR, 'cache-texte'); $fichier = "{$dossier}{$query}.png"; $flag_gd_typo = function_exists("imageftbbox") && function_exists('imageCreateTrueColor'); if (@file_exists($fichier)) { $image = $fichier; } else { if (!$flag_gd_typo) { return $texte; } else { $font = find_in_path('polices/' . $police); if (!$font) { spip_log(_T('fichier_introuvable', array('fichier' => $police))); $font = find_in_path('polices/' . "dustismo.ttf"); } $imgbidon = imageCreateTrueColor($largeur, 45); $retour = printWordWrapped($imgbidon, $taille + 5, 0, $largeur, $font, $couleur, $text, $taille, 'left', $hauteur_ligne); $hauteur = $retour["height"]; $largeur_reelle = $retour["width"]; $espace = $retour["espace"]; imagedestroy($imgbidon); $im = imageCreateTrueColor($largeur_reelle - $espace + 2 * $padding, $hauteur + 5 + 2 * $padding); imagealphablending($im, false); imagesavealpha($im, true); // Creation de quelques couleurs $grey2 = imagecolorallocatealpha($im, hexdec("0x{" . substr($couleur, 0, 2) . "}"), hexdec("0x{" . substr($couleur, 2, 2) . "}"), hexdec("0x{" . substr($couleur, 4, 2) . "}"), 127); ImageFilledRectangle($im, 0, 0, $largeur_reelle + 2 * $padding, $hauteur + 5 + 2 * $padding, $grey2); // Le texte a dessiner printWordWrapped($im, $taille + 5 + $padding, $padding, $largeur, $font, $couleur, $text, $taille, $align, $hauteur_ligne); // Utiliser imagepng() donnera un texte plus claire, // compare a l'utilisation de la fonction imagejpeg() _image_gd_output($im, array('fichier_dest' => $fichier, 'format_dest' => 'png')); imagedestroy($im); $image = $fichier; } } $dimensions = getimagesize($image); $largeur = $dimensions[0]; $hauteur = $dimensions[1]; return inserer_attribut("<img src='{$image}' width='{$largeur}' height='{$hauteur}' style='width:" . $largeur . "px;height:" . $hauteur . "px;' />", 'alt', $alt); }
function _image_creer_vignette($valeurs, $maxWidth, $maxHeight, $process='AUTO', $force=false, $test_cache_only = false) { // ordre de preference des formats graphiques pour creer les vignettes // le premier format disponible, selon la methode demandee, est utilise $image = $valeurs['fichier']; $format = $valeurs['format_source']; $destdir = dirname($valeurs['fichier_dest']); $destfile = basename($valeurs['fichier_dest'],".".$valeurs["format_dest"]); $format_sortie = $valeurs['format_dest']; // liste des formats qu'on sait lire $img = isset($GLOBALS['meta']['formats_graphiques']) ? (strpos($GLOBALS['meta']['formats_graphiques'], $format)!==false) : false; // si le doc n'est pas une image, refuser if (!$force AND !$img) return; $destination = "$destdir/$destfile"; // chercher un cache $vignette = ''; if ($test_cache_only AND !$vignette) return; // utiliser le cache ? if (!$test_cache_only) if ($force OR !$vignette OR (@filemtime($vignette) < @filemtime($image))) { $creation = true; // calculer la taille if (($srcWidth=$valeurs['largeur']) && ($srcHeight=$valeurs['hauteur'])){ if (!($destWidth=$valeurs['largeur_dest']) || !($destHeight=$valeurs['hauteur_dest'])) list ($destWidth,$destHeight) = _image_ratio($valeurs['largeur'], $valeurs['hauteur'], $maxWidth, $maxHeight); } elseif ($process == 'convert' OR $process == 'imagick') { $destWidth = $maxWidth; $destHeight = $maxHeight; } else { spip_log("echec $process sur $image"); return; } // Si l'image est de la taille demandee (ou plus petite), simplement // la retourner if ($srcWidth AND $srcWidth <= $maxWidth AND $srcHeight <= $maxHeight) { $vignette = $destination.'.'.$format; @copy($image, $vignette); } // imagemagick en ligne de commande else if ($process == 'convert') { define('_CONVERT_COMMAND', 'convert'); define ('_RESIZE_COMMAND', _CONVERT_COMMAND.' -quality 85 -resize %xx%y! %src %dest'); $vignette = $destination.".".$format_sortie; $commande = str_replace( array('%x', '%y', '%src', '%dest'), array( $destWidth, $destHeight, escapeshellcmd($image), escapeshellcmd($vignette) ), _RESIZE_COMMAND); spip_log($commande); exec($commande); if (!@file_exists($vignette)) { spip_log("echec convert sur $vignette"); return; // echec commande } } else // imagick (php4-imagemagick) if ($process == 'imagick') { $vignette = "$destination.".$format_sortie; $handle = imagick_readimage($image); imagick_resize($handle, $destWidth, $destHeight, IMAGICK_FILTER_LANCZOS, 0.75); imagick_write($handle, $vignette); if (!@file_exists($vignette)) { spip_log("echec imagick sur $vignette"); return; } } else // netpbm if ($process == "netpbm") { define('_PNMSCALE_COMMAND', 'pnmscale'); // chemin a changer dans mes_options if (_PNMSCALE_COMMAND == '') return; $vignette = $destination.".".$format_sortie; $pnmtojpeg_command = str_replace("pnmscale", "pnmtojpeg", _PNMSCALE_COMMAND); if ($format == "jpg") { $jpegtopnm_command = str_replace("pnmscale", "jpegtopnm", _PNMSCALE_COMMAND); exec("$jpegtopnm_command $image | "._PNMSCALE_COMMAND." -width $destWidth | $pnmtojpeg_command > $vignette"); if (!($s = @filesize($vignette))) spip_unlink($vignette); if (!@file_exists($vignette)) { spip_log("echec netpbm-jpg sur $vignette"); return; } } else if ($format == "gif") { $giftopnm_command = str_replace("pnmscale", "giftopnm", _PNMSCALE_COMMAND); exec("$giftopnm_command $image | "._PNMSCALE_COMMAND." -width $destWidth | $pnmtojpeg_command > $vignette"); if (!($s = @filesize($vignette))) spip_unlink($vignette); if (!@file_exists($vignette)) { spip_log("echec netpbm-gif sur $vignette"); return; } } else if ($format == "png") { $pngtopnm_command = str_replace("pnmscale", "pngtopnm", _PNMSCALE_COMMAND); exec("$pngtopnm_command $image | "._PNMSCALE_COMMAND." -width $destWidth | $pnmtojpeg_command > $vignette"); if (!($s = @filesize($vignette))) spip_unlink($vignette); if (!@file_exists($vignette)) { spip_log("echec netpbm-png sur $vignette"); return; } } } // gd ou gd2 else if ($process == 'gd1' OR $process == 'gd2') { if (_IMG_GD_MAX_PIXELS && $srcWidth*$srcHeight>_IMG_GD_MAX_PIXELS){ spip_log("vignette gd1/gd2 impossible : ".$srcWidth*$srcHeight."pixels"); return; } $destFormat = $format_sortie; if (!$destFormat) { spip_log("pas de format pour $image"); return; } $fonction_imagecreatefrom = $valeurs['fonction_imagecreatefrom']; if (!function_exists($fonction_imagecreatefrom)) return ''; $srcImage = @$fonction_imagecreatefrom($image); if (!$srcImage) { spip_log("echec gd1/gd2"); return; } // Initialisation de l'image destination if ($process == 'gd2' AND $destFormat != "gif") $destImage = ImageCreateTrueColor($destWidth, $destHeight); if (!$destImage) $destImage = ImageCreate($destWidth, $destHeight); // Recopie de l'image d'origine avec adaptation de la taille $ok = false; if (($process == 'gd2') AND function_exists('ImageCopyResampled')) { if ($format == "gif") { // Si un GIF est transparent, // fabriquer un PNG transparent $transp = imagecolortransparent($srcImage); if ($transp > 0) $destFormat = "png"; } if ($destFormat == "png") { // Conserver la transparence if (function_exists("imageAntiAlias")) imageAntiAlias($destImage,true); @imagealphablending($destImage, false); @imagesavealpha($destImage,true); } $ok = @ImageCopyResampled($destImage, $srcImage, 0, 0, 0, 0, $destWidth, $destHeight, $srcWidth, $srcHeight); } if (!$ok) $ok = ImageCopyResized($destImage, $srcImage, 0, 0, 0, 0, $destWidth, $destHeight, $srcWidth, $srcHeight); // Sauvegarde de l'image destination $valeurs['fichier_dest'] = $vignette = "$destination.$destFormat"; $valeurs['format_dest'] = $format = $destFormat; _image_gd_output($destImage,$valeurs); if ($srcImage) ImageDestroy($srcImage); ImageDestroy($destImage); } } $size = @getimagesize($vignette); // Gaffe: en safe mode, pas d'acces a la vignette, // donc risque de balancer "width='0'", ce qui masque l'image sous MSIE if ($size[0] < 1) $size[0] = $destWidth; if ($size[1] < 1) $size[1] = $destHeight; $retour['width'] = $largeur = $size[0]; $retour['height'] = $hauteur = $size[1]; $retour['fichier'] = $vignette; $retour['format'] = $format; $retour['date'] = (file_exists($vignette)) ? filemtime($vignette) : 0; // renvoyer l'image return $retour; }