Merge pull request #2692 from uploadcare/16-bit-rgb-tiff

Load 16-bit RGB and RGBA TIFF image
This commit is contained in:
Alexander Karpinsky 2017-08-28 21:39:17 +03:00 committed by GitHub
commit 2aa0d59d43
5 changed files with 127 additions and 2 deletions

View File

@ -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):

Binary file not shown.

View File

@ -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]

View File

@ -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,6 +271,21 @@ 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", "RGBA;I", 4,
@ -279,6 +295,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 +333,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 +481,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)

View File

@ -492,6 +492,20 @@ ImagingUnpackRGB(UINT8* out, const UINT8* in, int pixels)
}
}
void
unpackRGB16L(UINT8* out, const UINT8* in, int pixels)
{
int i;
/* 16-bit RGB triplets, little-endian order */
for (i = 0; i < pixels; i++) {
out[R] = in[1];
out[G] = in[3];
out[B] = in[5];
out[A] = 255;
out += 4; in += 6;
}
}
void
unpackRGB16B(UINT8* out, const UINT8* in, int pixels)
{
@ -736,6 +750,54 @@ unpackRGBALA16B(UINT8* out, const UINT8* in, int pixels)
}
}
static void
unpackRGBa16L(UINT8* out, const UINT8* in, int pixels)
{
int i;
/* premultiplied 16-bit RGBA, little-endian */
for (i = 0; i < pixels; i++) {
int a = in[7];
if (!a)
out[R] = out[G] = out[B] = out[A] = 0;
else if (a == 255) {
out[R] = in[1];
out[G] = in[3];
out[B] = in[5];
out[A] = a;
} else {
out[R] = CLIP(in[1] * 255 / a);
out[G] = CLIP(in[3] * 255 / a);
out[B] = CLIP(in[5] * 255 / a);
out[A] = a;
}
out += 4; in += 8;
}
}
static void
unpackRGBa16B(UINT8* out, const UINT8* in, int pixels)
{
int i;
/* premultiplied 16-bit RGBA, big-endian */
for (i = 0; i < pixels; i++) {
int a = in[6];
if (!a)
out[R] = out[G] = out[B] = out[A] = 0;
else if (a == 255) {
out[R] = in[0];
out[G] = in[2];
out[B] = in[4];
out[A] = a;
} else {
out[R] = CLIP(in[0] * 255 / a);
out[G] = CLIP(in[2] * 255 / a);
out[B] = CLIP(in[4] * 255 / a);
out[A] = a;
}
out += 4; in += 8;
}
}
static void
unpackRGBa(UINT8* out, const UINT8* in, int pixels)
{
@ -813,6 +875,20 @@ unpackRGBAL(UINT8* out, const UINT8* in, int pixels)
}
}
void
unpackRGBA16L(UINT8* out, const UINT8* in, int pixels)
{
int i;
/* 16-bit RGBA, little-endian order */
for (i = 0; i < pixels; i++) {
out[R] = in[1];
out[G] = in[3];
out[B] = in[5];
out[A] = in[7];
out += 4; in += 8;
}
}
void
unpackRGBA16B(UINT8* out, const UINT8* in, int pixels)
{
@ -1223,6 +1299,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},
@ -1246,12 +1323,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},
@ -1279,6 +1359,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},