PIL FITs image decoder

jbrewer jeremy.d.brewer at gmail.com
Tue Nov 22 18:44:51 CET 2005

I'm trying to read in a FITs image file for my research, and I decided
that writing a file decoder for the Python imaging library would be the
easiest way to accomplish this for my needs.  FITs is a raw data format
used in astronomy.

Anyway, I followed the example in the PIL documentation online, and I
also had a look at the FITs image stub file included with PIL 1.1.5.  I
cooked up something that should work (or nearly work), but I keep
running into either one of two errors (below).  The crux of the problem
appears to be that my plugin isn't being registered properly and isn't
being read at runtime when I call Image.open().

1.)  The library loads the FitsStubImagePlugin.py file from the
site-packages directory (instead of my plugin) and then gives the
following error:

line 255, in load
    raise IOError("cannot find loader for this %s file" % self.format)
IOError: cannot find loader for this FITS file

2.)  I remove the FitsStubImagePlugin.py, pyc files and stick my plugin
in the directory instead (my plugin was already in the PYTHONPATH
before).  Then I get the following error:

Traceback (most recent call last):
  File "FitsImagePlugin.py", line 111, in ?
    image = Image.open(fits_name).save(jpg_name)
line 1745, in open
    raise IOError("cannot identify image file")
IOError: cannot identify image file

This seems like I'm either doing (or not doing) something really stupid
or the docs are outdated.  Any help would be greatly appreciated!


 ------------------------------ Code below

import Image, ImageFile

_handler = None

# Install application-specific FITS image handler.
# @param handler Handler object.

def register_handler(handler):
    global _handler
    _handler = handler

# --------------------------------------------------------------------
# Image adapter

def _accept(prefix):
    return prefix[:6] == "SIMPLE"

class FitsImageFile(ImageFile.StubImageFile):
#class FitsImageFile(ImageFile.ImageFile):

    format = "FITS"
    format_description = "FITs raw image"

    def _open(self):

        # byte offset for FITs images
        byte_offset = 2880

        # check header for valid FITs image
        header_data = self.fp.read(byte_offset)

        # headers are stored in 80 character strings, so sort them out
into a
        # nice list
        i = 0
        headers = []
        while header_data[i] != "\n" and i < len(header_data):
            headers.append(header_data[i:i + 80])
            i += 81

        # parse individual headers
        ok = False
        for header in headers:
            words = header.split()

                keyword = words[0]
                value = words[2]
            except IndexError:
                ok = False

            if keyword == "NAXIS" and value == 2:
                ok = True
            elif keyword == "NAXIS1":
                xsize = value
            elif keyword == "NAXIS2":
                ysize = value

        if not ok:
            raise ValueError("file is not a valid FITs image")

        # size in pixels (width, height)
        self.size = (xsize, ysize)

        # mode setting is always greyscale
        self.mode = "F"

        # data descriptor
        self.tile = [("raw", (0, 0) + self.size, byte_offset, ("F", 0,

        # is this needed?
        loader = self._load()
        if loader:

    def _load(self):
        return _handler

def _save(im, fp, filename):
    if _handler is None or not hasattr("_handler", "save"):
        raise IOError("FITS save handler not installed")
    _handler.save(im, fp, filename)

# register the plugin
Image.register_open(FitsImageFile.format, FitsImageFile, _accept)
Image.register_save(FitsImageFile.format, _save)

# method given in docs
#Image.register_open(FitsImageFile.format, FitsImageFile)

Image.register_extension(FitsImageFile.format, ".fits")
Image.register_extension(FitsImageFile.format, ".fit")

# test code
if __name__ == "__main__":
    import os

    fits_name = "fpC-001739-r1-0304.fit"
    jpg_name = os.path.splitext(fits_name)[0] + ".jpg"

    image = Image.open(fits_name).save(jpg_name)
    print "Converted FITs image '%s' to jpeg image '%s'" % (fits_name,

More information about the Python-list mailing list