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

Reply via email to