Hi, I recently found myself needing to process some Adobe Filmstrip (.flm) files with PIL. This format was apparently introduced with Adobe Premiere, and is described here: http://www.compuphase.com/filmstrp.htm It's a remarkably simple format (consisting of a sequence of uncompressed RGBA images along with a fixed 36-byte header at the end), and so I've put together a straightforward file decoder plugin to provide read-only support for the format - I hope this will be useful to others. You can find a sample .flm file here (zipped), for testing: http://zxdemo.org/extra/Matthew.flm.zip
The 'open' method sets the following info properties: frame_count - number of images in the sequence fps - frame rate specified by the file, in frames per second The 'seek' and 'tell' methods are implemented for moving between frames - random access is supported. Kind regards, - Matt Westcott
# # The Python Imaging Library. # $Id$ # # Adobe Filmstrip (.FLM) image file handling # # File format description: http://www.compuphase.com/filmstrp.htm # # History: # 2012-01-02 MW Created # # Copyright (c) 2012 by Matt Westcott # # See the README file for information on usage and redistribution. # __version__ = "0.1" import Image, ImageFile # helper functions to read big-endian integers def i32(c): return (ord(c[0])<<24) + (ord(c[1])<<16) + (ord(c[2])<<8) + ord(c[3]) def i16(c): return (ord(c[0])<<8) + ord(c[1]) class AdobeFilmstripImageFile(ImageFile.ImageFile): format = "FLM" format_description = "Adobe Premiere Filmstrip" def _open(self): # check header - 36 bytes at end of file self.fp.seek(-36, 2) header = self.fp.read(36) if header[:4] != "Rand": raise SyntaxError, "Not an Adobe Filmstrip file" self.__frame_count = self.info["frame_count"] = i32(header[4:]) packing_method = i16(header[8:]) if packing_method != 0: raise SyntaxError, "Packing methods other than 0 (no packing) are unsupported" # FLM files are always RGBA self.mode = 'RGBA' # size in pixels (width, height) self.size = i16(header[12:]), i16(header[14:]) self.__leading = i16(header[16:]) self.info["fps"] = i16(header[18:]) self.__fp = self.fp # HACK: store fp as it's needed for seek, but does not persist after opening self.seek(0) # get ready to read first frame def seek(self, frame): if frame >= self.__frame_count: raise EOFError, "no more images in Filmstrip file" self.fp = self.__fp self.__frame = frame width, height = self.size byte_offset = frame * width * (height + self.__leading) * 4 self.tile = [ ("raw", (0, 0, width, height), byte_offset, ('RGBA', 0, 1)) ] def tell(self): return self.__frame Image.register_open("FLM", AdobeFilmstripImageFile) Image.register_extension("FLM", ".flm")
_______________________________________________ Image-SIG maillist - Image-SIG@python.org http://mail.python.org/mailman/listinfo/image-sig