[Tutorial] Evitar hotlinking y sacarle provecho
El código PHP que nos permite modificar la imagen lo he dividido en funciones, que pondremos en el archivo (funciones.php). Veamos detalladamente cada función:
Transformar imagen a escala de grises [función blanco_negro()]
El funcionamiento de ésta función es algo complejo, pero podrÃamos decir que cambia pÃxel por pÃxel el color de la imagen, y devuelve su equivalente en blanco y negro:
function blanco_negro($nombre,$img){
// Obtener las dimensiones de la imagen
list($ancho, $altura) = getimagesize($nombre);
// Definir nuestra fuente de imagen
$fuente = $img;
// Crear Canvas
$imgblanconegro= imagecreate($ancho, $altura);
//Crear una paleta de 256 colores
for ($c=0;$c<256;$c++)
$palette[$c] = imagecolorallocate($imgblanconegro,$c,$c,$c);
//Funcion para modificar los colores
function yiq($r,$g,$b){
return (($r*0.299)+($g*0.587)+($b*0.114));
}
//Leer los colores originales pixel por pixel
for ($y=0;$y<$altura;$y++)
for ($x=0;$x<$ancho;$x++)
{
$rgb = imagecolorat($fuente,$x,$y);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8 ) & 0xFF;
$b = $rgb & 0xFF;
//Aqui es donde usamos yiq para cambiar los colores
//y convertir la imagen a escala de grises
$gs = yiq($r,$g,$b);
imagesetpixel($imgblanconegro,$x,$y,$palette[$gs]);
}
// retornar la imagen creada working with
return $imgblanconegro;
}
Redimensionar la imagen [función redimensionar()]
Esta función crea una nueva imagen a partir de la original, siempre y cuando la imagen sea más ancha o larga de 250px. Además, verifica la dimensión adecuada para la nueva imagen, es decir, si la imagen es más larga horizontalmente, crea una imagen de 250px de ancho y de alto la redimensiona de tal manera que guarde las proporciones, y viceversa.
function redimensionar($imagen){
// Obtener el tamanio original
$ancho = imagesx($imagen);
$altura = imagesy($imagen);
if($ancho > 250 || $altura > 250){
if($ancho > $altura){
//Asignar nuevo tamanio
$nueva_anchura = 250;
$av = 25000/$ancho;
$nueva_altura = ($altura/100)*$av;
}
else{
//Asignar nuevo tamanio
$nueva_altura = 250;
$av = 25000/$altura;
$nueva_anchura = ($ancho/100)*$av;
}
// redimensionar
$imagen_nueva = imagecreatetruecolor($nueva_anchura, $nueva_altura);
imagecopyresampled($imagen_nueva, $imagen, 0, 0, 0, 0, $nueva_anchura, $nueva_altura, $ancho, $altura);
return $imagen_nueva;
}
}
Aplicar una marca de agua a la imagen [función marca_de_agua()]
Esta función crea un rectángulo negro en el centro de la imagen (imagefilledrectangle), y dentro de él inserta dos lÃneas de texto (imagestring), que nos permitirán indicarle al usuario que la imagen es nuestra:
function marca_de_agua($imagen, $texto, $texto2) {
// Crear objetos de colores
$blanco = imagecolorallocate($imagen, 255, 255, 255);
$negro = imagecolorallocate($imagen, 0, 0, 0);
// Aniadir el texto
$ancho = 7.5*strlen($texto2);
$primerX = (imagesx($imagen)-($ancho))/2;
$altura = 40;
$primerY = (imagesy($imagen)-($altura))/2;
imagefilledrectangle ( $imagen , $primerX , $primerY , $primerX + $ancho , $primerY + $altura , $negro );
imagestring($imagen, 3, $primerX+10, $primerY+3, $texto, $blanco);
imagestring($imagen, 3, $primerX+10, $primerY+23, $texto2, $blanco);
return $imagen;
}
Script que ejecuta las funciones [hotlink.php]
En el script hotlink.php, realiza lo siguiente:
- Crear una variable con la dirección de la imagen que a procesar (lÃnea 2)
- Obtener la extensión de la imagen (lÃneas 3 y 4), y comprobar que sea realmente una imagen (lÃnea 6), puesto que no queremos que nos carguen basura allÃ. SerÃa además conveniente que comprobaramos que la imagen es realmente nuestra, y que no se encuentra en otro servidor; esto no lo he implementado para no complicar las cosas.
- Cargar el archivo de las funciones (lÃnea 9)
- Abrir la imagen (lÃnea 11)
- Transformar imagen a blanco y negro (lÃnea 15)
- Redimensionar la imagen (lÃnea 17)
- Poner una marca de agua (lÃnea 19)
- Generar la imagen JPG resultante (lÃneas 20 y 21)
<?php
$direccion_imagen = $_GET["i"];
$extension = strrchr($direccion_imagen, '.');
$extension = strtolower($extension);
//Verificar si es una imagen
if($extension == ".gif" || $extension == ".jpg" || $extension == ".jpeg" || $extension == ".png" || $extension == ".bmp")
{
//Incluir las funciones
include_once ("funciones.php");
//Cargar imagen
$imagen = abrir_imagen($direccion_imagen);
if ($imagen === false) { die ('No se puede cargar la imagen'); }
//Cambiar a blanco y negro
$imagen = blanco_negro($direccion_imagen,$imagen);
//Redimensionar la imagen
$imagen = redimensionar($imagen);
//Aplicar marca de agua
$imagen = marca_de_agua($imagen, 'Visita casidiablo.net', 'Para ver la imagen correctamente');
header('Content-type: image/jpeg');
imagejpeg($imagen);
}
else echo "Que putas quieres?";
die();
?>
Para cargar el script cuando alguien intente hacernos hotlinking, debemos de configurar por supuesto nuestro .htaccess. A continuación, mi .htaccess con todos los ejemplos incluidos:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /wordpress/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /wordpress/index.php [L]
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://casidiablo.net$ [NC]
RewriteCond %{HTTP_REFERER} !^http://casidiablo.net/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^http://www.casidiablo.net$ [NC]
RewriteCond %{HTTP_REFERER} !^http://www.casidiablo.net/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^http://www.google.com/reader/view/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^http://www.google.com/reader/m/view/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^http://[^/.]\.feedburner\.com$ [NC]
RewriteCond %{HTTP_REFERER} !^http://feeds.feedburner.com/Casidiablo$ [NC]
RewriteRule .*\.(gif|jpg|jpeg|png|bmp)$ http://casidiablo.net/hotlink/hotlink.php?i=%{REQUEST_FILENAME} [R,NC,L]
</IfModule>
- Incluye una lista de los sitios que pueden visualizar las imagenes
- Y una redirección al script que modifica la imagen
Recuerda cambiar las URLs por las tuyas, tanto para la web, como para el feed y para el script PHP.
Enlaces y descargas
- Leyendo esta entrada se me ocurrió lo de modificar la imagen, en vez de motrar otra
- Documentación ModRewrite
- De aquà aprendà bastante









Cristian dice:
Mayo 20th, 2009 a las 9:55 am
Claro, tan simple como eso!
blog2k dice:
Mayo 20th, 2009 a las 10:51 am
de mas agradecido!, ahora me queda ver que server uso!
saludos y gracias
blog2k dice:
Mayo 20th, 2009 a las 12:07 pm
bueno les dejo la consulta por ahi puede ser un tema del servidor… estoy probando esto en un directorios de enlaces hecho con phpld y agrego la siguiente linia al htacces
RewriteRule .*\.(gif|jpg|jpeg|png|bmp)$ http://img196.imageshack.us/img196/8088/enlaceblogdir6.gif [R,NC,L]
el tema es que en algunos sitios no me muestra nada y en otros me lo muestra en cualquier posición….
saludos
Andres dice:
Junio 21st, 2009 a las 8:11 pm
Hola, use tus funciones para redimensionar las imagenes antes de subirlas a la BD y quedó perfecto, gracias. Pero hay imagenes sobre 1600px en que da un error de memoria. Esta imagen pesa 396Kb y las dimensiones son 3000 x 2121.
Este es el error: Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 413965 bytes)
Espero me puedas ayudar.
Cristian dice:
Junio 23rd, 2009 a las 9:22 am
Hola andrés, debes modificar una de las opciones del archivo php.ini en el que indicas la máxima cantidad de RAM que puedes usar.
Un saludo!
Andres dice:
Junio 23rd, 2009 a las 9:00 pm
Cristian, Gracias por contestar.
Modifiqué la memoria limite del php.ini y mejoró, me dejo subir la foto, pero ahora tengo otra foto y pereciera que tengo que agrandar mas y mas la memoria limite. Ya voy en 512M. Como puedo restringir que intenten subir estas imágenes.
Salu2.
Cristian dice:
Junio 24th, 2009 a las 9:56 am
Umm… OK, eso lo haces directamente desde PHP… en muchas partes se explica cómo hacerlo, por ejemplo:
http://www.maestrosdelweb.com/editorial/upphp/
Un saludo!
Andres dice:
Junio 24th, 2009 a las 9:28 pm
Hola Cristian.
Yo tambien uso $_FILES['archivo']['size']; para restringir el tamaño. Tengo imagenes que pesan 300k y no tengo problemas para subirlas y redimensionarlas, pero hay otras que pesan menos, pero que superan los 1600px donde aparece el error. Eso me ocurre justo en la linea donde ejecuto $im = imagecreatefromstring($bin_data);
En un foro decÃan que que se debe a la función descomprime la imagen para poder trabajar con ella….. no se que tan valido es eso…. pero ahora estoy tratando de manejar el error que aparece para que el usuario entienda lo que pasó. Sabes como se hace?
Salu2