[Image-SIG] Problems with XpmImagePlugin.py
by Richard Oudkerk other posts by this author
Jul 6 2004 10:32AM messages near this date
[Image-SIG] Problems with XpmImagePlugin.py
|
Re: [Image-SIG] Problems with XpmImagePlugin.py
I have found a few problems related to the XpmImagePlugin filter. (A
patched version is included in the attachment.)
(1) self.tile is defined as
self.tile = [("raw", (0, 0)+self.size, self.fp.tell(),
("P", 0, 1))]
This assumes that the pixel data will have no padding --- but this is
only true if the fall-back XpmImagePlugin.load_read is used because
PIL was unable to use Image.core.map or Image.core.map_buffer.
Therefore the resulting pictures are badly mangled (except when the
fall-back is used).
I think the correct statement (assuming no C-style comments) should be
self.tile = [("raw", (0, 0)+self.size, self.fp.tell()+1,
("P", stride, 1))]
where 'stride' is the length of a full line of pixel data including
the end-of-line character(s).
With this change there is no need to define XpmImagePlugin.load_read
because the default definition of load_read (in ImageFile) works fine.
(2) XpmImagePlugin expects all colours to be specified in the form
"#rrggbb". However the form "#rrrrggggbbbb" also seems to be very
common. Also, the XPM files with actual colour names like "red" or
"SandyBrown" are not accepted.
(3) XpmImagePlugin cannot deal with any C-style comments like
"/* colors */" or "/* pixels */" which appear in most XPM files
(certainly those produced by netpbm and ImageMagick).
(4) In the function PyImaging_MapBuffer() in map.c there is a check to
make sure that we don't have
offset + ysize * stride > bytes
where "bytes" is the length of the buffer. However if there is not
enough padding at the end of the file then this can fail. I have a
couple of XPM files which end with '"};' (with no final '\n' or
'\r\n') where this fails and produces the error "ValueError: buffer is
not large enough".
I think it is sufficient to check is that we don't have
offset + (ysize-1) * stride + xsize > bytes
This will ensure that if "0 <= y < ysize" and "0 <= x < xsize" then
"im-> image[y][x]" will always be a point in the buffer.
Making this change seems to solve the problem. (A similar check also
appears in map.c/mapping_readimage() --- maybe a change is needed
there as well.)
(5) If I load a GIF or XPM file where one colour is supposed to be
transparent and then save it as a PNG file, the transparent colour
becomes solid. This is not something that happens if I use
ImageMagick.
(6) ImageColor.colormap misspells 'lightgray' as 'lightgrey'. (I
assume this is a misspelling since it contains 'gray', 'dimgray',
'slategray',... but not 'grey', 'dimgrey', 'slategrey',...)
A patched version of XpmImagePlugin.py which deals with problems (1),
(2) and (3) is in the attachment. (ImageColor.colormap and a dict of
ten or so exceptions is used to deal with colour names like "red" or
"firebrick".)
I have tested PIL on the 2000+ XPM files on my linux partition. With
the old version of XpmImagePlugin.py only a third could be
successfully converted to PNG by PIL (and even then the results were
wrong because of problem (1)).
The patched version can deal with over 90% (although with the
transparency problem mentioned above). Of the remainder a further 7%
use 2 chars/pixel (and so can't be dealt with using the "raw"
decoder), with the rest either being broken in some way or using X11
colours ending in a number such as 'peachpuff4' (which seems to be
deprecated for use XPM files).
I have tested it under under cygwin/python2.3, win32/python2.2 and
linux/python1.5.
Thanks, Richard
Attachments:
unknown2
XpmImagePlugin.py
Thread:
Richard Oudkerk
Douglas Bagnall
|