En este post voy a explicar y demostrar cómo se pueden poner marcas de agua con PHP utilizando las funciones de la librería GD.
Vamos a ver cómo poner la marca de agua en distintas posiciones (arriba a la izquierda, arriba a la derecha, centrada horizontal y verticalmente) y cómo modificar la opacidad de la marca de agua.
En la imagen de arriba se puede notar que he colocado una marca de agua de una “terminal” sobre una captura de código C (es sobre el post de generar números aleatorios con C).
He elegido estas dos imágenes porque el dueño soy yo, así que no pueden existir reclamaciones de derechos de autor y esas cosas que dan pereza.
Nota: recuerda que hace tiempo publiqué WaterPy, una aplicación similar pero escrita en Python.
Probar ejemplos y ver código completo
A lo largo del tutorial explicaré las partes más importantes del código y ahorraré las repetitivas. Por ello es que he puesto todo el código actualizado en GitHub.
Funciones y explicación de las mismas
Primero debemos cargar la imagen; en este caso fueron imágenes PNG así que usamos la función llamada imagecreatefrompng
; si fuera jpeg sería imagecreatefromjpeg
. Ambas funciones reciben la ruta de la imagen,
Cuando tenemos una referencia al recurso de la imagen podemos obtener algunos datos de ella, por ejemplo la altura o anchura.
La función que realmente hace el trabajo de poner la marca de agua es imagecopy
, pues pone una imagen encima de otra en determinadas posiciones.
Marca de agua en la parte superior izquierda
Veamos un ejemplo que coloca la marca de agua en la esquina superior izquierda, es decir, al “inicio” de la imagen:
<?php
/**
* Ejemplos de cómo poner marcas de agua con PHP y GD
*
* @author parzibyte
*/
$rutaImagenOriginal = __DIR__ . "/codigo.png";
$rutaMarcaDeAgua = __DIR__ . "/marca.png";
$original = imagecreatefrompng($rutaImagenOriginal);
$marcaDeAgua = imagecreatefrompng($rutaMarcaDeAgua);
# En dónde poner la marca de agua sobre la original
$xOriginal = 0;
$yOriginal = 0;
# Desde dónde comenzar a cortar la marca de agua (si son 0, se comienza desde el inicio)
$xMarcaDeAgua = 0;
$yMarcaDeAgua = 0;
# Hasta dónde poner la marca de agua sobre la original
$alturaMarcaDeAgua = imagesy($marcaDeAgua) - $yMarcaDeAgua;
$anchuraMarcaDeAgua = imagesx($marcaDeAgua) - $xMarcaDeAgua;
imagecopy($original, $marcaDeAgua, $xOriginal, $yOriginal, $xMarcaDeAgua, $yMarcaDeAgua, $anchuraMarcaDeAgua, $alturaMarcaDeAgua);
# Imprimir y liberar recursos
header('Content-Type: image/png');
imagepng($original);
imagedestroy($original);
imagedestroy($marcaDeAgua);
Cuando llamamos a imagecopy
la imagen se copia, pero no se guarda ni se muestra. Para mostrarla directamente en el navegador enviamos un encabezado indicando el tipo de imagen y llamamos a imagepng
con un único argumento: el recurso de la imagen.
Para liberar los recursos tanto de la marca de agua como de la imagen a la que se le pone la marca de agua se llama a imagedestroy
.
Se supone que deberían liberarse automáticamente al salir del script pero no siempre se llamarán al final del script; por eso es una buena práctica liberar lo tomado.
La sintaxis de imagecopy
Al principio es un poco difícil de comprender, pero yo te explico los argumentos en el orden que se mandan a imagecopy:
- Imagen de destino obtenida con una función de
imagecreatefrom*
: Es la imagen sobre la cual se pone la marca de agua - Imagen fuente: recurso de imagen que se va a poner sobre la imagen de destino. Es la marca de agua
- Posición x de inicio en donde se coloca la marca de agua sobre la imagen de destino: por ejemplo, si es 0 se pondrá hasta la izquierda. Si es 100 se pondrá 100 pixeles alejado de la izquierda y así sucesivamente.
- Posición y de inicio: lo mismo que x pero ahora sobre Y.
- Posición x de marca de agua: desde dónde comenzar a “cortar” la marca de agua. Si es 0 se empieza desde el inicio, si es, por ejemplo, 100, se cortará la marca de agua desde 100 pixeles en X.
- Posición y de marca de agua: lo mismo que la posición anterior pero en y. En resumen, si quieres la imagen completa simplemente pon este y el anterior en 0.
- Anchura de la imagen que se sobrepone: la anchura de la marca de agua
- Altura de la imagen que se sobrepone: la altura de la marca de agua. Estos dos últimos se obtienen de
imagesy
eimagesx
.
Centrar marca de agua
Sabiendo lo anterior podemos jugar un poco con las matemáticas y las medidas de las imágenes para centrar completamente la marca de agua, tanto vertical como horizontalmente. El siguiente código ejemplifica cómo:
<?php
/**
* Ejemplos de cómo poner marcas de agua con PHP y GD
*
* @author parzibyte
*/
$rutaImagenOriginal = __DIR__ . "/codigo.png";
$rutaMarcaDeAgua = __DIR__ . "/marca.png";
$original = imagecreatefrompng($rutaImagenOriginal);
$marcaDeAgua = imagecreatefrompng($rutaMarcaDeAgua);
# Como vamos a centrar necesitamos sacar antes las anchuras y alturas
$anchuraOriginal = imagesx($original);
$alturaOriginal = imagesy($original);
$alturaMarcaDeAgua = imagesy($marcaDeAgua);
$anchuraMarcaDeAgua = imagesx($marcaDeAgua);
# En dónde poner la marca de agua sobre la original
$centroHorizontalDeOriginal = floor($anchuraOriginal / 2);
$centroHorizontalDeMarcaDeAgua = floor($anchuraMarcaDeAgua / 2);
$centroVerticalDeOriginal = floor($alturaOriginal / 2);
$centroVerticalDeMarcaDeAgua = floor($alturaMarcaDeAgua / 2);
$centroHorizontal = $centroHorizontalDeOriginal - $centroHorizontalDeMarcaDeAgua;
$centroVertical = $centroVerticalDeOriginal - $centroVerticalDeMarcaDeAgua;
$xOriginal = $centroHorizontal;
$yOriginal = $centroVertical;
# Desde dónde comenzar a cortar la marca de agua (si son 0, se comienza desde el inicio)
$xMarcaDeAgua = 0;
$yMarcaDeAgua = 0;
# Hasta dónde poner la marca de agua sobre la original
$alturaMarcaDeAgua = $alturaMarcaDeAgua - $yMarcaDeAgua;
$anchuraMarcaDeAgua = $anchuraMarcaDeAgua - $xMarcaDeAgua;
imagecopy($original, $marcaDeAgua, $xOriginal, $yOriginal, $xMarcaDeAgua, $yMarcaDeAgua, $anchuraMarcaDeAgua, $alturaMarcaDeAgua);
# Imprimir y liberar recursos
header('Content-Type: image/png');
imagepng($original);
imagedestroy($original);
imagedestroy($marcaDeAgua);
Para centrar se saca el punto medio de la imagen y el punto medio de la marca de agua, después de eso se hace una resta y se redondea hacia abajo.
Guardar imagen con marca de agua en lugar de mostrarla
Si se desea guardar la imagen en el disco duro para su futuro procesamiento solamente se debe pasar un segundo parámetro a imagepng
: la ruta de la imagen (recuerda que el primer parámetro es el recurso de imagen)
<?php
$resultado = imagepng($original, "marcada.png");
Cambiar opacidad de marca de agua
Si queremos podemos cambiar la opacidad de la marca de agua para que se vea un poco transparente.
Para ello usamos la función imagecopymerge
que funciona exactamente igual que imagecopy
pero recibe un parámetro adicional: un entero que indica el porcentaje de opacidad.
<?php
# Usar imagecopymerge en lugar de imagecopy
# La diferencia es que al final se indica el porcentaje
imagecopymerge($original, $marcaDeAgua, $xOriginal, $yOriginal, $xMarcaDeAgua, $yMarcaDeAgua, $anchuraMarcaDeAgua, $alturaMarcaDeAgua, $porcentajeOpacidad);
Todo se comportará de la misma manera pero la marca de agua estará transparente. Entre menor sea el número, la marca de agua será más transparente.
Marca de agua en distintas posiciones
Es totalmente posible colocar la marca de agua sobre la imagen en distintas posiciones, simplemente hay que llamar varias veces a imagecopy o imagecopymerge con distintos parámetros.
Al final, al llamar a imagepng
se obtendrá el resultado de todas las imágenes copiadas.
Otro tipo de imágenes
En el ejemplo utilizamos únicamente imágenes PNG pero se pueden utilizar otro tipo de imágenes, por ejemplo JPG, BMP, etcétera.
Para esto existen las funciones imagecreatefromjpeg y todas ellas que se pueden ver en el manual oficial.
Cuando trabajes con imágenes y las muestres directamente en el navegador recuerda establecer el encabezado a la forma correcta, por ejemplo image/jpeg.
De la misma manera, no siempre vas a llamar a imagepng
, puedes llamar a otras dependiendo del formato de tus imágenes.
Conclusión
Por si no lo leíste, puedes ver los ejemplos en GitHub y probar lo que hicimos en mi sitio web. Al inicio del post dejé los enlaces.
Puedes hacer que una imagen se envíe a través de un formulario y se ponga la marca de agua, por ejemplo. Las posibilidades son infinitas y todo depende de lo que necesidades.
Lee más sobre PHP aquí.
Pingback: Instalar librería gd para PHP en Linux Ubuntu - Parzibyte's blog