from PIL import Image
from PIL import ImageDraw


def render(animation, out, scale=8):
  images = [render_frame(colors, scale=scale) for colors in animation]
  save_gif(out, *images)

def render_frame(colors, scale=8):
  led_count = 53
  size = (led_count * scale, scale)

  im = Image.new("RGB", size, "black")
  d = ImageDraw.Draw(im)
  for idx, color in enumerate(colors):
    color = tuple(map(int, color))
    x0 = scale * idx
    y0 = 0
    x1 = scale * (idx + 1)
    y1 = scale
    d.rectangle((x0, y0, x1, y1), fill=color)
  return im

def save_gif(out, image, *more_images):
  image.save(out, save_all=True,
             append_images=list(more_images),
             loop=1000,
             duration=50)

from PIL import Image
from PIL import ImageDraw


def render(animation, out, scale=8):
  images = [render_frame(colors, scale=scale) for colors in animation]
  save_gif(out, *images)

def render_frame(colors, scale=8):
  led_count = 53
  size = (led_count * scale, scale)

  im = Image.new("RGB", size, "black")
  d = ImageDraw.Draw(im)
  for idx, color in enumerate(colors):
    color = tuple(map(int, color))
    x0 = scale * idx
    y0 = 0
    x1 = scale * (idx + 1)
    y1 = scale
    d.rectangle((x0, y0, x1, y1), fill=color)
  return im

def save_gif(out, image, *more_images):
  delay_ms = 1000 * 0.035
  image.save(out, save_all=True,
             append_images=list(more_images),
             duration=delay_ms, optimize=True)

Optimize GIF palette (too many colors right now), better GIF timing options.
Optimize GIF palette (too many colors right now), better GIF timing options.

  from PIL import Image
  from PIL import ImageDraw
  
  
  def render(animation, out, scale=8):
    images = [render_frame(colors, scale=scale) for colors in animation]
    save_gif(out, *images)
  
  def render_frame(colors, scale=8):
    led_count = 53
    size = (led_count * scale, scale)
  
    im = Image.new("RGB", size, "black")
    d = ImageDraw.Draw(im)
    for idx, color in enumerate(colors):
      color = tuple(map(int, color))
      x0 = scale * idx
      y0 = 0
      x1 = scale * (idx + 1)
      y1 = scale
      d.rectangle((x0, y0, x1, y1), fill=color)
    return im
  
  def save_gif(out, image, *more_images):
+   delay_ms = 1000 * 0.035
    image.save(out, save_all=True,
               append_images=list(more_images),
+              duration=delay_ms, optimize=True)
-              loop=1000,
-              duration=50)
  
Optimize GIF palette (too many colors right now), better GIF timing options.
## Code Before:
from PIL import Image
from PIL import ImageDraw


def render(animation, out, scale=8):
  images = [render_frame(colors, scale=scale) for colors in animation]
  save_gif(out, *images)

def render_frame(colors, scale=8):
  led_count = 53
  size = (led_count * scale, scale)

  im = Image.new("RGB", size, "black")
  d = ImageDraw.Draw(im)
  for idx, color in enumerate(colors):
    color = tuple(map(int, color))
    x0 = scale * idx
    y0 = 0
    x1 = scale * (idx + 1)
    y1 = scale
    d.rectangle((x0, y0, x1, y1), fill=color)
  return im

def save_gif(out, image, *more_images):
  image.save(out, save_all=True,
             append_images=list(more_images),
             loop=1000,
             duration=50)

## Instruction:
Optimize GIF palette (too many colors right now), better GIF timing options.
## Code After:
from PIL import Image
from PIL import ImageDraw


def render(animation, out, scale=8):
  images = [render_frame(colors, scale=scale) for colors in animation]
  save_gif(out, *images)

def render_frame(colors, scale=8):
  led_count = 53
  size = (led_count * scale, scale)

  im = Image.new("RGB", size, "black")
  d = ImageDraw.Draw(im)
  for idx, color in enumerate(colors):
    color = tuple(map(int, color))
    x0 = scale * idx
    y0 = 0
    x1 = scale * (idx + 1)
    y1 = scale
    d.rectangle((x0, y0, x1, y1), fill=color)
  return im

def save_gif(out, image, *more_images):
  delay_ms = 1000 * 0.035
  image.save(out, save_all=True,
             append_images=list(more_images),
             duration=delay_ms, optimize=True)
