diff --git a/PIL/TiffImagePlugin.py b/PIL/TiffImagePlugin.py index 333104966..bd66f4a7a 100644 --- a/PIL/TiffImagePlugin.py +++ b/PIL/TiffImagePlugin.py @@ -201,6 +201,17 @@ OPEN_INFO = { (II, 2, (1,), 1, (8, 8, 8, 8), (999,)): ("RGBA", "RGBA"), # Corel Draw 10 (MM, 2, (1,), 1, (8, 8, 8, 8), (999,)): ("RGBA", "RGBA"), # Corel Draw 10 + (II, 2, (1,), 1, (16, 16, 16), ()): ("RGB", "RGB;16L"), + (MM, 2, (1,), 1, (16, 16, 16), ()): ("RGB", "RGB;16B"), + (II, 2, (1,), 1, (16, 16, 16, 16), ()): ("RGBA", "RGBA;16L"), + (MM, 2, (1,), 1, (16, 16, 16, 16), ()): ("RGBA", "RGBA;16B"), + (II, 2, (1,), 1, (16, 16, 16, 16), (0,)): ("RGBX", "RGBX;16L"), + (MM, 2, (1,), 1, (16, 16, 16, 16), (0,)): ("RGBX", "RGBX;16B"), + (II, 2, (1,), 1, (16, 16, 16, 16), (1,)): ("RGBA", "RGBa;16L"), + (MM, 2, (1,), 1, (16, 16, 16, 16), (1,)): ("RGBA", "RGBa;16B"), + (II, 2, (1,), 1, (16, 16, 16, 16), (2,)): ("RGBA", "RGBA;16L"), + (MM, 2, (1,), 1, (16, 16, 16, 16), (2,)): ("RGBA", "RGBA;16B"), + (II, 3, (1,), 1, (1,), ()): ("P", "P;1"), (MM, 3, (1,), 1, (1,), ()): ("P", "P;1"), (II, 3, (1,), 2, (1,), ()): ("P", "P;1R"), @@ -230,7 +241,12 @@ OPEN_INFO = { (MM, 8, (1,), 1, (8, 8, 8), ()): ("LAB", "LAB"), } -PREFIXES = [b"MM\000\052", b"II\052\000", b"II\xBC\000"] +PREFIXES = [ + b"MM\x00\x2A", # Valid TIFF header with big-endian byte order + b"II\x2A\x00", # Valid TIFF header with little-endian byte order + b"MM\x2A\x00", # Invalid TIFF header, assume big-endian + b"II\x00\x2A", # Invalid TIFF header, assume little-endian +] def _accept(prefix): diff --git a/Tests/images/tiff_16bit_RGBa.tiff b/Tests/images/tiff_16bit_RGBa.tiff new file mode 100644 index 000000000..0fa209c5c Binary files /dev/null and b/Tests/images/tiff_16bit_RGBa.tiff differ diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index 6652b431e..bfc3bf120 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -51,6 +51,14 @@ class TestFileTiff(PillowTestCase): self.assertEqual(im.tile, [('raw', (0, 0, 55, 43), 8, ('RGBa', 0, 1))]) im.load() + def test_16bit_RGBa_tiff(self): + im = Image.open("Tests/images/tiff_16bit_RGBa.tiff") + + self.assertEqual(im.mode, "RGBA") + self.assertEqual(im.size, (100, 40)) + self.assertEqual(im.tile, [('tiff_lzw', (0, 0, 100, 40), 50, 'RGBa;16B')]) + im.load() + def test_gimp_tiff(self): # Read TIFF JPEG images from GIMP [@PIL168] diff --git a/Tests/test_lib_pack.py b/Tests/test_lib_pack.py index d062b33be..bc8317c84 100644 --- a/Tests/test_lib_pack.py +++ b/Tests/test_lib_pack.py @@ -243,6 +243,7 @@ class TestLibUnpack(PillowTestCase): self.assert_unpack("RGB", "RGB", 3, (1,2,3), (4,5,6), (7,8,9)) self.assert_unpack("RGB", "RGB;L", 3, (1,4,7), (2,5,8), (3,6,9)) self.assert_unpack("RGB", "RGB;R", 3, (128,64,192), (32,160,96)) + self.assert_unpack("RGB", "RGB;16L", 6, (2,4,6), (8,10,12)) self.assert_unpack("RGB", "RGB;16B", 6, (1,3,5), (7,9,11)) self.assert_unpack("RGB", "BGR", 3, (3,2,1), (6,5,4), (9,8,7)) self.assert_unpack("RGB", "RGB;15", 2, (8,131,0), (24,0,8)) @@ -270,8 +271,26 @@ class TestLibUnpack(PillowTestCase): (1,2,3,4), (5,6,7,8), (9,10,11,12)) self.assert_unpack("RGBA", "RGBa", 4, (63,127,191,4), (159,191,223,8), (191,212,233,12)) + self.assert_unpack("RGBA", "RGBa", + b'\x01\x02\x03\x00\x10\x20\x30\xff', + (0,0,0,0), (16,32,48,255)) + self.assert_unpack("RGBA", "RGBa;16L", 8, + (63,127,191,8), (159,191,223,16), (191,212,233,24)) + self.assert_unpack("RGBA", "RGBa;16L", + b'\x88\x01\x88\x02\x88\x03\x88\x00' + b'\x88\x10\x88\x20\x88\x30\x88\xff', + (0,0,0,0), (16,32,48,255)) + self.assert_unpack("RGBA", "RGBa;16B", 8, + (36,109,182,7), (153,187,221,15), (188,210,232,23)) + self.assert_unpack("RGBA", "RGBa;16B", + b'\x01\x88\x02\x88\x03\x88\x00\x88' + b'\x10\x88\x20\x88\x30\x88\xff\x88', + (0,0,0,0), (16,32,48,255)) self.assert_unpack("RGBA", "BGRa", 4, (191,127,63,4), (223,191,159,8), (233,212,191,12)) + self.assert_unpack("RGBA", "BGRa", + b'\x01\x02\x03\x00\x10\x20\x30\xff', + (0,0,0,0), (48,32,16,255)) self.assert_unpack("RGBA", "RGBA;I", 4, (254,253,252,4), (250,249,248,8), (246,245,244,12)) self.assert_unpack("RGBA", "RGBA;L", 4, @@ -279,6 +298,7 @@ class TestLibUnpack(PillowTestCase): self.assert_unpack("RGBA", "RGBA;15", 2, (8,131,0,0), (24,0,8,0)) self.assert_unpack("RGBA", "BGRA;15", 2, (0,131,8,0), (8,0,24,0)) self.assert_unpack("RGBA", "RGBA;4B", 2, (17,0,34,0), (51,0,68,0)) + self.assert_unpack("RGBA", "RGBA;16L", 8, (2,4,6,8), (10,12,14,16)) self.assert_unpack("RGBA", "RGBA;16B", 8, (1,3,5,7), (9,11,13,15)) self.assert_unpack("RGBA", "BGRA", 4, (3,2,1,4), (7,6,5,8), (11,10,9,12)) @@ -316,6 +336,8 @@ class TestLibUnpack(PillowTestCase): (1,2,3,4), (5,6,7,8), (9,10,11,12)) self.assert_unpack("RGBX", "RGBX;L", 4, (1,4,7,10), (2,5,8,11), (3,6,9,12)) + self.assert_unpack("RGBX", "RGBX;16L", 8, (2,4,6,8), (10,12,14,16)) + self.assert_unpack("RGBX", "RGBX;16B", 8, (1,3,5,7), (9,11,13,15)) self.assert_unpack("RGBX", "BGRX", 4, (3,2,1,X), (7,6,5,X), (11,10,9,X)) self.assert_unpack("RGBX", "XRGB", 4, (2,3,4,X), (6,7,8,X), (10,11,12,X)) self.assert_unpack("RGBX", "XBGR", 4, (4,3,2,X), (8,7,6,X), (12,11,10,X)) @@ -462,7 +484,7 @@ class TestLibUnpack(PillowTestCase): self.assert_unpack("I;16", "I;16", 2, 0x0201, 0x0403, 0x0605) self.assert_unpack("I;16B", "I;16B", 2, 0x0102, 0x0304, 0x0506) self.assert_unpack("I;16L", "I;16L", 2, 0x0201, 0x0403, 0x0605) - self.assert_unpack("I;16", "I;12", 2, 0x0010, 0x0203, 0x0040, 0x0506) + self.assert_unpack("I;16", "I;12", 2, 0x0010, 0x0203, 0x0040) if sys.byteorder == 'little': self.assert_unpack("I;16", "I;16N", 2, 0x0201, 0x0403, 0x0605) self.assert_unpack("I;16B", "I;16N", 2, 0x0201, 0x0403, 0x0605) diff --git a/libImaging/Unpack.c b/libImaging/Unpack.c index e836f954b..c7b9a606c 100644 --- a/libImaging/Unpack.c +++ b/libImaging/Unpack.c @@ -494,6 +494,18 @@ ImagingUnpackRGB(UINT8* _out, const UINT8* in, int pixels) } } +void +unpackRGB16L(UINT8* _out, const UINT8* in, int pixels) +{ + int i; + UINT32* out = (UINT32*) _out; + /* 16-bit RGB triplets, little-endian order */ + for (i = 0; i < pixels; i++) { + out[i] = MAKE_UINT32(in[1], in[3], in[5], 255); + in += 6; + } +} + void unpackRGB16B(UINT8* _out, const UINT8* in, int pixels) { @@ -724,6 +736,48 @@ unpackRGBALA16B(UINT8* _out, const UINT8* in, int pixels) } } +static void +unpackRGBa16L(UINT8* _out, const UINT8* in, int pixels) +{ + int i; + UINT32* out = (UINT32*) _out; + /* premultiplied 16-bit RGBA, little-endian */ + for (i = 0; i < pixels; i++) { + int a = in[7]; + if ( ! a) { + out[i] = 0; + } else if (a == 255) { + out[i] = MAKE_UINT32(in[1], in[3], in[5], a); + } else { + out[i] = MAKE_UINT32(CLIP(in[1] * 255 / a), + CLIP(in[3] * 255 / a), + CLIP(in[5] * 255 / a), a); + } + in += 8; + } +} + +static void +unpackRGBa16B(UINT8* _out, const UINT8* in, int pixels) +{ + int i; + UINT32* out = (UINT32*) _out; + /* premultiplied 16-bit RGBA, big-endian */ + for (i = 0; i < pixels; i++) { + int a = in[6]; + if ( ! a) { + out[i] = 0; + } else if (a == 255) { + out[i] = MAKE_UINT32(in[0], in[2], in[4], a); + } else { + out[i] = MAKE_UINT32(CLIP(in[0] * 255 / a), + CLIP(in[2] * 255 / a), + CLIP(in[4] * 255 / a), a); + } + in += 8; + } +} + static void unpackRGBa(UINT8* _out, const UINT8* in, int pixels) { @@ -732,9 +786,9 @@ unpackRGBa(UINT8* _out, const UINT8* in, int pixels) /* premultiplied RGBA */ for (i = 0; i < pixels; i++) { int a = in[3]; - if ( ! a) + if ( ! a) { out[i] = 0; - else if (a == 255) { + } else if (a == 255) { out[i] = MAKE_UINT32(in[0], in[1], in[2], a); } else { out[i] = MAKE_UINT32(CLIP(in[0] * 255 / a), @@ -753,9 +807,9 @@ unpackBGRa(UINT8* _out, const UINT8* in, int pixels) /* premultiplied BGRA */ for (i = 0; i < pixels; i++) { int a = in[3]; - if (!a) + if ( ! a) { out[i] = 0; - else if (a == 255) { + } else if (a == 255) { out[i] = MAKE_UINT32(in[2], in[1], in[0], a); } else { out[i] = MAKE_UINT32(CLIP(in[2] * 255 / a), @@ -792,6 +846,18 @@ unpackRGBAL(UINT8* _out, const UINT8* in, int pixels) } } +void +unpackRGBA16L(UINT8* _out, const UINT8* in, int pixels) +{ + int i; + UINT32* out = (UINT32*) _out; + /* 16-bit RGBA, little-endian order */ + for (i = 0; i < pixels; i++) { + out[i] = MAKE_UINT32(in[1], in[3], in[5], in[7]); + in += 8; + } +} + void unpackRGBA16B(UINT8* _out, const UINT8* in, int pixels) { @@ -1192,6 +1258,7 @@ static struct { {"RGB", "RGB", 24, ImagingUnpackRGB}, {"RGB", "RGB;L", 24, unpackRGBL}, {"RGB", "RGB;R", 24, unpackRGBR}, + {"RGB", "RGB;16L", 48, unpackRGB16L}, {"RGB", "RGB;16B", 48, unpackRGB16B}, {"RGB", "BGR", 24, ImagingUnpackBGR}, {"RGB", "RGB;15", 16, ImagingUnpackRGB15}, @@ -1215,12 +1282,15 @@ static struct { {"RGBA", "LA;16B", 32, unpackRGBALA16B}, {"RGBA", "RGBA", 32, copy4}, {"RGBA", "RGBa", 32, unpackRGBa}, + {"RGBA", "RGBa;16L", 64, unpackRGBa16L}, + {"RGBA", "RGBa;16B", 64, unpackRGBa16B}, {"RGBA", "BGRa", 32, unpackBGRa}, {"RGBA", "RGBA;I", 32, unpackRGBAI}, {"RGBA", "RGBA;L", 32, unpackRGBAL}, {"RGBA", "RGBA;15", 16, ImagingUnpackRGBA15}, {"RGBA", "BGRA;15", 16, ImagingUnpackBGRA15}, {"RGBA", "RGBA;4B", 16, ImagingUnpackRGBA4B}, + {"RGBA", "RGBA;16L", 64, unpackRGBA16L}, {"RGBA", "RGBA;16B", 64, unpackRGBA16B}, {"RGBA", "BGRA", 32, unpackBGRA}, {"RGBA", "ARGB", 32, unpackARGB}, @@ -1248,6 +1318,8 @@ static struct { {"RGBX", "BGR;5", 16, ImagingUnpackBGR15}, /* compat */ {"RGBX", "RGBX", 32, copy4}, {"RGBX", "RGBX;L", 32, unpackRGBAL}, + {"RGBX", "RGBX;16L", 64, unpackRGBA16L}, + {"RGBX", "RGBX;16B", 64, unpackRGBA16B}, {"RGBX", "BGRX", 32, ImagingUnpackBGRX}, {"RGBX", "XRGB", 24, ImagingUnpackXRGB}, {"RGBX", "XBGR", 32, ImagingUnpackXBGR},