Se lo leí el otro día a Rinzewind, de alguién en Reddit que se había hecho un script que genera una nueva imagen combinando un PNG de Calvin&Hobbs con la imagen de temática astronómica que a diario la NASA publica en su sitio.

El script original estaba hecho en Ruby, alguien lo rehizo despues en bash y recientemente he hecho una versión en PHP que permite insertalo facilmente en la web. Para ello he incorporado algunas opciones más que podeis leer más abajo.

La idea original era hacer el script PHP para subirlo al hosting gratuito que tengo en Tripod.es (Lycos) y así poder linkarlo todo el que quiera usarlo en su web, fondo de escritorio, etc… si que la descarga de imágenes de gran tamaño le diera a este servidor más trabajo del que tiene. El problema es que parece que dichos hosting tiene capadas muchas funciones que impiden que funcione correctamente. Asi es que, de forma temporal, lo cuelgo en este dominio y en versión de imagen pequeña, ya que como digo, las imágenes que es capaz de producir a partir de las gigantes que se publican en esa web (+3000 pixels) producirian un trabajo extra a este servidor que no tengo ganas de asumir.

Si alguien se anima a subirlo a su propio dominio solo necesita soporte PHP5 y disponer de las librerias gráficas (GD, bastante habitual en servidores web “normales”).
Del mismo modo, si alguien quiere utilizarlo para otra funcion similar que le interesa, pues aqui debajo cuento como funciona, como se descarga y como se instala.

Foto composición automática de Kalvin&Hoobs + NASAFoto composición automática de Kalvin&Hoobs + NASA

El script PHP básicamente lo que hace es:

  • una visita solicita la imagen calvin.php ó calvin_nasa.jpg (url amigables)
  • conecta con la página de la NASA y obtiene la fecha de la imagen publicada en ese momento (aparece impresa justo encima de la imagen)
  • Con esa fecha componemos un nombre: calvin_nasa_2010_septembre_8.jpg y buscamos dicha imagen en nuestra carpeta del hosting.
  • Si la imagen existe (alguién la solicitó anteriormente) se sirve simplemente al cliente.
  • Si la imagen no la tenemos descargada (porque acaban de cambiarla en la página)
  • Se descarga la nueva imagen.
  • Se coloca sobre ella el PNG de Kalvin&Hobbs ( incluido en el zip de descarga ) y se reescala este último para ajustarlo a la nueva imagen.
  • Se guarda bajo el patrón de nombre calvin_nasa_2010_septembre_11.jpg y se sirve.

Url amigable

Esto es perfectamente prescindible pero ayuda bastante. Añadiendo un par de lineas en .htaccess del directorio en que se encuentre el script PHP facilitamos la url de la imagen.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule calvin_nasa.jpg$ calvin.php [QSA,L]
RewriteRule calvin_nasa_([0-9]{2,3}).jpg$ calvin.php?size=$1 [QSA,L]
</IfModule>

De esta manera las solicitudes de http://www.tudominio.com/tuDirectorioConEscritura/calvin_nasa.jpg son tratadas por http://www.tudominio.com/tuDirectorioConEscritura/calvin.php y las que además incluyan calvin_nasa_UNNUMERO.jpg son pasadas al script con la variable “size” que podremos coger con $_GET[“size”].

Escalado bajo solicitud

Para facilitar la integración de la imagen en el blog he dispuesto la posilibidad de descargar la imagen a 3 tamaños diferentes: 240px, 500px y original (unos 900px, cambia entre imágenes). Luego vendría la versión grande (+3000px) que como decía ahora no usamos.
Para solicitar una imagen escalada hay que incluir el tamaño en la url de la imagen. Asi:
Sin URL AMIGABLES
#Sirve la imagen grande +/- 900px
http://www.tudominio.com/tuDirectorioConEscritura/calvin.php
#Sirver una imagen a 500 px
http://www.tudominio.com/tuDirectorioConEscritura/calvin.php?size=500
#Sirve a 240px
http://www.tudominio.com/tuDirectorioConEscritura/calvin.php?size=240

Con URL AMIGABLES
#Sirve la imagen grande +/- 900px
http://www.tudominio.com/tuDirectorioConEscritura/calvin_nasa.jpg
#Sirver una imagen a 500 px
http://www.tudominio.com/tuDirectorioConEscritura/calvin_nasa_500.jpg
#Sirve a 240px
http://www.tudominio.com/tuDirectorioConEscritura/calvin_nasa_240.jpg

En realidad podemos pedirle el tamaño que queramos, pero el script digamos que “redondea” las solicitudes a los tres tamaños comentados. Asi es que si solicitamos una imagen menos de 320px nos sirve la de 240px, entre 320 y 680 sirve una de 500px y por encima de 680 sirve la original.

Pseudo-cache

No hay manera de saber si la imagen que tenemos descargada es la última publicada en la página web de la NASA. Solo nos queda consultar dicha página y leer la fecha inserta en el HTML. Esto puede llegar a ser un incordio importante de solicitudes para dicha web de la NASA si este script es ejcutado por muchas máquinas (sitio web muy visitado). Ahora bién lo que podriamos hacer (que no he hecho, si alguien se anima que lo incorpore a su antojo) es almacenar la hora de la última solicitud para evitar hacer otra antes de ¿10 minutos? y dar “periodos de descanso” si es que script PHP fuese usado masivamente.
Por ahora se queda en tareas pendientes.

Imagen a gran tamaño

Las imagenes servidas por la pagina web de la NASA son enormes, por lo que descargarlas y procesarlas para insertar la mascara de Kalvin&Hobbs y volverlas a descargar al cliente es un proceso lento y costoso, por esto en el script que el colgado se trabaja solo con la imagen grande (+/- 900px)
Si quereis usar el script con las imagenes grandes basta con descargarlo y editar la linea 53 para que en lugar de
$i=imagenCompuesta("calvin.png", $urlNasa.$coincidencias[3]);
ponga
$i=imagenCompuesta("calvin.png", $urlNasa.$coincidencias[2]);
con eso es script toma la url del enlace en lugar de la url de la imagen. Dependiendo del tamaño puede demorarse hasta 1 minuto en el proceso de descargar, procesar y volcar la nueva imagen.

Descargar e instalar

Para usar el script en tu propio servidor e insertarlo en tu pagina haz:
Descarga este archivo calvin.zip.
Contiene un archivo PHP y una imagen PNG que corresponde a la máscara de Calvin&Hobbs.

Sube ambos archivos a la misma carpeta de tu dominio.
Asegurate que dicha carpeta tenga permisos de escritura ya que el script PHP irá produciendo cada día (bajo demanda) hasta 3 imágenes JPG con siguiente patrón:
calvin_nasa.jpg (al tamaño que se encuentre en la página)
calvin_nasa_500.jpg (mediana, 500 pixels)
calvin_nasa_240.jpg (pequeña, 240 pixels)

Apunta tu navegador hacia la ruta del PHP que acabas de subir
(http://www.tudominio.com/tuDirectorioConEscritura/calvin.php)
ó inserta algo como esto en tu página:
<img src="http://www.tudominio.com/tuDirectorioConEscritura/calvin.php?size=500" width="500px" alt="calvin sobre fondo de la NASA a 500pixels">

Script e imagen

Si lo prefieres, el contenido del script es este y la imagen PNG de Calvin es esta.
<?php
header("Content-type: image/jpeg");
$anchoV=""; $anchoT=""; $escalar=false;
if( isset( $_GET["size"] ) ) {
if( $_GET["size"] <= 320) {
$escalar=true;
$anchoT="_240";
$anchoV=240;
} else if ( $_GET["size"] > 320 && $_GET["size"] <= 680) {
$escalar=true;
$anchoT="_500";
$anchoV=500;
} else if ( $_GET["size"] > 680) {
$escalar=false;
}
}
$urlNasa="http://apod.nasa.gov/apod/";
function imagenCompuesta($encima="calvin.png", $debajo) {
global $escalar;
global $anchoV;
$imagenSuperior = imagecreatefrompng($encima);
$imagenInferior = imagecreatefromjpeg($debajo);
$sizeSuperior=getimagesize($encima);
$proporcionesSuperior=$sizeSuperior[0]/$sizeSuperior[1];
$sizeInferior=getimagesize($debajo);
if($escalar)
$rescalado=($anchoV/$sizeInferior[0]);
else
$rescalado=1;
$imagenCompuesta=imagecreatetruecolor( ($sizeInferior[0] * $rescalado), ($sizeInferior[1] * $rescalado) );
imagecopyresampled($imagenCompuesta, $imagenInferior, 0, 0, 0, 0, ($sizeInferior[0] * $rescalado), ($sizeInferior[1] * $rescalado), $sizeInferior[0], $sizeInferior[1] );
imagecopyresampled($imagenCompuesta, $imagenSuperior, 0, ( ($sizeInferior[1] * $rescalado)- ( ($sizeInferior[0]*$rescalado)/$proporcionesSuperior ) ), 0, 0, ( $sizeInferior[0] * $rescalado ), ( ( $sizeInferior[0]/$proporcionesSuperior ) * $rescalado ), $sizeSuperior[0], $sizeSuperior[1]);
return $imagenCompuesta;
}
$contenido=file_get_contents($urlNasa);
$patron='/([0-9]{4} [\w]* [0-9]{1,2})[^<]*<br>[^<]*<a *href="([^"]*)"[^>]*>[^<]*<IMG SRC="([^"]*)"/';
if ( preg_match($patron, $contenido, $coincidencias) > 0 ) {
$fecha=str_replace(" ","_", $coincidencias[1]);
$archivoDestino="calvin_nasa_".$fecha.$anchoT.".jpg";
if( file_exists($archivoDestino ) ) {
$i=imagecreatefromjpeg($archivoDestino);
imagejpeg($i);
} else {
$i=imagenCompuesta("calvin.png", $urlNasa.$coincidencias[3]);
imagejpeg($i, $archivoDestino);
imagejpeg($i);
}
} else {
$fecha=date("Y_F_j", strtotime("-1 day"));
$archivoDestino="calvin_nasa_".$fecha.$anchoT.".jpg";
$i=imagecreatefromjpeg($archivoDestino);
imagejpeg($i);
}
imagedestroy($i);
?>