Guia básica para editar imágenes en PHP con GD
Escrito por Alex Barros Crear y editar imágenes con PHP puede ser muy fácil si tienes instalada la biblioteca GD en tu servidor.
Aunque las opciones que ofrece GD son muy básicas, son suficientes para desarrollar scripts con capacidades muy superiores. Ahora voy a presentaros estas funciones básicas con ejemplos, para que puedas crear aplicaciones más complejas.
Crear la imagen de cero o desde un archivo
Para tratar imágenes en GD trabajamos con recursos o variables tipo resource de imágenes. Esto es una varible que representa a la imagen.
Para crear un nuevo recurso de imagen podemos usar la función imagecreate() aúnque es más recomendable usar la función imagecreatetruecolor()
-
$im = imagecreatetruecolor(300, 200); //a partir de aqui trabajo con una imagen de 300×200
-
$im2 = imagecreatetruecolor(100, 100); //he creado otra imagen distinta con dimensiones 100×100
Si queremos partir de una imagen ya existente, para convertirla en recurso tendremos que usar la función adecuada dependiendo del formato de la imagen. Los principales formatos son JPEG, PNG y GIF; con las funciones imagecreatefromjpeg(), imagecreatefrompng() y imagecreatefromgif() respectivamente.
-
$miJpeg =imagecreatefromjpeg(‘miimagen.jpg’); //he creado un recurso a partir del archivo miimagen.jpg
Si quieres ahorrarte el pensar a la hora de crear un recurso a partir de imagen, o desconoces el formato de entrada de la imagen (y quieres que lo haga automáticamente) puedes usar esta función para crear cualquier tipo de imagen.
-
function newimage($src) {
-
$im = false;
-
switch(true) {
-
$im = imagecreatefromstring( getUrlData($src) );
-
imagealphablending($im, true);
-
imagesavealpha($im, true);
-
break;
-
$im = imagecreatefromjpeg($src);
-
break;
-
$imp = imagecreatefromgif($src);
-
-
$x = imagesx($imp);
-
$y = imagesy($imp);
-
$im = imagecreatetruecolor($x, $y);
-
imagefilledrectangle( $im, 0, 0, $x, $y, imagecolorallocate($im, 255, 255, 255) );
-
imagecopy($im, $imp, 0, 0, 0, 0, $x, $y);
-
break;
-
$im = imagecreatefrompng($src);
-
-
imagealphablending($im, true);
-
imagesavealpha($im, true);
-
break;
-
}
-
return $im;
-
}
-
function getUrlData($url){
-
$ch = curl_init($url);
-
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
-
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
-
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
-
$get = curl_exec($ch);
-
curl_close($ch);
-
return $get;
-
}
Esta función puede crear una imagen a partir de JPEG, PNG, GIF o URL (requiere CURL)
Si queremos saber las dimensiones de un recurso de imagen, usaremos las funciones imagesx($im) e imagesy($im) que devuelven el ancho y alto del recurso, en píxeles, respectivamente.
Copiar, recortar y redimensionar
La modificación más básica que podemos hacer a una imagen es recortarla y redimensionarla.
En ambos casos la forma de trabajar es, en primer lugar crear un nuevo recurso con las dimensiones apropiadas, y en segundo lugar copiar de la imagen origen a la imagen destino aplicando el cambio deseado.
Recortar una imagen
Para recortar una imagen de, por ejemplo, 500 x 400 en 50px por la derecha y por abajo, haremos lo siguiente:
- Creamos un nuevo recurso de 500 – 50 = 450 por 400 – 50 = 350px
- Usamos la función imagecopy para copiar de la imagen origen, en nuestra nueva imagen
bool imagecopy ( resource $im_destino , resource $im_origen , int $pos_x_destino , int $pos_y_destino , int $pos_x_origen , int $pos_y_origen , int $ancho_origen , int $alto_origen )
- Los dos primeros parámetros son los recursos destino y origen
- Los dos siguientes son la posición en eje x e y de la imagen destino, donde queremos comenzar a copiar (en nuestro caso 0,0; porque el eje está arriba y a la izquierda)
- Los dos siguientes son el ancho y el alto de la imagen que queremos recortar del aimagen original. En nuestro caso 450 y 350.
-
$im_origen = imagecreatefromjpeg(‘mi_imagen.jpg’); //sabemos que mide 500 x 400
-
$im_destino = imagecreatetruecolor(450, 350); //im_destino contendrá la nueva imagen recortada
-
-
imagecopy($im_destino, $im_origen, 0, 0, 0, 0, 450, 350);
-
// Ahora im_destino es im_origen recortada por abajo y por la derecha 50px
[descargar código] Ejemplo: [original] [recortada dinámicamente]
Redimensionar una imagen
En este ejemplo vamos a redimensionar a la mitad la imagen origen, sea cual sea su tamaño.
Crearemos primero un nuevo recurso con las dimexiones x/2 e y/2, y usaremos la función imagecopyresampled() (también podríamos usar imagecopyresized(), pero la que vamos a usar suaviza los píxeles interpolándolos – tiene mejor calidad)
-
$im_origen = imagecreatefrompng(‘foo.png’);
-
$ancho = imagesx($im_origen);
-
$alto = imagesy($im_origen);
-
-
-
$im_destino = imagecreatetruecolor($nuevo_ancho, $nuevo_alto);
-
imagecopyresampled($im_destino, $im_origen, 0, 0, 0, 0, $nuevo_ancho, $nuevo_alto, $ancho, $alto);
-
// ahora im_destino es la mitad de grande que im_origen
Dibujar figuras y texto
Las figuras que GD nos deja pintar son muy básicas, parecidas a las que ofrece el programa Paint
En este punto lo más importante es crear colores para una imagen. Los colores se deben crear y asociar a una imagen mediante la función imagecolorallocate(). El color lo indicamos mediante parámetros RGB (Red Green Blue) que podemos extraer fácilmente de cualquier paleta, como la del Photoshop o el Gimp
Dibujar un rectángulo
Quizás la figura más simple. Podemos dibujar sólo el borde del rectángulo con la función imagerectangle() o el rectangulo relleno de color, con la función imagefilledrectangle()
bool imagerectangle ( resource $imagen , int $x1 , int $y1 , int $x2 , int $y2 , int $color )
bool imagefilledrectangle ( resource $imagen , int $x1 , int $y1 , int $x2 , int $y2 , int $color )
-
$imagen = imagecreatefromjpeg(‘mi_imagen.jpg’);
-
$negro = imagecolorallocate($imagen, 0, 0, 0);
-
//voy a dibujar un rectangulo negro entre las coordenadas (5,5) y (25,15), recuerda que el eje está arriba a la izquierda
-
imagefilledrectangle($imagen, 5, 5, 25, 15, $negro);
Otras figuras
Existen muchas figuras que puedes dibujar con GD, desde una línea hasta un polígono, pasando por la elipse o el píxel. Sólo busca la que más te conviene en la documentación, o combina varias para obtener la figura deseada.
Escribir texto
Es realmente sencillo. Si no te quieres complicar la vida, puedes usar la función imagestring() que te da la opción de elegir entre 5 fuentes internas indicando sólo el número de referencia…
-
$im = imagecreate(100, 30); //creo una nueva imagen de 100×30
-
$fondo = imagecolorallocate($im, 255, 255, 255); //blanco. El primer color creado, se utiliza como fondo automaticamente para esa imagen
-
$color_texto = imagecolorallocate($im, 0, 0, 255); //azul
-
// escribo la cadena arriba a la izquierda con la fuente #5
-
imagestring($im, 5, 0, 0, "¡Hola mundo!", $color_texto);
… o si quieres tener más control sobre el estilo, puedes usar fuentes TrueType con la función imagettftext() (en la web DaFont tienes miles de fuentes TrueType gratuitas)
-
$im = imagecreatetruecolor(400, 30); //creo una nueva imagen de 400×30
-
// creo algunos colores
-
$blanco = imagecolorallocate($im, 255, 255, 255);
-
$gris = imagecolorallocate($im, 128, 128, 128);
-
$negro = imagecolorallocate($im, 0, 0, 0);
-
imagefilledrectangle($im, 0, 0, 399, 29, $blanco); //relleno el fondo
-
-
// El texto a pintar
-
$texto = "Boozox.net";
-
// El archivo ttf, escribe la ruta correctamente!!
-
$fuente = ‘fuente.ttf’;
-
-
// Agrego una sombra al texto
-
imagettftext($im, 20, 0, 11, 21, $gris, $fuente, $texto);
-
-
// Escribo el texto
-
imagettftext($im, 20, 0, 10, 20, $negro, $fuente, $texto);
[descargar código]
Demo:
Tratar bien la transparencia en PNG
Las imágenes PNG admiten un canal Alpha que indica la opacidad en cada punto de la imagen, para crear efectos semitransparentes. Si te interesa que esta transparencia se muestre correctamente, deberás calentarte un poco más la cabeza, y tener el canal Alpha siempre en cuenta. Te aconsejo que incluyas estas dos líneas después de crear una nueva imagen con transparencia (aunque tendrás que estar siempre atento de que el canal alpha no se pierda!)
-
$im = imagecreatefrompng(‘mi_transparencia.png’);
-
//conservar transparencia
-
imagealphablending($im, true);
-
imagesavealpha($im, true);
Recuerda también que puedes crear colores con canal de transparencia usando imagecolorallocatealpha() en lugar de imagecolorallocate()
Exportar la imagen para visualizarla
Después de haber modificado nuestra imagen tal como deseamos, tendremos que exportarla. Existe una función para cada formato de salida (imagejpeg(), imagepng(), imagegif(), etc…). Personalmente te recomiendo siempre exportar en PNG porque se conserva la calidad y la nitidez mucho mejor.
En todos los casos tendremos la opción de generar el código de la imagen, si queremos que el archivo PHP simule ser la propia imagen, o indicarle dónde queremos que almacene la imagen resultado.
Para el primer caso, tendremos que indicar mediante las cabeceras que lo que estamos a punto de mostrar es una imagen. Para esto usamos la función header() indicando el tipo de archivo en concreto de que se trata (image/jpeg, image/png o image/gif).
-
//este codigo se incluiria al final del proceso de edicion, suponiendo que $im es el recurso de la imagen que queremos mostrar
-
imagepng($im);
Una vez creado este archivo, podemos mostrar el resultado en una página HTML simplemente creando una etiqueta de imagen que referencie a ese archivo .php
-
<img src="imagen.php" />
Si queremos almacenar en nuestro disco la imagen resultante, tendremos que pasar como segundo parámetro a la función el nombre del archivo que queremos generar.
-
imagepng($im,‘ruta/miarchivo.png’);
Recuerda que me interesa mucho tu opinión. Crees que falta algo? tienes dudas? vas a trabajar con la librería GD ahora que sabes cómo funciona? has hecho experimentos curiosos con imágenes dinámicas? …
Categorias: Código, Imagen Digital, PHP, Ubuntu |



Respeta el copyleft
Octubre
15:05 Joan Ha dicho:
¿Son cosas de mi Firefox o el número de la línia de los segmentos de código aparecen en japonés?
Mmm… No he leído el post, lo dejo en la cola de pendientes pero tiene buena pinta.
Saludos!
Octubre
16:02 Alex Barros Ha dicho:
Tranquilo, no son cosas de tu Firefox, son cosas de mi esquizofrenia. Las líneas de código están en Katakana.
Me gusta mucho más que los insípidos números decimales.
Cuando leas el artícula ya comentarás si te ha parecido útil, o lo que hayas hecho para probarlo!
[...] Alex de Boozox, me avisa de que ha desarrollado un artículo en el que nos muestra de forma clara y concisa la forma de usar la librería GD de PHP para editar y crear imagenes. [...]
Octubre
22:40 Diego Ha dicho:
Yo me hice una clase de PHP 5 para encapsular la mayoría de la funcionalidad de tratamiento de imágenes. Y no va mal. No está suficientemente probada pero facilita enormemente esta tarea.
A ver si termino mi pequeño proyecto y puedo poner alguna reseña de esta (y otras) clases.
Octubre
0:39 Alex Barros Ha dicho:
@Diego: estaría genial!
[...] Puedes ver la guía en Boozox.net. [...]
Octubre
17:58 Eduardo Ha dicho:
Genial!
hermosa guia
Octubre
18:17 edgard Ha dicho:
buenisima guia
gracias…
Octubre
19:08 Alex Barros Ha dicho:
@Eduardo @edgard: Muchas gracias! Me quedó un pelín larga, pero esque quería incluir toda esta información, para que sirva de referencia.
Muchas gracias por los elogios, ayuda a echar palante
Octubre
18:37 Gerardo Ha dicho:
Espectacular la funcion.
Yo lo hacia de la una forma menos practica. ahora empezare a usar esta funcion. Saludos y Gracias
[...] Alex de Boozox, me avisa de que ha desarrollado un artículo en el que nos muestra de forma clara y concisa la forma de usar la librería GD de PHP para editar y crear imagenes. [...]
Octubre
16:37 Isra Ha dicho:
Hola! Muy interesante la guía. Con GD lo único interesante que he hecho gráficas, CAPTCHA y marca de agua. No conocía la función imagettftext()… se ve que no he buceado lo suficiente por el manual
imagestring() con imageloadfont() no me servía de mucho con las fuentes en formatos GDF…
Octubre
19:09 Alex Barros Ha dicho:
Yo también me llevé una grata sorpresa al descubrir imagettftext() ^^
Octubre
17:32 Sebastian Ha dicho:
Muy buen post!!!! Un tema muy interesante y nuevo para mi, y explicado con palabras muy simples.
Te felicito!!!!!
Octubre
17:39 Alex Barros Ha dicho:
Muchas gracias Sebastian! Me alegra mucho que te haya gustado el post. Si buscas por entradas anteriores de Boozox, hay muchas de este estilo, manuales simples de introducción a tencnoligías web.
Un saludo, espero verte más veces por los coments
Octubre
5:40 Alvaro Ha dicho:
Muy buena guia, gracias.
Lo que no se muy bien es si me llega una imagen por POST, como puedo pasar dicha imagen a una rutina que redimensiona.
¿Pasando solo el nombre ya paso la imagen?
Octubre
11:32 Alex Barros Ha dicho:
No entiendo muy bien tu problema, Alvaro.
Imagino que quieres que una imágen que viene de un formulario POST se redimensione. Pero, el formulario envía un texto representando una dirección de imágen, o es un formulario que envía un archivo?
Si es el primer caso, puedes generar la imagen usando la función newimage() así:
Si es el segundo, recuerda que tu formulario debe tener la propiedad enctype=“multipart/form-data” y podrás acceder a la imagen usando la dirección temporal del archivo, almacenada en la variable $_FILES['imagen']['tmp_name'], el problema es que este archivo temporal no tiene el nombre del archivo, así que tendrás que usar otra función a la que se le pase la dirección de la imagen, y el nombre de la imagen original, para que pueda escojer el formato con el que descodificarla:
function createFromName($source,$name=false) { if(!$name) $name = $source; switch(true) { case eregi('\.jpg',$name): $im = imagecreatefromjpeg($source); break; case eregi('\.gif',$name): $im = imagecreatefromgif($source); break; case eregi('\.png',$name): $im = imagecreatefrompng($source); break; default: $im = false; } return $im; }Entonces podrás llamarla así:
Espero que esto satisfaga tu problema. Si no es así, intenta explicarte mejor.
Un saludo.
Noviembre
19:34 Julio Gonzales Ochoa Ha dicho:
Solo por curiosidad, es posible agregar texto permanentemente, al contenido de un grafico. Para que me entiendan mejor, si tengo una imagen de un documento cualquiera, es posible agregarle a esta un rotulo que diga la fecha de recepcion. No se si alguien pudiera proporcionar el codigo como ejemplo se los agradeceria.
Noviembre
22:48 Alex Barros Ha dicho:
Claro que sí es posible. Puedes crearte un script en PHP que al ejecutarlo pasándole una dirección de imágen, le imprima la fecha. El código sería algo similar a este:
< ?php
//incluye la declaración de la funcion newimage() descrita en el tutorial
$im = newimage($_GET['imagen']);
$colortxt = imagecolorallocate($im,0,0,0); //negro
$texto = date(DATE_RFC822); //algo como: Mon, 15 Aug 2005 15:12:46 UTC
imagettftext($im, 20, 0, 11, 21, $colortxt, 'mifuente.ttf', $texto);
//se guarda la imagen de nuevo en el mismo lugar
switch(true) {
case eregi(‘\.jpg’, $_GET['imagen']):
imagejpeg($im,$_GET['imagen']);
break;
case eregi(‘\.gif’, $_GET['imagen']):
imagegif($im,$_GET['imagen']);
break;
case eregi(‘\.png’, $_GET['imagen']):
imagepng($im,$_GET['imagen']);
break;
default:
imagepng($im,$_GET['imagen']);
break;
}
?>
Noviembre
3:05 Rafael Ha dicho:
Saludos. Estoy tratando de cargar una imagen generada con GD en un tag de html, pero no me sale la imagen.. no se cual puede ser el error.
el html lo coloco asi:
y en mi carnet.php recibo con $_GET las variables ced y nac, y genero la imagen usando funciones de GD. Al final de carnet.php tengo el siguiente código:
header(’Content-Type: image/jpeg’);
imagejpeg($im);
imagedestroy($im);
y la imagen no sale.. no se si estoy haciendo algo mal.
Noviembre
3:33 Alex Barros Ha dicho:
La razón puede ser que exista un error en el código que genera la imagen, y por eso no se genera el JPEG. Puedes compiar el código completo de carnet.php?
Diciembre
0:16 Maxi Ha dicho:
Hola, esta muy bueno tu articulo, no sabia que se podian formar figuras como poligonos en PHP.
Gracias por la info.
Saludos
Diciembre
3:24 EDSH Ha dicho:
Perfecto era justo lo que buscaba ja ja ja… Pues bueno soy nuevo programando en php y me ha parecido un excelente lenguaje por su sencillez de codigo y por la forma de tratar las cosas…
Me ha sido muy util tu resumen…
Bye
Diciembre
10:10 Alex Barros Ha dicho:
Un auténtico placer, Maxi y EDSH
Enero
23:38 CodesPwg Ha dicho:
emmmm … Realmente me volvi Un 8 xD … Deberian de poner Todo el Form y Todo el code en un archivito , seria mas facil …
x lo viso yo tengo que hacer todo el Formmm …T_T
Enero
0:12 Diego Ha dicho:
Hola, mi consulta es la siguiente, tal vez me puedan ayudar, enstoy desarrollando un sitio donde las imagenes son png de 24 bits , si bien uso todo lo que dice en el post, no he podido lograr que se vean correctamente, se ven distorcionadas, mejor dicho de ven con fondo blanco y borrosas…podrian ayudarme…Gracias!!!
Enero
14:24 Alex Barros Ha dicho:
El tercer parámetro de la función imagepng() es la calidad, que va ce cero (sin comprimir) a 9
El fondo blanco imagino que te refieres a que originalmente tenian transparencia. Después de crear el recurso de imagen, debes aplicar estas dos funciones:
imagealphablending($im, true);
imagesavealpha($im, true);
Enero
14:36 Diego Ha dicho:
Muchas Gracias…Lo he logrado usando esas 2 funciones, y ya que tenia que ubicarlas dentro de otra imagen png de 24 bits he usado la funcion imagecopy, ya que usaba imagecopymerge y no daba resultado. Gracias nuevamente. Saludos
Enero
9:13 Jose Ha dicho:
yo estaba buscando como poner un sello a las fotos que tengo en mi portal de mecanico y con esto se puede hacer esta bueno lo boy a probar
jose
Enero
18:59 Alex Barros Ha dicho:
Claro que si! Y si tienes cualquier duda pregunta por aquí.
Febrero
5:42 cafe Ha dicho:
tengo un proyecto que hacer sobre tratamiento de imagenes y soy novato en php ya muestra la imagen
y tengo que aplicarle un filtro que es escala de grises lo hice con la funcion html ya viene predeterminado el filtro
pero ahora la tengo que filtrar por negativo y no tengo ni la mas minima idea podrian ayudarme cualquier opinion es buena
Abril
0:04 Fabian Ha dicho:
Quiero agregar una marca de agua a una imagen guardada en una base mysql, como se hace? Gracias.
Abril
23:10 diseño web Ha dicho:
No se como al guaradste, quizas ea solo la direccion. Entodo caso te copio un codigo que encontre en otro foro:
<?php
$image = $_GET['imagen']; //esta parte la puedes reemplazar por la conexion a la base de datos y recuperar la URL de tu imagen.
$watermark = “marca_de_agua.png”;
$im = imagecreatefrompng($watermark);
$ext = substr($image, -3);
if(strtolower($ext) == “gif”) {
if (!$im2 = imagecreatefromgif($image)) {
echo “Error opening $image!”;
exit;
}
} else if(strtolower($ext) == “jpg”) {
if (!$im2 = imagecreatefromjpeg($image)) {
echo “Error opening $image!”;
exit;
}
} else if(strtolower($ext) == “png”) {
if (!$im2 = imagecreatefrompng($image)) {
echo “Error opening $image!”;
exit;
}
} else {
die;
}
imagecopy($im2, $im, (imagesx($im2)/2)-(imagesx($im)/2), (imagesy($im2)/2)-(imagesy($im)/2), 0, 0, imagesx($im), imagesy($im));
if($_GET[repeat]) {
$waterless = imagesx($im2) – imagesx($im);
$rest = ceil($waterless/imagesx($im)/2);
for($n=1; $n
Saludos
Agosto
19:43 Mauricio Reyes Ha dicho:
Hola, primero que nada, felicitaciones por la información, realmente útil.
Por eso, en parte, debo pedir ayuda.
Me encanta crear páginas web, pero aún me falta muchísmo.
Pr esa razón, planteo na idea que me dieron y no sé como hacerlo (aunque viendo el código, al parecer se puede)
Por medio un formulario, debo guardar datos de un cliente. Datos como nombre, rut, etc, y las validaciones no son problema. Sn embargo, está la posibildad de guardar su firma, usando un lápiz óptico y un campo similar a un textbox (en tamaño), pero que permita la creación de una firma (en otras palabras, la modificación de una imagen en blanco), y pensaba guardar esta en la base de datos para cargarla posteriormente (al imprimir el documento).
No encontré un e-mail para contactarlo. Posiblemente lo más obvio es lo que más cuesta ver.
Muchas gracias de antemano.
Mauricio Reyes.
No encontré
Agosto
7:40 Alex Barros Ha dicho:
El problema lo tienes a la hora de capturar el movimiento del dispositivo (lapiz optico) ya que el HTML actual no admite este tipo de entradas como estandard.
Probablemente la respuesta venga de un applet de Java, y sea MUY complicado de programar.
Siento ser desalentador! Gracias por el comentario
Agosto
20:45 Juan p. Ha dicho:
Muy interesante, tengo una duda… si yo quiero imagenes de 100 x 100
y me suben una de 30×30, como hago para que mantengan la imagen de 30×30 y el resto lo rellene de blanco? (es decir un cuadrado de 100 x 100 blanco con ese imagen incrustada…) muchas gracias
Agosto
18:27 Alex Barros Ha dicho:
Símplemente crea un lienzo nuevo en blanco de 100 x 100, y copia el recurso de la imágen de 30 x 30 dentro del lienzo, calculando sus coordenadas con simples cálculos matemáticos.
Es decir, si la quieres completamente centrada: x = y = 100 / 2 – (30 / 2) = 35px
Enero
6:07 Hermes Ha dicho:
Excelente material! esto es lo que estaba buscando para recortar imagenes dinamicamente, Gracias!