viernes, 23 de noviembre de 2012

Como crear y usar sprites en páginas HTML


HTML 5
CSS 3
Reducir el tiempo de carga de una página web es importante ya que un tiempo excesivo puede hacer que parte de los usuarios se vayan antes de que cargue la página completa. Para reducir el tiempo de carga de una página web se pueden hacer varias cosas, entre ellas:
  • Reducir el peso de la página, por ejemplo, reduciendo el tamaño de las imágenes o haciendo el código html más simple.
  • Utilizar versiones minimizadas de frameworks javascript y css.
  • Combinar archivos de javascript y css. Para hacer menos peticiones.
  • Usar CDNs que sirvan los javascript de tal modo que el usuario no tenga que descargarlos si ya los tiene cacheados de otras peticiones o accesos a otras páginas.
  • Y la que es de interés en esta entrada, reducir número de peticiones también en los iconos usados en la página usando la técnica de crear sprites.
Los iconos suelen tener la característica de que suelen ser pequeños (de uno o 2 KiB) de forma que el mayor tiempo empleado para descargarlos no es la transferencia sino el tiempo empleado para realizar la petición y la latencia de la red. Es mejor combinar todos los iconos en una imagen grande y hacer una sola petición (aunque algunos no se usen) que hacer tantas peticiones como iconos diferentes tengamos. Es lo mismo aplicado cuando se combinan varios archivos javascript y css en uno solo para hacer menos peticiones al servidor pero aplicado a las imágenes.

Para hacer la combinación de las imágenes hay herramientas en internet que nos permiten realizalo de forma sencilla y rápida, como este Generador de Sprite CSS. El resultado que obtendremos de esta herramienta será una salida de CSS y una imagen con la combinación de todas las que queremos.

Una biblioteca de iconos muy usados son los iconos silk de la página fam fam fam pero estos iconos vienen separados cada uno en su propio archivo y la mayoría tiene un tamaño de medio KiB asi que usando un sprite podemos beneficiarnos de la ventajas usando esta técnica. Lo primero que haremos es obtener y poner en una carpeta los iconos que queramos tener en un sprite, posteriormente crearemos un archivo zip, luego usaremos la herramienta de sprites que queramos.

Parte del CSS que obtenemos es:

Y un trozo de la imagen del sprite es:
Posteriormente para usar el sprite el html de nuestra página sería, incluyendo el CSS que hemos obtenido y aplicando los estilos a una imagen que en el src tiene una imagen con un pixel transparente:

Si te ha resultado interesante esta entrada quizá te interese también como hacer hojas de estilo css pero con el lenguaje de less, mucho más legible y mantenible que con css directamente.

Referencia:
http://es.spritegen.website-performance.org/
http://www.famfamfam.com/

viernes, 16 de noviembre de 2012

Como enviar un archivo con Apache Tapestry

Apache Tapestry
Si en la entrada anterior explique un ejemplo de como devolver un archivo con Apache Tapestry desde el servidor al cliente en esta vamos a ver la operación contraria, enviar un archivo del cliente al servidor con Apache Tapestry a través de un formulario html.

En una aplicación web el enviar un archivo al servidor se realiza con un campo <input type="file" /> pero en el servidor se trata de forma especial para recibirlo. Dado que no es tan simple recibir un archivo como recibir un dato de un campo file como de otros campos (text, radio, select) que son únicamente una cadena lo habitual será usar alguna librería que nos facilite la tarea o a través de las facilidades que nos proporcione el framework que usemos.

Con Tapestry para subir un archivo al servidor tenemos que modificar el html para el formulario e indicar el atributo enctype="multipart/form-data" de la siguiente forma:

En Tapestry disponemos de un componente que generará el html de un <input type="file" />:

En la parte del servidor en el código java de la página o componente tendremos un atributo para recibir el archivo seleccionado por el usuario (de nombre igual al atributo value del componente t:upload):

Esto será suficiente para recibir el archivo, con la referencia al objeto UploadedFile podremos obtener el nombre del archivo, tamaño y el InputStream para obtener su contenido. Finalmente, para hacer la subida de archivos en Tapestry necesitaremos incluir la siguiente dependencia en la versión específica que usemos:

Si desarrollamos una aplicación para ser ejecutada en el Google App Engine (GAE) deberemos hacer otras modificaciones para que la subida de archivos funcione correctamente. Añadiremos al descriptor del GAE appengine-web.xml la siguiente propiedad y redefiniremos el servicio FileItemFactory de la forma en que se hace en los siguientes enlaces de ejemplo [1], [2]:

En el código fuente de la siguiente aplicación se puede ver un ejemplo completo y fucionando.

Referencia:
http://tapestry.apache.orghttp://tapestry.apache.org/uploading-files.html
Documentación sobre Apache Tapestry

sábado, 10 de noviembre de 2012

Como devolver un archivo con Apache Tapestry

Apache Tapestry
En esta entrada voy a explicar como enviar un archivo al cliente desde el servidor usando el framework Apache Tapestry. Esto es necesario si por ejemplo nuestra aplicación necesita generar un informe ya sea en formato txt, excel, pdf, un archivo comprimido o de cualquier otro tipo.

En tapestry el proceso no es muy complicado, tan solo deberemos devolver un objeto que implemente la interfaz StreamResponse en el manejador de evento («event handler») que procesa la petición.

Aquí el código de parte de un manejador de evento que construye y devuelve un objeto que implementa la interfaz StreamResponse:

Una posible implementación de la clase StreamResponse podría ser la siguiente que podríamos reutilizar siempre que tengamos que devolver un archivo:

Si estuviésemos devolviendo un archivo de texto y si el cliente acepta compresión gzip según las cabeceras que nos ha enviado en la petición (Accept-encoding: gzip) podríamos devolver el resultado comprimido con este formato ahorrado ancho de banda y muy posiblemente reduciendo el tiempo de descarga del archivo. Haciendo uso del servicio ResponseCompressionAnalyzer y del método isGZipSupported podemos averiguarlo de forma muy sencilla.

En la siguiente entrada de documentación sobre Apache Tapestry puedes encontrar más entradas, ejemplos y documentación.

Para finalizar, decir que la forma indicada en este ejemplo para convertir el OutputStream al InputStream que necesita el objeto StreamResponse puede ser mejorado con el uso de un PipedInputStream. La manera indicada en el ejemplo con el ByteArrayOuputStream obliga a mantener en memoria el contenido completo generado antes de ser enviado al cliente además de no empezar a enviarlo hasta que se genera por completo, si se trata de unos pocos MiB puede ser suficiente pero si son varias decenas la aplicación puede presentar algún problema en el uso de memoria.

Referencia:
http://tapestry.apache.org
http://betterexplained.com/articles/how-to-optimize-your-site-with-gzip-compression/

sábado, 3 de noviembre de 2012

Convertir imágenes entre formatos y cambiar tamaño con ImageMagick

ImageMagick
Algunas personas que trabajan con muchas imágenes seguramente se han encontrado en la situación de querer convertir imágenes de un formato a otros o cambiarles de tamaño de forma masiva. Hacerlo de forma manual es un trabajo aburrido y repetitivo además de consumir mucho tiempo que será mayor o menor dependiendo de la cantidad de imágenes a tratar. En esta situación ImageMagick y unos pocos comandos en la terminal de Linux nos pueden ahorrar una buena cantidad de tiempo además de evitar posibles errores al hacer las cosas manualmente. Para convertir imágenes de un formato a otro podremos hacerlo con:

Esto convierte todas las imágenes de extensión png del directorio actual a imágenes en formato jpg cambiándoles además a los nombres de los archivos la extensión de «.png» a «*.jpg». También podríamos cambiar el tamaño de las imagenes a una determinada anchura máxima o a una altura máxima de forma masiva con:

El primer comando reescala la anchura de las imagenes a 400 píxeles y el segundo a 300 píxeles de altura en ambos casos manteniendo la proporción de las imágenes originales y en ambos casos sobrescribiendo la imagen original.
También podemos hacer uso del comando específico para realizar escalados:

Para instalar ImageMagick en Arch Linux basta con instalar su correspondiente paquete después de lo cual dispondremos de los comandos convert y mogrify:

Otra cosa que a veces es necesaria es añadir marcas de agua a las imágenes, para esto ImageMagick también es muy útil y se puede automatizar posiblemente ahorrando mucho tiempo, evitando errores al hacerlo manualmente y hacerlo de forma exactamente igual para todas las imágenes.

Referencia:
Documentación comando convert
Añadir marcas de agua a imágenes con ImageMagick