La
técnica más común para redondear esquinas en PHP consiste en tomar imágenes prefabricadas y aplicarlas sobre la imagen original.
La verdad es que, aunque produce buenos resultados, prefiero algo más standalone y que no haga trabajar tanto al servidor.
Hay una función muy útil, perteneciente a la librería
GD de
PHP, que puede ayudarnos en esta tarea. Se trata de
imagefilltoborder.
Vamos a citar el manual para ver qué hace exactamente:
Descripción
bool imagefilltoborder(resource $im,int $x,int $y,int $border,int $col)
imagefilltoborder() realiza un relleno hasta el color del borde que está definido por border . El punto de inicio para el relleno es x , y (arriba izquierda es 0,0) y la región se rellena con el color col .
Veamos una de las posibles aplicaciones de esta función:
El código utilizado es el siguiente:
<?php
if(isset($_GET['im'])){
header('Content-type:image/gif');
$img=imagecreatefromgif('mapaAmerica.gif');
$limit=imagecolorat($img, 317, 477);
$rojo=imagecolorallocate($img,255,0,0);
if(isset($_GET['imageField_x']))
imagefilltoborder($img,$_GET['imageField_x'],$_GET['imageField_y'],$limit,$rojo);
imagegif($img);
imagedestroy($img);
exit;
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Mapa</title>
<style>
*{margin:0}
h3{background-color:#000; color:#FFF; padding:3px; font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;}
input{cursor:crosshair}
</style>
</head>
<body>
<h3>Hacer click sobre el mapa para colorearlo</h3>
<form id="form1" name="form1" method="get" action="<?php echo basename($_SERVER['PHP_SELF']) ?>">
<input type="image" name="imageField" src="?im&<?php echo $_SERVER['QUERY_STRING'] ?>" />
</form>
</body>
</html>
Vemos que si la super global
$_GET['im'] está definida, el archivo entrega la imagen procesada y sale (
exit), y si no, muestra el formulario, que tiene un
input type image cuyo atributo src es el mismo archivo pero con la variable get
im siempre definida. El agregado de
$_SERVER['QUERY_STRING'] es para recoger las coordenadas
x e
y que envía siempre un
input type image cuando hacemos click sobre él, y que en este caso son usadas por
imagefilltoborder para realizar el relleno.
¿Y qué tiene esto que ver con las esquinas redondeadas?
Es que básicamente podemos usar la misma técnica.
Los pasos serían:
1) Desde el punto 0,0 de nuestra imagen dibujamos una línea horizontal cuya medida sea igual al radio del borde que vamos a aplicar (
imageline).
2) Hacemos lo mismo, pero esta vez con una línea vertical (
imageline).
3) Dibujamos un arco que una los extremos separados de las líneas que acabamos de dibujar (
imagearc).
Es importante que esos tres elementos tengan el mismo color, de manera que formen una figura cerrada de borde monocromo.
Veamos cómo sería en código:
<?php
header('Content-type:image/gif');
$r=60;
$color='FFFFFF';
$img=imagecreatefromgif('1.gif');
$m=getimagesize('1.jpg');
$bg=imagecolorallocate($img,hexdec(substr($color,0,2)),hexdec(substr($color,2,2)),hexdec(substr($color,4,2)));
imageline($img,0,0,$r,0,$bg);
imageline($img,0,0,0,$r,$bg);
imagearc($img,$r,$r,$r*2+1,$r*2+1,180,270,$bg);
imagegif($img);
imagedestroy($img);
?>
Este sería el resultado de ese código:
Como vemos, ya tenemos lo mismo que en nuestro ejemplo del mapa: una superficie aislada por un borde, que podemos rellenar usando la función
imagefilltoborder. Sólo nos queda definir un punto que se encuentre dentro de ella y rellenar a partir del mismo. El punto ubicado en las coordenadas 2,2 podría ser una buena opción:
<?php
header('Content-type:image/gif');
$r=60;
$color='FFFFFF';
$img=imagecreatefromgif('1.gif');
$m=getimagesize('1.jpg');
$bg=imagecolorallocate($img,hexdec(substr($color,0,2)),hexdec(substr($color,2,2)),hexdec(substr($color,4,2)));
imageline($img,0,0,$r,0,$bg);
imageline($img,0,0,0,$r,$bg);
imagearc($img,$r,$r,$r*2+1,$r*2+1,180,270,$bg);
imagefilltoborder($img,2,2,$bg,$bg);
imagegif($img);
imagedestroy($img);
?>
Resultado:
Y listo, haciendo lo mismo con los bordes restantes y algunas modificaciones para que sea más reusable, podemos obtener algo como esto:
<?php
header('Content-type:image/jpeg');
$r=!isset($_GET['r'])?20:$_GET['r'];
$color=!isset($_GET['color'])?'FFFFFF':$_GET['color'];
$img=imagecreatefromjpeg($_GET['img']);
$m=getimagesize($_GET['img']);
$bg=imagecolorallocate($img,hexdec(substr($color,0,2)),hexdec(substr($color,2,2)),hexdec(substr($color,4,2)));
/*sup-izq*/
if(!isset($_GET['si'])){
imageline($img,0,0,$r,0,$bg);
imageline($img,0,0,0,$r,$bg);
imagearc($img,$r,$r,$r*2+1,$r*2+1,180,270,$bg);
imagefilltoborder($img,2,2,$bg,$bg);
}
/*sup-izq*/
/*sup-der*/
if(!isset($_GET['sd'])){
imageline($img,$m[0],0,$m[0]-$r,0,$bg);
imageline($img,$m[0],0,$m[0],$r,$bg);
imagearc($img,$m[0]-$r,$r,$r*2+1,$r*2+1,270,360,$bg);
imagefilltoborder($img,$m[0]-2,2,$bg,$bg);
}
/*sup-der*/
/*abaj-izq*/
if(!isset($_GET['ai'])){
imageline($img,0,$m[1],0,$m[1]-$r,$bg);
imageline($img,0,$m[1],$r,$m[1],$bg);
imagearc($img,$r,$m[1]-$r,$r*2+1,$r*2+1,90,180,$bg);
imagefilltoborder($img,2,$m[1]-2,$bg,$bg);
}
/*abaj-izq*/
/*abaj-der*/
if(!isset($_GET['ad'])){
imageline($img,$m[0],$m[1],$m[0],$m[1]-$r,$bg);
imageline($img,$m[0]-$r,$m[1],$m[0],$m[1],$bg);
imagearc($img,$m[0]-$r,$m[1]-$r,$r*2+1,$r*2+1,0,90,$bg);
imagefilltoborder($img,$m[0]-2,$m[1]-2,$bg,$bg);
}
/*abaj-der*/
imagejpeg($img);
imagedestroy($img);
?>
Que podemos usar de esta manera para mostrar sólo algunas esquinas redondeadas y el radio por defecto:
<img width="500" src="roundCorner.php?img=38.jpg&sd&ai" />
Resultado:
O de esta otra para mostrar todas las esquinas redondeadas y otro radio:
<img src="roundCorner.php?img=39.jpg&r=40" />
Resultado:
Y si quisiéramos aplicarlo sobre un fondo de color #CCCCCC, por ejemplo, podríamos usarlo asi:
<img alt="ejemplo" src="roundCorner.php?img=11.jpg&r=40&color=CCCCCC" />
Resultado: