#
# The Python Imaging Library.
# $Id$
#
# FLI/FLC file handling.
#
# History:
#       95-09-01 fl     Created
#       97-01-03 fl     Fixed parser, setup decoder tile
#       98-07-15 fl     Renamed offset attribute to avoid name clash
#
# Copyright (c) Secret Labs AB 1997-98.
# Copyright (c) Fredrik Lundh 1995-97.
#
# See the README file for information on usage and redistribution.
#


from . import Image, ImageFile, ImagePalette
from ._binary import i8, i16le as i16, i32le as i32, o8

__version__ = "0.2"


#
# decoder

def _accept(prefix):
    return len(prefix) >= 6 and i16(prefix[4:6]) in [0xAF11, 0xAF12]


##
# Image plugin for the FLI/FLC animation format.  Use the <b>seek</b>
# method to load individual frames.

class FliImageFile(ImageFile.ImageFile):

    format = "FLI"
    format_description = "Autodesk FLI/FLC Animation"
    _close_exclusive_fp_after_loading = False

    def _open(self):

        # HEAD
        s = self.fp.read(128)
        magic = i16(s[4:6])
        if not (magic in [0xAF11, 0xAF12] and
                i16(s[14:16]) in [0, 3] and  # flags
                s[20:22] == b"\x00\x00"):  # reserved
            raise SyntaxError("not an FLI/FLC file")

        # frames
        self.__framecount = i16(s[6:8])

        # image characteristics
        self.mode = "P"
        self._size = i16(s[8:10]), i16(s[10:12])

        # animation speed
        duration = i32(s[16:20])
        if magic == 0xAF11:
            duration = (duration * 1000) // 70
        self.info["duration"] = duration

        # look for palette
        palette = [(a, a, a) for a in range(256)]

        s = self.fp.read(16)

        self.__offset = 128

        if i16(s[4:6]) == 0xF100:
            # prefix chunk; ignore it
            self.__offset = self.__offset + i32(s)
            s = self.fp.read(16)

        if i16(s[4:6]) == 0xF1FA:
            # look for palette chunk
            s = self.fp.read(6)
            if i16(s[4:6]) == 11:
                self._palette(palette, 2)
            elif i16(s[4:6]) == 4:
                self._palette(palette, 0)

        palette = [o8(r)+o8(g)+o8(b) for (r, g, b) in palette]
        self.palette = ImagePalette.raw("RGB", b"".join(palette))

        # set things up to decode first frame
        self.__frame = -1
        self.__fp = self.fp
        self.__rewind = self.fp.tell()
        self.seek(0)

    def _palette(self, palette, shift):
        # load palette

        i = 0
        for e in range(i16(self.fp.read(2))):
            s = self.fp.read(2)
            i = i + i8(s[0])
            n = i8(s[1])
            if n == 0:
                n = 256
            s = self.fp.read(n * 3)
            for n in range(0, len(s), 3):
                r = i8(s[n]) << shift
                g = i8(s[n+1]) << shift
                b = i8(s[n+2]) << shift
                palette[i] = (r, g, b)
                i += 1

    @property
    def n_frames(self):
        return self.__framecount

    @property
    def is_animated(self):
        return self.__framecount > 1

    def seek(self, frame):
        if not self._seek_check(frame):
            return
        if frame < self.__frame:
            self._seek(0)

        for f in range(self.__frame + 1, frame + 1):
            self._seek(f)

    def _seek(self, frame):
        if frame == 0:
            self.__frame = -1
            self.__fp.seek(self.__rewind)
            self.__offset = 128

        if frame != self.__frame + 1:
            raise ValueError("cannot seek to frame %d" % frame)
        self.__frame = frame

        # move to next frame
        self.fp = self.__fp
        self.fp.seek(self.__offset)

        s = self.fp.read(4)
        if not s:
            raise EOFError

        framesize = i32(s)

        self.decodermaxblock = framesize
        self.tile = [("fli", (0, 0)+self.size, self.__offset, None)]

        self.__offset += framesize

    def tell(self):
        return self.__frame


#
# registry

Image.register_open(FliImageFile.format, FliImageFile, _accept)

Image.register_extensions(FliImageFile.format, [".fli", ".flc"])

src/PIL/FliImagePlugin.py
#
# The Python Imaging Library.
# $Id$
#
# FLI/FLC file handling.
#
# History:
#       95-09-01 fl     Created
#       97-01-03 fl     Fixed parser, setup decoder tile
#       98-07-15 fl     Renamed offset attribute to avoid name clash
#
# Copyright (c) Secret Labs AB 1997-98.
# Copyright (c) Fredrik Lundh 1995-97.
#
# See the README file for information on usage and redistribution.
#


from . import Image, ImageFile, ImagePalette
from ._binary import i8, i16le as i16, i32le as i32, o8

__version__ = "0.2"


#
# decoder

def _accept(prefix):
    return len(prefix) >= 6 and i16(prefix[4:6]) in [0xAF11, 0xAF12]


##
# Image plugin for the FLI/FLC animation format.  Use the <b>seek</b>
# method to load individual frames.

class FliImageFile(ImageFile.ImageFile):

    format = "FLI"
    format_description = "Autodesk FLI/FLC Animation"
    _close_exclusive_fp_after_loading = False

    def _open(self):

        # HEAD
        s = self.fp.read(128)
        magic = i16(s[4:6])
        if not (magic in [0xAF11, 0xAF12] and
                i16(s[14:16]) in [0, 3] and  # flags
                s[20:22] == b"\x00\x00"):  # reserved
            raise SyntaxError("not an FLI/FLC file")

        # frames
        self.__framecount = i16(s[6:8])

        # image characteristics
        self.mode = "P"
        self._size = i16(s[8:10]), i16(s[10:12])

        # animation speed
        duration = i32(s[16:20])
        if magic == 0xAF11:
            duration = (duration * 1000) // 70
        self.info["duration"] = duration

        # look for palette
        palette = [(a, a, a) for a in range(256)]

        s = self.fp.read(16)

        self.__offset = 128

        if i16(s[4:6]) == 0xF100:
            # prefix chunk; ignore it
            self.__offset = self.__offset + i32(s)
            s = self.fp.read(16)

        if i16(s[4:6]) == 0xF1FA:
            # look for palette chunk
            s = self.fp.read(6)
            if i16(s[4:6]) == 11:
                self._palette(palette, 2)
            elif i16(s[4:6]) == 4:
                self._palette(palette, 0)

        palette = [o8(r)+o8(g)+o8(b) for (r, g, b) in palette]
        self.palette = ImagePalette.raw("RGB", b"".join(palette))

        # set things up to decode first frame
        self.__frame = -1
        self.__fp = self.fp
        self.__rewind = self.fp.tell()
        self.seek(0)

    def _palette(self, palette, shift):
        # load palette

        i = 0
        for e in range(i16(self.fp.read(2))):
            s = self.fp.read(2)
            i = i + i8(s[0])
            n = i8(s[1])
            if n == 0:
                n = 256
            s = self.fp.read(n * 3)
            for n in range(0, len(s), 3):
                r = i8(s[n]) << shift
                g = i8(s[n+1]) << shift
                b = i8(s[n+2]) << shift
                palette[i] = (r, g, b)
                i += 1

    @property
    def n_frames(self):
        return self.__framecount

    @property
    def is_animated(self):
        return self.__framecount > 1

    def seek(self, frame):
        if not self._seek_check(frame):
            return
        if frame < self.__frame:
            self._seek(0)

        for f in range(self.__frame + 1, frame + 1):
            self._seek(f)

    def _seek(self, frame):
        if frame == 0:
            self.__frame = -1
            self.__fp.seek(self.__rewind)
            self.__offset = 128
        else:
            # ensure that the previous frame was loaded
            self.load()

        if frame != self.__frame + 1:
            raise ValueError("cannot seek to frame %d" % frame)
        self.__frame = frame

        # move to next frame
        self.fp = self.__fp
        self.fp.seek(self.__offset)

        s = self.fp.read(4)
        if not s:
            raise EOFError

        framesize = i32(s)

        self.decodermaxblock = framesize
        self.tile = [("fli", (0, 0)+self.size, self.__offset, None)]

        self.__offset += framesize

    def tell(self):
        return self.__frame


#
# registry

Image.register_open(FliImageFile.format, FliImageFile, _accept)

Image.register_extensions(FliImageFile.format, [".fli", ".flc"])

src/PIL/FliImagePlugin.py
diff --git a/Tests/images/a_fli.png b/Tests/images/a_fli.png
new file mode 100644
index 00000000000..93c3f1b1266
Binary files /dev/null and b/Tests/images/a_fli.png differ
diff --git a/Tests/test_file_fli.py b/Tests/test_file_fli.py
index 142af3cec40..2375d3749af 100644
--- a/Tests/test_file_fli.py
+++ b/Tests/test_file_fli.py
@@ -85,6 +85,13 @@ def test_seek_tell(self):
         layer_number = im.tell()
         self.assertEqual(layer_number, 1)
 
+    def test_seek(self):
+        im = Image.open(animated_test_file)
+        im.seek(50)
+
+        expected = Image.open("Tests/images/a_fli.png")
+        self.assert_image_equal(im, expected)
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/src/PIL/FliImagePlugin.py b/src/PIL/FliImagePlugin.py
index c78c8c622d5..b1eb9ae4dfd 100644
--- a/src/PIL/FliImagePlugin.py
+++ b/src/PIL/FliImagePlugin.py
@@ -131,6 +131,9 @@ def _seek(self, frame):
             self.__frame = -1
             self.__fp.seek(self.__rewind)
             self.__offset = 128
+        else:
+            # ensure that the previous frame was loaded
+            self.load()
 
         if frame != self.__frame + 1:
             raise ValueError("cannot seek to frame %d" % frame)

Using seek to skip more than one frame with FliImageFile only shows the pixels changed that frame
### What did you do?
I opened a FLI file and used .seek(50) on the image before creating a PhotoImage to display it on a tix label.

### What did you expect to happen?
I expected to see the complete image.

### What actually happened?
I only saw the part of the image that had changed for that particular frame. The rest of the image is black.

### What versions of Pillow and Python are you using?
Python 3.6.2 on Windows 7 x64
Pillow: 4.2.1

I did find that if I hack in a call to self.load() in FliImageFile's _seek() method, the frame displays fully. I don't know if this is the best way to fix the issue.

```python
import PIL as pil
from PIL import Image,ImageTk,FliImagePlugin
import tkinter.tix as tix

class FliImageFile(FliImagePlugin.FliImageFile):
    def _seek(self, frame):
        FliImagePlugin.FliImageFile._seek(self, frame)
        # ensure that this frame is loaded
        self.load()

def createlabel(root, filename):
    label = tix.Label(root)
    label.original = Image.open(filename)
    label.original.seek(50) # Go to frame 50.
    label.photoimage = ImageTk.PhotoImage(label.original) # keep a reference!
    label.config(image=label.photoimage)
    return label

def main():
    root = tix.Tk()
    label1 = createlabel(root, 'a.fli')
    label1.pack()
    # Hack to replace PIL's FliImageFile with one that loads image data at
    # the end of each internal _seek() call.
    Image.OPEN[FliImagePlugin.FliImageFile.format] = (FliImageFile, Image.OPEN[FliImagePlugin.FliImageFile.format][1])
    label2 = createlabel(root, 'a.fli')
    label2.pack()
    root.mainloop()

main()
```
Using a.fli found at https://samples.libav.org/fli-flc/

Top image is what Pillow displays as-is. The bottom image uses my hack that loads the image at the end of _seek.

![fli-bug](https://user-images.githubusercontent.com/10321049/28949712-9eb3f24a-788c-11e7-8780-6931c971724d.png)
