title: Gifs read with Pillow have black borders
body: <p>I am reading gifs with Pillow, this code outputs every frame from a gif file as .gif and .png with and without converting to RGBA.</p>
  <p>I'll discuss the issues below, after showing the results</p>
  <pre class="lang-py prettyprint-override"><code>from PIL import Image
  
  # Download link below
  image = Image.open('PepePls.gif')
  
  loop = []
  frames = []
  durations = []
  try:
      while True:
          loop.append(image.info.get('loop', None))
          frame = image.copy()
          frames.append(frame)
          durations.append(image.info.get('duration', None))
          image.seek(image.tell() + 1)
  except EOFError:
      pass
  
  for i in range(len(frames)):
      print(f'#{i} loop = {loop[i]} duration = {durations[i]} mode = {frames[i].mode}')
      frames[i].save(f'gif_f{i}.gif')
      frames[i].save(f'png_f{i}.png')
      frames[i].convert(mode='RGBA').save(f'rgba_gif_f{i}.gif')
      frames[i].convert(mode='RGBA').save(f'rgba_png_f{i}.png')
  </code></pre>
  <p>Results, console output then explorer.exe screenshot:</p>
  <pre><code>#0 loop = 0 duration = 70 mode = P
  #1 loop = None duration = 70 mode = P
  #2 loop = None duration = 70 mode = P
  #3 loop = None duration = 70 mode = P
  #4 loop = None duration = 70 mode = P
  #5 loop = None duration = 70 mode = P
  #6 loop = None duration = 70 mode = P
  #7 loop = None duration = 70 mode = P
  #8 loop = None duration = 70 mode = P
  #9 loop = None duration = 70 mode = P
  #10 loop = None duration = 70 mode = P
  #11 loop = None duration = 70 mode = P
  #12 loop = None duration = 70 mode = P
  #13 loop = None duration = 70 mode = P
  #14 loop = None duration = 70 mode = P
  #15 loop = None duration = 70 mode = P
  #16 loop = None duration = 70 mode = P
  #17 loop = None duration = 70 mode = P
  #18 loop = None duration = 70 mode = P
  #19 loop = None duration = 70 mode = P
  #20 loop = None duration = 70 mode = P
  </code></pre>
  <p><a href="https://i.stack.imgur.com/vFPgK.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/vFPgK.png" alt="resulting frames" /></a></p>
  <p>Issues:</p>
  <ol>
  <li><p>Why did rgba gifs lose the transparency? And where does the background color comes from</p>
  </li>
  <li><p>Why are there black borders everywhere? I know from using GIMP a bit that gif frames can be combined or replace the previous one, does this explain what I'm seeing or is something else? (while on the topic, does Pillow handle combine/replace frames gifs on itw own?)</p>
  </li>
  <li><p>Not sure what's happening with the image size, explorer.exe says 68x104 but frames saved by Pillow are all 85x112 (firefox also says 85x112 when viewing the input gif file)</p>
  </li>
  </ol>
  <p>Find <a href="https://cdn.betterttv.net/emote/55898e122612142e6aaa935b/3x" rel="nofollow noreferrer">PepePls.gif here</a></p>
  <p>I have a similar issue with <a href="https://cdn.betterttv.net/emote/5b369beff037d44c5936ff13/3x" rel="nofollow noreferrer">this one too</a></p>
  <h1>EDIT:</h1>
  <p>I am pretty sure after a lot of research and reading the Pillow source code <a href="https://github.com/python-pillow/Pillow/blob/master/src/PIL/GifImagePlugin.py" rel="nofollow noreferrer">https://github.com/python-pillow/Pillow/blob/master/src/PIL/GifImagePlugin.py</a> that black borders are a bug, and it must be linked to the fact that each frame is drawn on a background of the inappropriate color (probably not checking the palette/color/transparency index at all)</p>
  <p>Here's what I achieved replacing <code>frame = image.copy()</code> in the above code by</p>
  <pre><code>frame = Image.new('RGBA', (85, 112), color=(255,0,0,0))
  frame.paste(image.crop(image.dispose_extent), box=(image.dispose_extent[0],image.dispose_extent[1]))
  </code></pre>
  <p>May want to use <code>image.tile[0][1]</code> instead of <code>image.dispose_extent</code> but I'm really not sure</p>
  <p><a href="https://i.stack.imgur.com/l4RfE.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/l4RfE.png" alt="new results" /></a></p>
  <p>It also seems to show that Pillow doesn't like gifs with transparency at all</p>
  <h1>EDIT 2:</h1>
  <p>I fixed black borders and combine/replace frames by using this:</p>
  <pre class="lang-py prettyprint-override"><code>from PIL import Image
  
  gif = 'PeepoCreepo.gif'
  #gif = 'PepePls.gif'
  
  image = Image.open(gif)
  
  frames = []
  
  disposal_method_last = 0
  
  try:
      while True:
          disposal_method = disposal_method_last
          disposal_method_last = image.__dict__.get('disposal_method', 0)
          if disposal_method == 2 or (disposal_method == 1 and frames == []):
              frame = Image.new('RGBA', image.size, color=(255,0,0,0))
              frame.paste(image.crop(image.dispose_extent), box=(image.dispose_extent[0],image.dispose_extent[1]))
          elif disposal_method == 1:
              newStuff = image.crop(image.dispose_extent)
              frame = frames[-1].copy()
              frame.paste(newStuff, image.dispose_extent, newStuff.convert(&quot;RGBA&quot;))
          else:
              frame = image.copy()
          frames.append(frame)
          image.seek(image.tell() + 1)
  except EOFError:
      pass
  
  for i in range(len(frames)):
      frames[i].convert(mode='RGBA').save(f'f{i}.png')
  </code></pre>
  <p><a href="https://i.stack.imgur.com/PKaxn.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/PKaxn.png" alt="PeepoCreepo frames almost perfect" /></a></p>
  <p>One issue I still see is if you zoom on f2.png you can see some of the black in the eyes is missing. This is not an issue from the gif file, as gimp can open and display each frame properly:</p>
  <p><a href="https://i.stack.imgur.com/GOCym.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/GOCym.png" alt="PeepoCreepo gif frames in gimp" /></a></p>
  <h1>EDIT3:</h1>
  <p><a href="https://github.com/python-pillow/Pillow/issues/4640" rel="nofollow noreferrer">Opened an issue on Github</a></p>
  <h1>EDIT4:</h1>
  <p>The Github issue has been marked as fixed!</p>