GIF: Formato de Intercambio de Gráficos para Animación y Gráficos
GIF (Graphics Interchange Format) fue introducido en 1987 como formato de imagen independiente de plataforma. Aunque GIF ha sido superado por PNG (gráficos lossless), WebP (animación) y vídeo moderno, GIF sigue siendo ubicuo para animaciones simples, memes y compatibilidad web. Comprender la estructura GIF es esencial para contenido web heredado y optimizar gráficos animados.
Estructura de Archivo GIF: Encabezado y Descriptor de Pantalla Lógica
Cada archivo GIF sigue una estructura binaria estricta:
G I F 8 9 a (firma — 'GIF89a' para animado, 'GIF87a' para estático)
[Descriptor de Pantalla Lógica — 7 bytes]
[Tabla de Color Global — opcional, hasta 768 bytes]
[Flujo de datos — imágenes, texto, extensiones]
; (terminador — marca el final)
Descriptor de Pantalla Lógica (7 bytes):
Byte 0-1: Ancho del Lienzo (16-bit little-endian)
Byte 2-3: Alto del Lienzo (16-bit little-endian)
Byte 4: Campos Empaquetados
Bit 7: Bandera de Tabla de Color Global (1 = presente)
Bits 6-4: Resolución de Color (bits por píxel - 1)
Bit 3: Bandera de Ordenamiento (1 = ordenado por luminancia)
Bits 2-0: Tamaño de Tabla de Color Global (2^(N+1) colores)
Byte 5: Índice de Color de Fondo (en paleta global)
Byte 6: Relación de Aspecto de Píxel (0 = píxeles cuadrados)
Ejemplo (GIF 256×256 con paleta de 256 colores, sin ordenamiento):
Ancho: 00 01 (256 píxeles, little-endian)
Alto: 00 01 (256 píxeles)
Empaquetado: F7 (11110111 binario)
bit 7=1 (tabla de color global presente)
bits 6-4=111 (8 bits por píxel = 256 colores)
bit 3=0 (no ordenado)
bits 2-0=111 (tamaño = 2^(7+1) = 256)
Fondo: 00 (color 0)
Aspecto: 00 (relación 1:1)
Paleta de Colores: Tablas Global y Local
GIF usa color indexado—cada píxel es un índice (0–255) en una tabla de colores:
Tabla de Color Global (GCT):
256 entradas × 3 bytes (RGB) = máximo 768 bytes
Entrada 0: [R0 G0 B0]
Entrada 1: [R1 G1 B1]
…
Entrada 255: [R255 G255 B255]
Tabla de Color Local (LCT, por imagen):
[Descriptor de Imagen]
[Tabla de Color Local — opcional, anula global]
[Datos de Imagen]
Usada cuando una imagen necesita una paleta diferente que la global (p.ej., primer fotograma usa colores cálidos, segundo usa colores fríos).
Transparencia:
[Extensión de Control Gráfico]
Byte 0: Bandera de Transparencia (1 = color transparente especificado)
Byte 1: Índice de Color Transparente (p.ej., 255 = magenta es transparente)
Los píxeles con índice que coincide con el índice de color transparente se renderean como transparentes (solo transparencia de 1 bit—completamente opaco o completamente transparente, sin mezcla alfa).
Compresión LZW: Codificación Basada en Diccionario
GIF usa compresión LZW (Lempel-Ziv-Welch)—un algoritmo lossless optimizado para datos de paleta:
Proceso de codificación LZW:
Entrada: [secuencia de índices de escanlines]
256 códigos iniciales (uno por entrada de paleta)
Códigos 256+ construidos dinámicamente conforme patrones emergen
Escanline: [0] [1] [0] [1] [0] [1] [2] …
Códigos: [0] [1] [0] [1] [0] [1] [2] [256=01] [257=10] …
Salida: [0] [1] [256] [257] [2]…
Resultado: patrones frecuentes (p.ej., colores alternados en gradientes) se codifican como códigos únicos, logrando ~30–50% compresión en gráficos.
Animación: Extensión de Control Gráfico y Descriptor de Imagen
Extensión de Control Gráfico (8 bytes):
Byte 0: Introductor de Extensión (0x21)
Byte 1: Etiqueta de Control Gráfico (0xF9)
Byte 2: Tamaño de Bloque (siempre 4)
Byte 3: Campos Empaquetados
Bit 7-5: Reservado
Bits 4-2: Método de Disposición (0=ninguno, 1=dejar, 2=restaurar fondo, 3=restaurar anterior)
Bit 1: Bandera de Entrada de Usuario (1 = animación pausa por entrada de usuario)
Bit 0: Bandera de Transparencia (1 = color transparente sigue)
Bytes 4-5: Tiempo de Retardo (unidades 10ms, little-endian)
p.ej., 5 = 50ms (20 FPS)
Byte 6: Índice de Color Transparente
Byte 7: Terminador de Bloque (0x00)
Descriptor de Imagen (10 bytes):
Byte 0: Separador de Imagen (0x2C)
Bytes 1-2: Posición Izquierda de Imagen
Bytes 3-4: Posición Superior de Imagen
Bytes 5-6: Ancho de Imagen
Bytes 7-8: Alto de Imagen
Byte 9: Campos Empaquetados
Bit 7: Bandera de Tabla de Color Local
Bit 6: Bandera de Entrelazado (1 = entrelazado Adam7 de 4 pasadas)
Bit 5: Bandera de Ordenamiento
Bits 2-0: Tamaño de LCT
Estructura de animación (GIF de 3 fotogramas):
[Encabezado GIF + Tabla de Color Global]
[Extensión de Control Gráfico — fotograma 1, retardo 50ms]
[Descriptor de Imagen — imagen 1]
[Datos de imagen comprimidos LZW]
[Extensión de Control Gráfico — fotograma 2, retardo 50ms]
[Descriptor de Imagen — imagen 2]
[Datos de imagen comprimidos LZW]
[Extensión de Control Gráfico — fotograma 3, retardo 50ms]
[Descriptor de Imagen — imagen 3]
[Datos de imagen comprimidos LZW]
[Terminador — 0x3B]
Entrelazado: Renderización Progresiva de 4 Pasadas
GIF soporta entrelazado para visualización progresiva:
Pasada 1: filas 0, 8, 16, 24… (cada 8ª fila)
Pasada 2: filas 4, 12, 20, 28… (cada 8ª, desplazamiento 4)
Pasada 3: filas 2, 6, 10, 14… (cada 4ª, desplazamiento 2)
Pasada 4: filas 1, 3, 5, 7… (cada 2ª, filas impares)
GIF entrelazado muestra vista previa aproximada primero, refina progresivamente. Compensación: ~10% archivo más grande (debido a pasadas de codificación adicionales).
GIF vs. Alternativas Modernas
| Métrica | GIF | PNG | WebP | MP4 (H.264) |
|---|---|---|---|---|
| Animado | ✅ | ❌ (existe APNG) | ✅ | ✅ |
| Limitación de paleta | 256 colores máx | Ilimitado | Ilimitado | Ilimitado |
| Transparencia | 1-bit (binaria) | Alfa completa (8-bit) | Alfa completa | Alfa completa |
| Tamaño de archivo (animación) | 2 MB (grande) | 500 KB (APNG) | 400 KB (WebP) | 100 KB (MP4 H.264) |
| Soporte de navegadores | 100% | 100% | 97% | 95% |
| Sin patentes | ⚠️ (patente LZW expirada 2003) | ✅ | ✅ | ⚠️ (MPEG LA) |
Recomendación moderna: Reemplaza GIF con WebP (mejor compresión) o MP4/WebM (vídeo—compresión muy superior).
Creación y Optimización de GIFs
FFmpeg (MP4 → GIF, 10 FPS):
ffmpeg -i entrada.mp4 -vf fps=10 -c:v gif salida.gif
ffmpeg -i entrada.mp4 -vf "scale=480:-1,fps=10" salida.gif
ImageMagick (secuencia de imagen → GIF animado):
convert -delay 10 -loop 0 fotograma*.png animado.gif
convert -delay 10 animado.gif -resize 50% optimizado.gif
Python (Pillow):
from PIL import Image
frames = [Image.open(f) for f in ['fotograma1.png', 'fotograma2.png']]
frames[0].save('salida.gif', save_all=True, append_images=frames[1:], duration=100, loop=0)
Optimización (gifsicle):
gifsicle -b -O3 --lossy=80 entrada.gif -o salida.gif
GIF sigue siendo importante para memes y web heredada, pero para nuevos proyectos, animaciones WebP o vídeo son superiores.
Conversiones relacionadas
Lo más habitual al trabajar con imágenes son estas direcciones de conversión: