<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
</head>
<body bgcolor="#ffffff" text="#000000">
<font face="Verdana"><br>
I recently downloaded the Python Imaging Library (PIL 1.1.5), and I
have been trying to use it to convert several hundred XPM files into
GIFs (I also tried converting into PNGs which may be useful in the
future). During this process, I ran into various problems which appear
to be caused by bugs.<br>
<br>
Most of the difficulties were related to XPMs -- not being able to load
XPM files which other applications were quite happy with. But there
were also a couple of minor issues with transparency in GIF and PNG
formats. <br>
<br>
Attached is a diff file containing the changes I had to make to the
code to fix these problems. This fixes things for the vast majority of
the XPM files I have. There are still some XPMs that can't be loaded
(those which use more than one character per pixel for example), but
these are far less common.<br>
<br>
<br>
Because I am not a regular contributer to this project I thought I
should include more information than just the diffs, so here is a list
of the bugs I found and what I changed as a result: <br>
<br>
<br>
</font><br>
<font face="Verdana"><b>Bug:</b> PIL could not open some XPM files
because it failed to cope with some features of XPM syntax.</font><br>
<br>
<font face="Verdana"><b>Fix: </b> Various changes in XpmImagePlugin.py:</font><br>
<br>
<ul>
<li><font face="Verdana">Changed the RE used to match the image
header to one that copes with leading spaces and multiple spaces
between words.</font></li>
</ul>
<ul>
<li><font face="Verdana">In XpmImageFile._open(), when reading the
image palette:</font></li>
</ul>
<blockquote>
<ul>
<li><font face="Verdana">Ignore lines which are commented-out.</font></li>
<li><font face="Verdana">Strip leading and trailing whitespace
before processing.</font></li>
<li><font face="Verdana">Remove case sensitivity when looking for
"None".</font></li>
<li><font face="Verdana">Use ImageColor.getrgb() to interpret color
values.</font></li>
<li><font face="Verdana">Look ahead to detect colour names
consisting of multiple words</font></li>
</ul>
</blockquote>
<ul>
<li><font face="Verdana">In XpmImageFile.load_read() (when reading
the pixels) ignore lines which are commented-out.</font></li>
</ul>
<br>
<br>
<br>
<br>
<font face="Verdana"><b>Bug: </b>PIL could not open some XPM files,
because the color names were not recognized.</font><br>
<br>
<font face="Verdana"><b>Fix: </b>various changes to ImageColor.py:</font><br>
<br>
<ul>
<li><font face="Verdana">Changed the colormap to the standard list of
X11 colours (as found on any Unix or Linux system).</font></li>
</ul>
<blockquote><font face="Verdana"><b>Note</b>: before this change, the
colormap apparently contained colours taken from CSS3 -- the comment
reads 'X11 colour table (from "CSS3 module: Color working draft")'.
However some of the standard X11 colours clashed with existing colours
in the map. In the end, I removed all the CSS3 colours and just
included the X11 colours. The comment does say "X11 colour table"
after all.</font></blockquote>
<ul>
<li><font face="Verdana">getrgb(): Remove spaces from the color name
in order to find a match. X11 has variations of some color names, such
as "light blue" and "LightBlue". But the version with spaces was not
recognized.</font></li>
</ul>
<ul>
<li><font face="Verdana">getrgb(): Recognize colours specified as a
48-bit RGB string (e.g. #FFFF0000AAAA). These are sometimes
encountered in XPMs. The 3 bytes of extra precision are ignored, and
the returned RGB value is a standard 24-bit RGB tuple.</font></li>
</ul>
<font face="Verdana"><br>
<br>
<br>
<b>Bug:</b> PIL loaded all XPM files incorrectly, shifting the entire
image several pixels to the right (truncating it on the right, and
adding a a band of incorrect pixels on the left).<br>
<br>
This is caused by trying to use memory mapping to read the file, which
prevents the proper XPM decoder from being used. Memory mapping does
not work because of the structure of XPM files -- the file includes
characters (such as the opening and closing quotes on each line) which
do not correspond to pixel values.<br>
<br>
<b>Fix:</b> Changed load() in ImageFile.py to explicitly exclude XPM
files from the memory mapping. <br>
</font><br>
<font face="Verdana">There may be a more elegent way to do this,
perhaps by changing the value of ImageFile.tile for XPMs. But I tried
the obvious thing -- changing the "raw" designation to something else,
and that seemed to break things even more. Perhaps someone more
familiar with this code could do better.</font><br>
<font face="Verdana"><br>
<br>
<br>
<b>Bug:</b> Could not write GIFs with transparency. The pixels which
should have been transparent were not.<br>
<br>
<b>Fix:</b> Changed _save() in GifImagePlugin.py. The code was
looking in the wrong dictionary for the transparency value.<br>
<br>
<br>
<b><br>
Bug:</b> Could not write PNGs with transparency. The pixels which
should have been transparent were not.<br>
<br>
<b>Fix:</b> Changed _save() in PngImagePlugin.py. The code was looking
in the wrong dictionary for the transparency value.<br>
<br>
<br>
-- <br>
Tom Heathcote</font><br>
<pre class="moz-signature" cols="72">--
Tom Heathcote Petris Technology
<a class="moz-txt-link-abbreviated"
href="mailto:tom.heathcote@petris.com">tom.heathcote@petris.com</a> 154 Brent Street
Tel +44 20 8202 2433 London NW4 2DR
Fax +44 20 8202 2287 England
</pre>
</body>
</html>