diff --git a/Tests/test_image_mode.py b/Tests/test_image_mode.py index 0232a5536..670b2f4eb 100644 --- a/Tests/test_image_mode.py +++ b/Tests/test_image_mode.py @@ -21,6 +21,7 @@ def test_sanity(): assert m.bands == ("1",) assert m.basemode == "L" assert m.basetype == "L" + assert m.typestr == "|b1" for mode in ( "I;16", @@ -45,6 +46,7 @@ def test_sanity(): assert m.bands == ("R", "G", "B") assert m.basemode == "RGB" assert m.basetype == "L" + assert m.typestr == "|u1" def test_properties(): diff --git a/src/PIL/Image.py b/src/PIL/Image.py index 9c35d3328..0e93eabde 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -264,48 +264,16 @@ ENCODERS = {} # -------------------------------------------------------------------- # Modes -if sys.byteorder == "little": - _ENDIAN = "<" -else: - _ENDIAN = ">" - -_MODE_CONV = { - # official modes - "1": ("|b1", None), # Bits need to be extended to bytes - "L": ("|u1", None), - "LA": ("|u1", 2), - "I": (_ENDIAN + "i4", None), - "F": (_ENDIAN + "f4", None), - "P": ("|u1", None), - "RGB": ("|u1", 3), - "RGBX": ("|u1", 4), - "RGBA": ("|u1", 4), - "CMYK": ("|u1", 4), - "YCbCr": ("|u1", 3), - "LAB": ("|u1", 3), # UNDONE - unsigned |u1i1i1 - "HSV": ("|u1", 3), - # I;16 == I;16L, and I;32 == I;32L - "I;16": ("u2", None), - "I;16L": ("i2", None), - "I;16LS": ("u4", None), - "I;32L": ("i4", None), - "I;32LS": ("" def _conv_type_shape(im): - typ, extra = _MODE_CONV[im.mode] - if extra is None: - return (im.size[1], im.size[0]), typ - else: - return (im.size[1], im.size[0], extra), typ + m = ImageMode.getmode(im.mode) + shape = (im.height, im.width) + extra = len(m.bands) + if extra != 1: + shape += (extra,) + return shape, m.typestr MODES = ["1", "CMYK", "F", "HSV", "I", "L", "LAB", "P", "RGB", "RGBA", "RGBX", "YCbCr"] diff --git a/src/PIL/ImageMode.py b/src/PIL/ImageMode.py index e6bf0bb10..0973536c9 100644 --- a/src/PIL/ImageMode.py +++ b/src/PIL/ImageMode.py @@ -13,6 +13,8 @@ # See the README file for information on usage and redistribution. # +import sys + # mode descriptor cache _modes = None @@ -20,11 +22,12 @@ _modes = None class ModeDescriptor: """Wrapper for mode strings.""" - def __init__(self, mode, bands, basemode, basetype): + def __init__(self, mode, bands, basemode, basetype, typestr): self.mode = mode self.bands = bands self.basemode = basemode self.basetype = basetype + self.typestr = typestr def __str__(self): return self.mode @@ -36,43 +39,53 @@ def getmode(mode): if not _modes: # initialize mode cache modes = {} - for m, (basemode, basetype, bands) in { + endian = "<" if sys.byteorder == "little" else ">" + for m, (basemode, basetype, bands, typestr) in { # core modes - "1": ("L", "L", ("1",)), - "L": ("L", "L", ("L",)), - "I": ("L", "I", ("I",)), - "F": ("L", "F", ("F",)), - "P": ("P", "L", ("P",)), - "RGB": ("RGB", "L", ("R", "G", "B")), - "RGBX": ("RGB", "L", ("R", "G", "B", "X")), - "RGBA": ("RGB", "L", ("R", "G", "B", "A")), - "CMYK": ("RGB", "L", ("C", "M", "Y", "K")), - "YCbCr": ("RGB", "L", ("Y", "Cb", "Cr")), - "LAB": ("RGB", "L", ("L", "A", "B")), - "HSV": ("RGB", "L", ("H", "S", "V")), + # Bits need to be extended to bytes + "1": ("L", "L", ("1",), "|b1"), + "L": ("L", "L", ("L",), "|u1"), + "I": ("L", "I", ("I",), endian + "i4"), + "F": ("L", "F", ("F",), endian + "f4"), + "P": ("P", "L", ("P",), "|u1"), + "RGB": ("RGB", "L", ("R", "G", "B"), "|u1"), + "RGBX": ("RGB", "L", ("R", "G", "B", "X"), "|u1"), + "RGBA": ("RGB", "L", ("R", "G", "B", "A"), "|u1"), + "CMYK": ("RGB", "L", ("C", "M", "Y", "K"), "|u1"), + "YCbCr": ("RGB", "L", ("Y", "Cb", "Cr"), "|u1"), + # UNDONE - unsigned |u1i1i1 + "LAB": ("RGB", "L", ("L", "A", "B"), "|u1"), + "HSV": ("RGB", "L", ("H", "S", "V"), "|u1"), # extra experimental modes - "RGBa": ("RGB", "L", ("R", "G", "B", "a")), - "BGR;15": ("RGB", "L", ("B", "G", "R")), - "BGR;16": ("RGB", "L", ("B", "G", "R")), - "BGR;24": ("RGB", "L", ("B", "G", "R")), - "BGR;32": ("RGB", "L", ("B", "G", "R")), - "LA": ("L", "L", ("L", "A")), - "La": ("L", "L", ("L", "a")), - "PA": ("RGB", "L", ("P", "A")), + "RGBa": ("RGB", "L", ("R", "G", "B", "a"), "|u1"), + "BGR;15": ("RGB", "L", ("B", "G", "R"), endian + "u2"), + "BGR;16": ("RGB", "L", ("B", "G", "R"), endian + "u2"), + "BGR;24": ("RGB", "L", ("B", "G", "R"), endian + "u3"), + "BGR;32": ("RGB", "L", ("B", "G", "R"), endian + "u4"), + "LA": ("L", "L", ("L", "A"), "|u1"), + "La": ("L", "L", ("L", "a"), "|u1"), + "PA": ("RGB", "L", ("P", "A"), "|u1"), }.items(): - modes[m] = ModeDescriptor(m, bands, basemode, basetype) + modes[m] = ModeDescriptor(m, bands, basemode, basetype, typestr) # mapping modes - for i16mode in ( - "I;16", - "I;16S", - "I;16L", - "I;16LS", - "I;16B", - "I;16BS", - "I;16N", - "I;16NS", - ): - modes[i16mode] = ModeDescriptor(i16mode, ("I",), "L", "L") + for i16mode, typestr in { + # I;16 == I;16L, and I;32 == I;32L + "I;16": "u2", + "I;16BS": ">i2", + "I;16N": endian + "u2", + "I;16NS": endian + "i2", + "I;32": "u4", + "I;32L": "i4", + "I;32LS": "