The DIB image format uses the 40 byte BMP header, followed by 3 masks
for RGB channels. We were reading 4 masks, consuming the first pixel
of the image.
Mostly fixes issue #1293. Remaining issue: alpha channel is actually a
transparency mask.
Does not change testing on other files, but fixes a case which previously made PIL collapse.
The Bitmap was a 1x1 RGBA and provoked an exception in PIL, but every Image viewer can load it.
Fixed code with comparison of header size, compression type and loading type of masks and fixed it.
Error happening in Python 3.x with P images:
in original code, palette data was created from a list of bytestrings. Changed to a full bytestring.
- `b"".join(list of bytestrings)` works in python 2.7 and 3.x
- `b"".join(bytestring)` works in python 2.7 but fails in python 3.x
No need to `join` anymore. Works in 3.x
Fixed loading of all types of provided images (+rgba). Added edge case where the header is reported as 40 bytes long with BITFIELDS (they start past the 40 bytes of the header). Loading fails for RLE, but IIRC, they're unsupported so it's normal.
It appears that
{{{
The handling of 1bpp bitmaps is a little complicated.
When reading 1bpp bitmaps, the palette is ignored.
1's are considered foreground, and they are considered black.
0's are considered background, and they are considered white.
}}}
so the raw mode has to be `1;I`
PIL choked on perfectly valid BMP files (32 bits with Alpha). It could not handle valid RGBA masks to determine the raw format.
To clarify things, I:
- Rewrote the `BmpImagePlugin.BmpImageFile` class to be far more readable
- Made error messages more explicit (e.g. say that RLE bitmaps are unsupported)
- Made a readable dict to contain BMP header information
- Kept the existing security checks
- Instead of reading palette info by chunks of 3/4 bytes, read the whole palette info at once and parse the data.
- Now works with BMPv4/5 with Alpha (and can be exported to alpha PNG for example)
- Tested load and save with RGB24, RGB8, RGB8L, RGB32 and RGBA32.
- Tested with one bogus file. File not accepted, as expected.
I wanted to test more BMP formats, but I could not find that many images.
But for all the types I tested, it worked flawlessly.
There are two main issues fixed with this commit:
* bytes vs. str: All file, image, and palette data are now handled as
bytes. A new _binary module consolidates the hacks needed to do this
across Python versions. tostring/fromstring methods have been renamed to
tobytes/frombytes, but the Python 2.6/2.7 versions alias them to the old
names for compatibility. Users should move to tobytes/frombytes.
One other potentially-breaking change is that text data in image files
(such as tags, comments) are now explicitly handled with a specific
character encoding in mind. This works well with the Unicode str in
Python 3, but may trip up old code expecting a straight byte-for-byte
translation to a Python string. This also required a change to Gohlke's
tags tests (in Tests/test_file_png.py) to expect Unicode strings from
the code.
* True div vs. floor div: Many division operations used the "/" operator
to do floor division, which is now the "//" operator in Python 3. These
were fixed.
As of this commit, on the first pass, I have one failing test (improper
handling of a slice object in a C module, test_imagepath.py) in Python 3,
and three that that I haven't tried running yet (test_imagegl,
test_imagegrab, and test_imageqt). I also haven't tested anything on
Windows. All but the three skipped tests run flawlessly against Pythons
2.6 and 2.7.
In py3k, imports are absolute unless using the "from . import" syntax.
This commit also solves a recursive import between Image, ImageColor, and
ImagePalette by delay-importing ImagePalette in Image.
I'm not too keen on this commit because the syntax is ugly. I might go back
and prefer the prettier "from PIL import".
y.has_key(x) is gone (use x in y), and keys(), values(), items(), and
range() all return views.
Some iterables needed to be packed into lists, either because the code
expected a list (such as "range(256) * 3") or because the original
collection was being modified (automatic global declarations).
The Tiff ImageFileDictionary is a special case and will be dealt with in
another commit.