Patch - read support for Adobe Filmstrip (.flm) files
Matt Westcott <[email protected]> Mon, 2 Jan 2012 02:23:50 +0000
| Newsgroups | gmane.comp.python.image |
|---|---|
| Message-ID | <[email protected]> |
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 _______________________________________________ Image-SIG maillist - [email protected] http://mail.python.org/mailman/listinfo/image-sig
FlmImagePlugin.py
(text/x-python-script, 2.1 KB)
#
# 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")