Creador de GIFs para Slack
Un conjunto de herramientas que proporciona utilidades y conocimiento para crear GIFs animados optimizados para Slack.
Requisitos de Slack
Dimensiones:
- GIFs de emoji: 128x128 (recomendado)
- GIFs de mensaje: 480x480
Parámetros:
- FPS: 10-30 (menor FPS = tamaño de archivo más pequeño)
- Colores: 48-128 (menos colores = tamaño de archivo más pequeño)
- Duración: Mantener por debajo de 3 segundos para GIFs de emoji
Flujo de trabajo principal
from core.gif_builder import GIFBuilder
from PIL import Image, ImageDraw
# 1. Crear el constructor
builder = GIFBuilder(width=128, height=128, fps=10)
# 2. Generar cuadros
for i in range(12):
frame = Image.new('RGB', (128, 128), (240, 248, 255))
draw = ImageDraw.Draw(frame)
# Dibuje su animación usando primitivas de PIL
# (círculos, polígonos, líneas, etc.)
builder.add_frame(frame)
# 3. Guardar con optimización
builder.save('output.gif', num_colors=48, optimize_for_emoji=True)
Dibujar gráficos
Trabajar con imágenes subidas por el usuario
Si un usuario sube una imagen, considere si quiere:
- Usarla directamente (ej., "anima esto", "divide esto en cuadros")
- Usarla como inspiración (ej., "haz algo como esto")
Cargue y trabaje con imágenes usando PIL:
from PIL import Image
uploaded = Image.open('archivo.png')
# Úsela directamente, o solo como referencia para colores/estilo
Dibujar desde cero
Cuando dibuje gráficos desde cero, use las primitivas de PIL ImageDraw:
from PIL import ImageDraw
draw = ImageDraw.Draw(frame)
# Círculos/óvalos
draw.ellipse([x1, y1, x2, y2], fill=(r, g, b), outline=(r, g, b), width=3)
# Estrellas, triángulos, cualquier polígono
puntos = [(x1, y1), (x2, y2), (x3, y3), ...]
draw.polygon(puntos, fill=(r, g, b), outline=(r, g, b), width=3)
# Líneas
draw.line([(x1, y1), (x2, y2)], fill=(r, g, b), width=5)
# Rectángulos
draw.rectangle([x1, y1, x2, y2], fill=(r, g, b), outline=(r, g, b), width=3)
No use: Fuentes de emoji (no confiables entre plataformas) ni asuma que existen gráficos preempaquetados en esta habilidad.
Hacer que los gráficos se vean bien
Los gráficos deben verse pulidos y creativos, no básicos. Aquí le mostramos cómo:
Use líneas más gruesas - Siempre establezca width=2 o más para contornos y líneas. Las líneas finas (width=1) se ven entrecortadas y poco profesionales.
Agregue profundidad visual:
- Use gradientes para fondos (
create_gradient_background) - Superponga múltiples formas para mayor complejidad (ej., una estrella con una estrella más pequeña dentro)
Haga las formas más interesantes:
- No dibuje solo un círculo simple: agregue reflejos, anillos o patrones
- Las estrellas pueden tener resplandores (dibuje versiones más grandes y semitransparentes detrás)
- Combine múltiples formas (estrellas + destellos, círculos + anillos)
Preste atención a los colores:
- Use colores vibrantes y complementarios
- Agregue contraste (contornos oscuros sobre formas claras, contornos claros sobre formas oscuras)
- Considere la composición general
Para formas complejas (corazones, copos de nieve, etc.):
- Use combinaciones de polígonos y elipses
- Calcule los puntos cuidadosamente para lograr simetría
- Agregue detalles (un corazón puede tener una curva de resalte, los copos de nieve tienen ramas intrincadas)
¡Sea creativo y detallado! Un buen GIF de Slack debe verse pulido, no como gráficos de marcador de posición.
Utilidades disponibles
GIFBuilder (core.gif_builder)
Ensambla cuadros y optimiza para Slack:
builder = GIFBuilder(width=128, height=128, fps=10)
builder.add_frame(frame) # Agregar imagen PIL
builder.add_frames(frames) # Agregar lista de cuadros
builder.save('out.gif', num_colors=48, optimize_for_emoji=True, remove_duplicates=True)
Validadores (core.validators)
Verifica si el GIF cumple con los requisitos de Slack:
from core.validators import validate_gif, is_slack_ready
# Validación detallada
passes, info = validate_gif('my.gif', is_emoji=True, verbose=True)
# Verificación rápida
if is_slack_ready('my.gif'):
print("¡Listo!")
Funciones de interpolación (core.easing)
Movimiento suave en lugar de lineal:
from core.easing import interpolate
# Progreso de 0.0 a 1.0
t = i / (num_frames - 1)
# Aplicar interpolación
y = interpolate(start=0, end=400, t=t, easing='ease_out')
# Disponibles: linear, ease_in, ease_out, ease_in_out,
# bounce_out, elastic_out, back_out
Ayudantes de cuadro (core.frame_composer)
Funciones de conveniencia para necesidades comunes:
from core.frame_composer import (
create_blank_frame, # Fondo de color sólido
create_gradient_background, # Gradiente vertical
draw_circle, # Ayudante para círculos
draw_text, # Representación simple de texto
draw_star # Estrella de 5 puntas
)
Conceptos de animación
Sacudida/Vibración
Desplazar la posición del objeto con oscilación:
- Use
math.sin()omath.cos()con el índice del cuadro - Agregue pequeñas variaciones aleatorias para una sensación natural
- Aplique a la posición x y/o y
Pulso/Latido
Escalar el tamaño del objeto rítmicamente:
- Use
math.sin(t * frecuencia * 2 * math.pi)para un pulso suave - Para latido: dos pulsos rápidos y luego pausa (ajuste la onda sinusoidal)
- Escale entre 0.8 y 1.2 del tamaño base
Rebote
El objeto cae y rebota:
- Use
interpolate()coneasing='bounce_out'para el aterrizaje - Use
easing='ease_in'para la caída (aceleración) - Aplique gravedad aumentando la velocidad en y cada cuadro
Giro/Rotación
Rotar el objeto alrededor del centro:
- PIL:
image.rotate(angle, resample=Image.BICUBIC) - Para tambaleo: use onda sinusoidal para el ángulo en lugar de lineal
Desvanecimiento de entrada/salida
Aparecer o desaparecer gradualmente:
- Cree una imagen RGBA, ajuste el canal alfa
- O use
Image.blend(imagen1, imagen2, alpha) - Desvanecimiento de entrada: alfa de 0 a 1
- Desvanecimiento de salida: alfa de 1 a 0
Deslizamiento
Mover el objeto desde fuera de la pantalla hasta su posición:
- Posición inicial: fuera de los límites del cuadro
- Posición final: ubicación objetivo
- Use
interpolate()coneasing='ease_out'para una parada suave - Para sobrepaso: use
easing='back_out'
Zoom
Escalar y posicionar para efecto de zoom:
- Acercar: escala de 0.1 a 2.0, recortar centro
- Alejar: escala de 2.0 a 1.0
- Puede agregar desenfoque de movimiento para dramatismo (filtro PIL)
Explosión/Ráfaga de partículas
Crear partículas que se irradian hacia afuera:
- Genere partículas con ángulos y velocidades aleatorias
- Actualice cada partícula:
x += vx,y += vy - Agregue gravedad:
vy += constante_gravedad - Desvanezca las partículas con el tiempo (reduzca alfa)
Estrategias de optimización
Solo cuando se le solicite hacer el tamaño de archivo más pequeño, implemente algunos de los siguientes métodos:
- Menos cuadros - FPS más bajo (10 en lugar de 20) o duración más corta
- Menos colores -
num_colors=48en lugar de 128 - Dimensiones más pequeñas - 128x128 en lugar de 480x480
- Eliminar duplicados -
remove_duplicates=Trueen save() - Modo emoji -
optimize_for_emoji=Trueoptimiza automáticamente
# Optimización máxima para emoji
builder.save(
'emoji.gif',
num_colors=48,
optimize_for_emoji=True,
remove_duplicates=True
)
Filosofía
Esta habilidad proporciona:
- Conocimiento: Requisitos de Slack y conceptos de animación
- Utilidades: GIFBuilder, validadores, funciones de interpolación
- Flexibilidad: Cree la lógica de animación usando primitivas de PIL
NO proporciona:
- Plantillas de animación rígidas o funciones predefinidas
- Representación de fuentes de emoji (no confiables entre plataformas)
- Una biblioteca de gráficos preempaquetados integrados en la habilidad
Nota sobre cargas de usuarios: Esta habilidad no incluye gráficos preconstruidos, pero si un usuario sube una imagen, use PIL para cargarla y trabajar con ella; interprete según su solicitud si quiere usarla directamente o solo como inspiración.
¡Sea creativo! Combine conceptos (rebotando + girando, pulsando + deslizando, etc.) y use todas las capacidades de PIL.
Dependencias
pip install pillow imageio numpy