diff --git a/scikits/image/data/palette_color.png b/scikits/image/data/palette_color.png new file mode 100644 index 00000000..4f5878af Binary files /dev/null and b/scikits/image/data/palette_color.png differ diff --git a/scikits/image/data/palette_gray.png b/scikits/image/data/palette_gray.png new file mode 100644 index 00000000..a47b5d54 Binary files /dev/null and b/scikits/image/data/palette_gray.png differ diff --git a/scikits/image/io/pil_imread.py b/scikits/image/io/pil_imread.py index 421f45c7..10d273ca 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 in palette mode 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) diff --git a/scikits/image/io/tests/test_imread.py b/scikits/image/io/tests/test_imread.py index 86aa8fe6..2e9a2f7a 100644 --- a/scikits/image/io/tests/test_imread.py +++ b/scikits/image/io/tests/test_imread.py @@ -3,6 +3,7 @@ import numpy as np from scikits.image import data_dir from scikits.image.io import imread +from scikits.image.io.pil_imread import palette_is_grayscale def test_imread_flatten(): # a color image is flattened and returned as float32 @@ -15,3 +16,16 @@ def test_imread_flatten(): def test_imread_dtype(): img = imread(os.path.join(data_dir, 'camera.png'), dtype=np.float64) assert img.dtype == np.float64 + +def test_imread_palette(): + img = imread(os.path.join(data_dir, 'palette_gray.png')) + assert img.ndim == 2 + img = imread(os.path.join(data_dir, 'palette_color.png')) + assert img.ndim == 3 + +def test_palette_is_gray(): + from PIL import Image + gray = Image.open(os.path.join(data_dir, 'palette_gray.png')) + assert palette_is_grayscale(gray) + color = Image.open(os.path.join(data_dir, 'palette_color.png')) + assert not palette_is_grayscale(color)