[Image-SIG] Re: What are plans for PIL, ...

Edward C. Jones edcjones@erols.com
Thu, 27 Aug 1998 23:05:25 -0400


I have a need to manage and analyse a collection of images. I use
Python as
a top level language because it is easy to read and write. I use
C as a low
level language because I know it and it is fast. I would like to
use PIL
primarily to hide from me the nasty details of image formats. 

As an example of what I need, suppose I have created a Python
module that
does median filters. Suppose the module name is "MedianFilter". I
write the
module in C using one of the standard ways of representing two
dimensional
arrays in C. (I tend to prefer a pointer to an array of pointers
to rows.)
The module is to be integrated using SWIG.

I would like the python program to look something like:

import Image, MedianFilter
im = Image.open('pic.jpg', 'r')
im2 = MedianFilter.medianfilter(im, (11, 11) )

or perhaps even:

import Image, MedianFilter
im = Image.open('pic.jpg', 'r')
ptrim = im.pointertoimage()
im2 = MedianFilter.medianfilter(ptrim, (11, 11) )

What do I put in my module to allow this to happen? How do I use
SWIG in
this case?

1. Which parts of PIL support 32 bit images? When should the C
programmer
use "image", "image8", "image32", "UINT8", "UINT32", "FLOAT32",
etc.? See
Fill.c, Blend.c, GetBBox.c, and ImagingGetExtrema.

2. In "Image.py" is the comment "fix to handle multiband images
since
_imaging doesn't". When is this fix needed?

3. Documentation.
   a. Some functions are listed in the user documentation without
any
   explanation. Examples include "putdata" and "tostring".

   b. Some functions are undocumented including "and", "or',
"xor", and
   "GetExtrema".

   c. Each function in the code needs a few lines of overview
documentation
   explaining what the code does and how it is used. For example,
what does
   "ImagingNewPrologue" do?

   d. An overview of how variables are named should be given. It
took me a
   while to figure out "getbbox", "GetBBox", "ImagingGetBBox",
etc.

   e. An overview of the design of PIL is needed. So far, I have
added
   things to PIL by stumbling across somethng that works and
imitating it
   blindly. Include a description of how errors are handled.

   f. Certain operations currently cannot be done on certain
images. As a
   beginner I assumed that any problem was my fault. When an
operation is
   impossible or unimplemented, it should be clearly stated.

4. What is "delayed operation" or "delayed evaluation", how is it
   implemented, and when should the C programmer use it?

5. What is the format of the string returned by "tostring"?

6. The error messages need to be more precise and detailed. If I
give
"Image.merge" images of different sizes I get "wrong number of
bands". If
images mismatch, the nature of the mismatch should be in the
error message.
It took me a while to internalize the idea that while all images
are opened
with Image.open, they are not all alike, and not every operation
is
possible.

7. Input images are often not perfect. PIL needs capabilities for
fixing
broken images. Currently I use the following poor piece of code:


        # Two ugly kludges.
        if string.lower(ext) == '.jpg':
                # jpegtran works on truncated images.
                # For consistency, use it on all jpg's.
                string1 = 'jpegtran  -copy none '
                string2 = ' > tmp.jpg'
                os.system(string1 + file + string2)
                im = Image.open('tmp.jpg')
                os.unlink('tmp.jpg')
        elif string.lower(ext) == '.gif':
                try:
                        # Any truncation error shows up only when
the opened
                        # file is used. Filters don't work on
mode 'P'.
                        # Need to convert to 'RGB'.
                        im = Image.open(file).convert('RGB')
                except IOError, x:
                        if string.find(str(x), 'truncated') !=
-1:
                                print 'Truncated gif'
                                line = 'giffix -q ' + file + ' >
tmp.gif'
                                os.system(line)
                                im =
Image.open('tmp.gif').convert('RGB')
                                os.unlink('tmp.gif')
                        else:
                                print file, 'IOError:', x
                                continue
        else:
                # An unusual format or a non-image file.
                try:
                        im = Image.open(file).convert('RGB')
                except IOError:
                        print 'Unusual format or non-image file.'
                        continue