| # | 
| # 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. | 
| # | 
|   | 
|   | 
| __version__ = "0.2" | 
|   | 
| import Image, ImageFile, ImagePalette | 
| import string | 
|   | 
|   | 
| def i16(c): | 
|     return ord(c[0]) + (ord(c[1])<<8) | 
|   | 
| def i32(c): | 
|     return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24) | 
|   | 
| # | 
| # decoder | 
|   | 
| def _accept(prefix): | 
|     return 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" | 
|   | 
|     def _open(self): | 
|   | 
|         # HEAD | 
|         s = self.fp.read(128) | 
|         magic = i16(s[4:6]) | 
|         if magic not in [0xAF11, 0xAF12]: | 
|             raise SyntaxError, "not an FLI/FLC file" | 
|   | 
|         # 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 = map(lambda a: (a,a,a), 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 = map(lambda (r,g,b): chr(r)+chr(g)+chr(b), palette) | 
|         self.palette = ImagePalette.raw("RGB", string.join(palette, "")) | 
|   | 
|         # set things up to decode first frame | 
|         self.frame = -1 | 
|         self.__fp = self.fp | 
|   | 
|         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 + ord(s[0]) | 
|             n = ord(s[1]) | 
|             if n == 0: | 
|                 n = 256 | 
|             s = self.fp.read(n * 3) | 
|             for n in range(0, len(s), 3): | 
|                 r = ord(s[n]) << shift | 
|                 g = ord(s[n+1]) << shift | 
|                 b = ord(s[n+2]) << shift | 
|                 palette[i] = (r, g, b) | 
|                 i = i + 1 | 
|   | 
|     def seek(self, frame): | 
|   | 
|         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 = self.__offset + framesize | 
|   | 
|     def tell(self): | 
|   | 
|         return self.frame | 
|   | 
| # | 
| # registry | 
|   | 
| Image.register_open("FLI", FliImageFile, _accept) | 
|   | 
| Image.register_extension("FLI", ".fli") | 
| Image.register_extension("FLI", ".flc") |