Ayer tuvimos una caída en una web de una empresa. El servidor colapsó por falta de ancho de banda y memoria. ¿El motivo? El equipo de marketing había decidido actualizar el catálogo de otoño y volcó directamente cientos de fotos RAW de 10 Megabytes por archivo en la carpeta FTP que el sistema lee para la tienda online.

Estamos muy acostumbrados a lidiar con números y cadenas de texto, pero tratamos a las imágenes como ciudadanos de segunda clase. Simplemente guardamos la ruta del .jpg en la base de datos relacional y nos desentendemos. Eso se ha acabado. He metido el procesamiento de imágenes directamente en el flujo de datos nocturno.

Automatizando la compresión gráfica

La solución pasa por interceptar los ficheros antes de que toquen el servidor web, normalizarlos, redimensionarlos a tres tamaños estándar (miniatura, catálogo y zoom detallado) y comprimirlos para web.

Aunque existen herramientas de línea de comandos brutales como ImageMagick (cuyo comando mogrify puede hacerlo en un bash script), he preferido integrarlo en nuestro pipeline de Python usando la librería PIL (bueno, su fork amigable, Pillow).

import os
from PIL import Image

ruta_origen = '/datos/ftp/marketing/crudos/'
ruta_destino = '/var/www/ecommerce/imagenes/optimizadas/'

def optimizar_catalogo():
    for archivo in os.listdir(ruta_origen):
        if archivo.lower().endswith(('.jpg', '.jpeg', '.png')):
            ruta_completa = os.path.join(ruta_origen, archivo)

            try:
                # Abrimos la imagen original
                img = Image.open(ruta_completa)

                # Forzamos formato RGB (por si vienen CMYK de imprenta)
                if img.mode != 'RGB':
                    img = img.convert('RGB')

                # Redimensionamos manteniendo la proporción (máximo 800x800)
                img.thumbnail((800, 800), Image.ANTIALIAS)

                # Guardamos comprimido con calidad 85% progresivo
                nombre_salida = os.path.join(ruta_destino, "web_" + archivo)
                img.save(nombre_salida, 'JPEG', quality=85, progressive=True)

                print "Optimizada:", archivo
            except Exception as e:
                print "Error con", archivo, ":", str(e)

optimizar_catalogo()

Este script es súper tonto, pero ha reducido la carga de la página de inicio en un 90%. El FTP de marketing sigue siendo un desastre, pero ahora nuestro ETL actúa de filtro sanitario.

Reflexión: La imagen como dato puro

Tratar las imágenes programáticamente me ha hecho pensar. Por ahora, para nosotros una imagen es solo un bloque de datos binarios (BLOB) que ocupa espacio en disco. Pero, esto tiene que cambiar.

Hay que cambiar la mentalidad: Cuando metamos una imagen en el ETL corporativo, no solo la redimensionaremos. Ejecutaremos un modelo que extraerá el color predominante, detectará si el modelo de la foto lleva gafas o incluso etiquetará automáticamente las prendas de ropa, insertando esos metadatos directamente en nuestra base de datos para mejorar las búsquedas. Las imágenes están a punto de convertirse en bases de datos por sí mismas.