Hi, Currently, imread doesn't properly handle palette images since PIL palette images can't be converted directly to numpy arrays. Well, you can convert it, but the output is garbage since the array values correspond to the image palette, which you don't have access. Flattening the image seems to be an OK work around, but if the image had a color palette, this information is lost. Also, this work around requires you to know that an image is in palette mode before calling imread. Below is a short patch that checks if an image is in palette mode; if it is, grayscale images are converted to luminance mode and color images are converted to RGB. I'm not sure if these conversions are appropriate, but at least it's an improvement. I hope this is helpful to somebody. Cheers, -Tony P.S. `palette_is_grayscale` is a convoluted function to check whether the palette is grayscale. PIL may provide a simpler check; if so, I couldn't find it. P.P.S. The following link has examples of palette images if you want to test: http://homepages.inf.ed.ac.uk/rbf/HIPR2/libfce.htm (NOTE: the thumbnails are actually not palette images, but the linked images are) ~~~~~~~ diff --git a/scikits/image/io/pil_imread.py b/scikits/image/io/ pil_imread.py index 421f45c..946d00c 100644 --- a/scikits/image/io/pil_imread.py +++ b/scikits/image/io/pil_imread.py @@ -34,6 +34,34 @@ def imread(fname, flatten=False, dtype=None): " instructions.") im = Image.open(fname) + if im.mode == 'P': + if palette_is_grayscale(im): + im = im.convert('L') + else: + im = im.convert('RGB') if flatten and not im.mode in ('1', 'L', 'I', 'F', 'I;16', 'I; 16L', 'I;16B'): im = im.convert('F') return np.array(im, dtype=dtype) + + +def palette_is_grayscale(pil_image): + """Return True if PIL image is grayscale. + + Parameters + ---------- + pil_image : PIL image + PIL Image that is in Palette mode. + + Returns + ------- + is_grayscale : bool + True if all colors in image palette are gray. + """ + assert pil_image.mode == 'P' + # get palette as an array with R, G, B columns + palette = np.asarray(pil_image.getpalette()).reshape((256, 3)) + # Not all palette colors are used; unused colors have junk values. + start, stop = pil_image.getextrema() + valid_palette = palette[start:stop] + # Image is grayscale if channel differences (R - G and G - B) are all zero. + return np.allclose(np.diff(valid_palette), 0)