Laboratorio: Recorta imágenes dinámicamente con PHP y HTML
15:18 H (CET)| Temas: Grafismo · How to · Javascript · Laboratorio · PHP
En muchos sitios web de almacenamiento de imágenes se nos permite retocar las imágenes. Hoy vamos a explicar como recortar una imagen directamente desde una página web.
Para ello tenemos que crearnos una página web que nos permita seleccionar la zona de la imagen que queremos recortar y de un script PHP que usando la librería GD recortará la imagen y la devolverá en formato PNG.
Primero es crear la página web que muestra la imagen y permite recortarla. Constará de una capa que contiene la imagen y de otra capa (span) que se usará para crear el marco de selección. Bueno, también hay una capa que mostrará la imagen resultante, pero esto no es necesario, solo es para mostrar el resultado en la misma página.
El HTML necesario para contener la imagen es el siguiente:
<div class="contenedor"
onclick="posicionaMarco(event)"
onmousemove="despliegaMarco(event)">
<img src="foto.jpg" alt="Foto" />
<span id="marco"></span>
</div>
La capa contenedor tendrá dos eventos que serán controlados:
- onclick: cuando se pincha en la imagen se empecerá/finalizará la selección de la zona de la imagen que queremos recortar.
- onmousemove: mientras se mueva el ratón por la imagen se creará el marco que indica que zona de la imagen se está seleccionando. En este caso, para no complicar la explicación del efecto, obligamos a que la selección se haga de izquierda-derecha y de arriba-abajo.
Los estilos solo hay que destacar que la capa contenedora debe tener el mismo tamaño que la imagen para evitar seleccionar más de la cuenta y que luego falle el script PHP, y que la capa marco debe tener el borde visible, en este caso sólido, rojizo y de 2 píxeles de grosor.
Cuando pinchamos en la imagen almacenamos la posición x e y del ratón, ya que será la esquina superior izquierda y luego inicializar los valores del marco.
var _IE_ = navigator.userAgent.indexOf("MSIE") != -1; // Si es IE
var inicio = false;
var xini = 0;
var yini = 0;
var xfin = 0;
var yfin = 0;
function posicionaMarco(e) {
inicio = !inicio;
var marco = document.getElementById("marco");
if (inicio) {
marco.style.display = "block";
// En IE y Opera se usa otra propiedad del evento
if (_IE_) {
xini = e.offsetX;
yini = e.offsetY;
} else {
xini = e.layerX;
yini = e.layerY;
}
marco.style.left = xini+"px";
marco.style.top = yini+"px";
marco.style.width = "0px";
marco.style.height = "0px";
}
}
Cuando se mueve el ratón por la superficie de la imagen (realmente de la capa), almacenamos la esquina inferior derecha del marco y modificamos el ancho y alto.
function despliegaMarco(e) {
if (inicio) {
var marco = document.getElementById("marco");
// En IE y Opera se usa otra propiedad del evento
// El 7 es para evitar que el ratón se solape con el marco y nos dé problemas
if (_IE_) {
xfin = e.offsetX-7;
yfin = e.offsetY-7;
} else {
xfin = e.layerX-7;
yfin = e.layerY-7;
}
// El 5 es para que haya un tamaño mínimo
if (xfin > xini+5) {
marco.style.width = (xfin-xini)+"px";
}
if (yfin > yini+5) {
marco.style.height = (yfin-yini)+"px";
}
}
}
Ya tenemos el HTML que nos permite seleccionar la zona de la imagen, ahora solo hace falta el script PHP. El funcionamiento es sencillo, carga la imagen, crea una imagen nueva con el tamaño final que debe tener y copiamos la zona que queremos recortar de la imagen en la nueva imagen. Por último devolvemos la imagen nueva.
<?php
// Abre la imagen
$fichero = getcwd()."/".$_GET["img"];
if (preg_match('/.png$/', $fichero)) {
$img = imagecreatefrompng($fichero);
} else if (preg_match('/.gif$/', $fichero)) {
$img = imagecreatefromgif($fichero);
} else if (preg_match('/.jpg$/', $fichero)) {
$img = imagecreatefromjpeg($fichero);
}
$xini = $_GET["xini"];
$yini = $_GET["yini"];
$xfin = $_GET["xfin"];
$yfin = $_GET["yfin"];
$res = imagecreatetruecolor (
$xfin-$xini, $yfin-$yini);
imagecopy($res, $img, 0, 0,
$xini, $yini,
$xfin-$xini, $yfin-$yini);
header("Content-type: image/png");
imagepng($res);
?>
Se le pueden añadir más funcionalidades, pero para ir empezando creo que está bien así.
Te puedes bajar las fuentes aquí
Relacionados
Feedback (44) » Formulario
1. David ~ Lunes, 17 Abr 2006 | 19:41H:
Hola Luis.
Estaba buscando como cortar una parte de una imagen cuando he encontrado tu articulo.
Lo que yo quiero hacer es saber si una parte de una imagen a cambiado, creo que puedo hacerlo con tu script y comprovando el tamaño de la imagen "muestra" con otra.
2. Luis ~ Lunes, 17 Abr 2006 | 21:01H:
Hola David.
Como bien dices se podría hacer mediante la comprobación de tamaño, aunque el tamaño puede ser el mismo y haber diferencias en la imagen, por ejemplo habiendo pintado sobre ella.
Permíteme que no te conteste del todo hoy e intentaré mañana hacer una entrada que responda a tu pregunta.
Saludos y gracias por contar con nosotros.
3. Héctor ~ Lunes, 22 May 2006 | 10:54H:
Hola Luis... necesito un favor... podrías decirme como podria ser el codigo, para que en vez de al hacer click, el marco vaya aumentando a donde indique el raton, que por defecto ya tenga un marco de recorte de unos determinados pixeles, y ke no se pueda aumentar, en todo caso solo mover el marco por la imagen. podrias ayudarme? gracias
4. Luis ~ Lunes, 22 May 2006 | 12:59H:
Hola Héctor.
No entiendo muy bien lo que me pides. No quieres que se use el click (¿para empezar a crear el recuadro o para finalizar el recuadro?). Luego me dices que vaya aumentando mientras se mueve el ratón, pero luego dices: "ke no se pueda aumentar".
Cuéntamelo más detalladamente, por favor.
Saludos
5. Héctor ~ Lunes, 29 May 2006 | 16:22H:
Si la verdad es que me he expresado mal, pero de todas formas ya lo he conseguido... Lo que queria, es crear una seleccion FIJA (por ejemplo de 50 x 50 px), y poder mover esa seleccion por toda la foto (sin que sobre salga de la imagen real). Y a ser posible, que una vez creada esa seleccion, se pueda mover con el raton. Sabrias decirmelo?
Hasta ahora he conseguido crear la seleccion fija cada vez que se clickea en una parte de la imagen, pero no consigo poder moverla con el raton... Sabrias decirmelo?
Gracias Luis
6. Johan ~ Sábado, 22 Jul 2006 | 11:45H:
Hector podrias decirme como hiciste esa area de selección? con este codigo. gracias
7. Andres Arena ~ Miércoles, 02 Ago 2006 | 00:51H:
Luis
Mi consulta es la siguiente, estoy realizzando un web para una colegio, en el se deben autenticar usuarios con capacidad para ingresar o modificar datos, claves, ahora puede hacerce por la forma clasica user+password, pero la idea es que estos usuarios tendrian una tarjeta de identidad con un codigo de barras especial, lo que ya tengo es el flash para realizar la captura desde una webcam del codigo y guardarlo en un directorio del web, lo que nececitaria seria el script para comparar esta imagen capturada con la que estaria en la base de datos, si es igual permitiria el ingreso de lo contrario no.
probe el codigo publicado en comparar dos imagenes con php, pero me da un error. y no se como solucionarlo, puedes testearlo en el link superior, desde ya muchas gracias ojala puedas ayudarme.
atte.
Andres
8. Luis ~ Miércoles, 02 Ago 2006 | 08:39H:
Hola Andrés.
Acabo de contestar tu duda en la otra entrada. Pero aún así, te recomiendo que busques otra solución, porque el método que explicamos para comparar imágenes, no te va a servir para lo que tu quieres.
Te en cuenta que cuando escaneas una imágen, vas a obtener mucho ruido, y no va a estar situada en el mismo sitio que la que tienes escaneada, a parte del tamaño, que posiblemente sean distintos. Total, que con nuestro script, nunca te van a dar imágenes iguales.
Yo te recomiendo que proceses los códigos de barras, los códigos de barras, a parte del gráfico, son un código (creo que numérico). Si procesas cada gráfico, para obtener el código, cuando escanees el código del usuario mediante la webcam, podrás procesar el gráfico y obtener el código, y así tendrás la certeza de que ambos códigos son el mismo, aunque los gráficos no se parezcan en nada.
Le he estado echando un ojo a Source Forge, y hay algunos proyectos que te pueden ayudar.
Saludos y espero haberte podido ayudar.
Luis
9. fredyrivera ~ Jueves, 17 Ago 2006 | 02:19H:
Para esto tendrias que utilizar un codigo de barras bidireccional que efectivamente almacena la foto talcual la tomaste ademas de los otros datos, pues este funciona como un pdf, pero debe ser bidireccional por que los unidireccionales o los que conocemos normalmente como el EAN(el que traen los productos del supermercado) solo almacenan una secuencia de caracteres.
10. Gustavo ~ Martes, 12 Sep 2006 | 20:39H:
como puedo capturar la imagen de mi webcam desde php y guardarla en mysql
11. Luis ~ Martes, 12 Sep 2006 | 21:58H:
Hola Gustavo.
Desde PHP no se puede hacer, entre otras cosas porque se ejecuta en el servidor, tú lo que necesitas es capturar la imagen desde una aplicación en el cliente. Desde Flash se puede hacer, luego tendrás que hacerte un actionscript para guardarlo en la BD.
Espero que esto te ayude
12. Mauro ~ Domingo, 17 Dic 2006 | 17:45H:
Hola
Genial artículo, hace tiempo que venía buscando algo así. En mi caso particular la aplicación que estoy desarrollando requiere que la selección del recuadro respete ciertas proporciones, así que me tomé el atrevimiento de realizar una pequeña modificación al script en la función despliegaMarco:
if (_IE_) {
xfin = e.offsetX-7;
} else {
xfin = e.layerX-7;
}
yfin = (yini+((xfin-xini)*3/4)-7);
Como verán, lo que hago es calcular la posición de yfin en base a la posición elegida de X, y no en base al lugar Y en el que se encuentre el mouse en ese momento. De esta manera, cada vez que se mueve el mouse en X se recalcula el lugar correspondiente a Y.
Pero tengo dos problemas:
1) Tengo un efecto no deseado del mouse, ví que anteriormente lo solucionaste restando 7 a la posición del mouse, pero en este caso no sé exactamente dónde restar para que no aparezca
2) Si se mueve el mouse sólo en la posición Y y dejo quieto el X, el cuadrado no cambia de tamañao, estoy pensando en una solución y si la encuentro les aviso.
Eso es todo, vuelvo a agradecer por el post.
14. alex Sanabria ~ Viernes, 09 Mar 2007 | 21:55H:
Hola que tal estuve utilizando tu código para hacer una aplicación de que a partir de una fotografía te la divida varias partes para poder hacer un rompecabezas pero al hacer esto en mi computadora con el wamp lo realiza a la perfección corta la imagen y me muestra todos los pedazos pero en el momento que lo subo a internet no funciona bien debido a que solo hace bien el trabajo hasta como la imagen 10 de 100 después ya no me muestra las demás imágens tienes alguna idea de cual pueda ser mi problema?
18. ELOY !! ~ Viernes, 16 Mar 2007 | 20:04H:
hola luis...
estoy haciendome una pagina web de spaces hotmail y la verdad eske no se komo poner los codigos ke muchas paginas me dicen por ejemplo codigos para poner videos o para poner el tiempo etc...
me gustaria k me respondieras por favor y eske kiero poner un video gracias luis espero k me contestes hasta otra...
20. juli ~ Domingo, 01 Abr 2007 | 22:57H:
Buenas, yo tengo una duda al modificar este script, y primero necesitaría reducir una imagen de tamaño y luego recortarla para tener unas dimensiones en concreto perdiendo lo menos posible, o sea, reducir una imagen al ancho que necesito y luego recortar su alto, o viceversa, para tener por ejemplo un cuadrado de una imagen rectangular
al intentarlo, reducir la imagen, como esta no se guarda en el servidor y luego se vuelve a tratar para recortarla, sino que lo intento hacer directamente, no me funciona, sino que o me recorta sobre la imagen sin reducir o me reduce la imagen pero no me mantiene las proporciones
alguna idea?
21. Luis ~ Domingo, 01 Abr 2007 | 23:38H:
Yo creo que realmente da igual si primero se reduce o luego se recorta, pero ten en cuenta que si primero reduces y luego recortas, las variables $xini, $xfin, $yini, $yfin han variado y las tienes que modificar tu en la escala a la que has reducido la imagen.
Saludos
22. Luna ~ Sábado, 07 Abr 2007 | 01:04H:
Por favor podría alguien explicarme como puedo, conseguir la imagen de una foto,sola sin el marco que la encuadra,por ejemplo, un perro,solo el perro ,como silueta pero la imagen tal cual se ve pero sin el marco cuadrado de la foto.
Muchas gracias.
Luna
40. wuelfhis asuaje ~ Martes, 29 Abr 2008 | 23:52H:
Hermano un saludo desde Venezuela, por favor, dado tu experiencia ayudame en lo siguiente, tengo unos directorio con ciertas imagenes, otro con recortes de esas imagenes, ahora bien necesito ponerle nombre a esos recortes para guardarlos en BBDD, pero me encuentro con que cientos de ellos ya los her recortado antes (con otra hora y fecha). La pregunta: ¿como puedo yo al escanear o al procesar archivos de este directorio de recortes saber (por reconocimiento de patron de la imagen) que ya le he puesto nombre antes y que simplemente me traiga ese nombre ?. Y luego este nombre ya asociarlo al nuevo recorte. te agradezco lo que puedas hacer por mi
41. wuelfhis asuaje ~ Miércoles, 30 Abr 2008 | 14:43H:
Saludos hermano, otra pregunta, con tu ejemplo de recortar imagenes. como hago para guardar físicamente en disco con un nombre o automatico o tecleado por un usuario, para guardar ese nombre en BBDD y el recorte en un directorio????
muchas gracias

