From 71a8d8db073626eb6d627d8b84f1ba67f056cf0d Mon Sep 17 00:00:00 2001 From: hugovk Date: Sun, 26 Oct 2014 11:15:29 +0200 Subject: [PATCH 01/61] Created with ImageMagick: convert hopper.jpg hopper_jpg.tif --- Tests/images/hopper_jpg.tif | Bin 0 -> 17149 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Tests/images/hopper_jpg.tif diff --git a/Tests/images/hopper_jpg.tif b/Tests/images/hopper_jpg.tif new file mode 100644 index 0000000000000000000000000000000000000000..fee98f5ec94931bbdcef302ea74eb6d8ab76a93d GIT binary patch literal 17149 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 literal 0 HcmV?d00001 From e60683e3b1ee8ca6f9b1a061e6b7292def08e612 Mon Sep 17 00:00:00 2001 From: hugovk Date: Sun, 26 Oct 2014 11:21:02 +0200 Subject: [PATCH 02/61] Test opening TIFF with JPEGTables and saving it --- Tests/test_file_tiff.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index cf809d5d0..472ed167a 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -298,6 +298,19 @@ class TestFileTiff(PillowTestCase): # Assert self.assertEqual(ret, [0, 1]) + def test_save_tiff_with_jpegtables(self): + # Arrange + outfile = self.tempfile("temp.tif") + + # Created with ImageMagick: convert hopper.jpg hopper_jpg.tif + # Contains JPEGTables (347) tag + infile = "Tests/images/hopper_jpg.tif" + im = Image.open(infile) + + # Act / Assert + # Should not raise UnicodeDecodeError or anything else + im.save(outfile) + if __name__ == '__main__': unittest.main() From f9bc87ed01bc1f4952896d6a977e1b500f72e9fd Mon Sep 17 00:00:00 2001 From: hugovk Date: Sun, 26 Oct 2014 11:24:57 +0200 Subject: [PATCH 03/61] flake8 --- Tests/test_file_tiff.py | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index 472ed167a..94e0741f8 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -147,25 +147,24 @@ class TestFileTiff(PillowTestCase): # file is a multipage tiff, 10x10 green, 10x10 red, 20x20 blue im.seek(0) - self.assertEqual(im.size, (10,10)) - self.assertEqual(im.convert('RGB').getpixel((0,0)), (0,128,0)) + self.assertEqual(im.size, (10, 10)) + self.assertEqual(im.convert('RGB').getpixel((0, 0)), (0, 128, 0)) im.seek(1) im.load() - self.assertEqual(im.size, (10,10)) - self.assertEqual(im.convert('RGB').getpixel((0,0)), (255,0,0)) + self.assertEqual(im.size, (10, 10)) + self.assertEqual(im.convert('RGB').getpixel((0, 0)), (255, 0, 0)) im.seek(2) im.load() - self.assertEqual(im.size, (20,20)) - self.assertEqual(im.convert('RGB').getpixel((0,0)), (0,0,255)) + self.assertEqual(im.size, (20, 20)) + self.assertEqual(im.convert('RGB').getpixel((0, 0)), (0, 0, 255)) def test_multipage_last_frame(self): im = Image.open('Tests/images/multipage-lastframe.tif') im.load() - self.assertEqual(im.size, (20,20)) - self.assertEqual(im.convert('RGB').getpixel((0,0)), (0,0,255)) - + self.assertEqual(im.size, (20, 20)) + self.assertEqual(im.convert('RGB').getpixel((0, 0)), (0, 0, 255)) def test___str__(self): # Arrange @@ -199,7 +198,6 @@ class TestFileTiff(PillowTestCase): def test_load_byte(self): # Arrange - from PIL import TiffImagePlugin ifd = TiffImagePlugin.ImageFileDirectory() data = b"abc" @@ -223,7 +221,6 @@ class TestFileTiff(PillowTestCase): def test_load_float(self): # Arrange - from PIL import TiffImagePlugin ifd = TiffImagePlugin.ImageFileDirectory() data = b"abcdabcd" @@ -235,7 +232,6 @@ class TestFileTiff(PillowTestCase): def test_load_double(self): # Arrange - from PIL import TiffImagePlugin ifd = TiffImagePlugin.ImageFileDirectory() data = b"abcdefghabcdefgh" From 4d147c16d3a6500bf7e3428248a9012b2265aa92 Mon Sep 17 00:00:00 2001 From: zwhfly Date: Mon, 28 Mar 2016 17:44:06 +0800 Subject: [PATCH 04/61] Add Some Unpackers for 2/4 bpp Grayscale Format As seen in some tiff image files. --- libImaging/Unpack.c | 118 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 110 insertions(+), 8 deletions(-) diff --git a/libImaging/Unpack.c b/libImaging/Unpack.c index 3fab73cec..702bc9f1f 100644 --- a/libImaging/Unpack.c +++ b/libImaging/Unpack.c @@ -191,14 +191,64 @@ unpack1IR(UINT8* out, const UINT8* in, int pixels) static void unpackL2(UINT8* out, const UINT8* in, int pixels) { - /* nibbles */ + /* nibbles (msb first, white is non-zero) */ while (pixels > 0) { UINT8 byte = *in++; switch (pixels) { - default: *out++ = ((byte >> 6) & 3) * 255 / 3; byte <<= 2; - case 3: *out++ = ((byte >> 6) & 3) * 255 / 3; byte <<= 2; - case 2: *out++ = ((byte >> 6) & 3) * 255 / 3; byte <<= 2; - case 1: *out++ = ((byte >> 6) & 3) * 255 / 3; + default: *out++ = ((byte >> 6) & 0x03U) * 0x55U; byte <<= 2; + case 3: *out++ = ((byte >> 6) & 0x03U) * 0x55U; byte <<= 2; + case 2: *out++ = ((byte >> 6) & 0x03U) * 0x55U; byte <<= 2; + case 1: *out++ = ((byte >> 6) & 0x03U) * 0x55U; + } + pixels -= 4; + } +} + +static void +unpackL2I(UINT8* out, const UINT8* in, int pixels) +{ + /* nibbles (msb first, white is zero) */ + while (pixels > 0) { + UINT8 byte = *in++; + switch (pixels) { + default: *out++ = 0xFFU - (UINT8)(((byte >> 6) & 0x03U) * 0x55U); byte <<= 2; + case 3: *out++ = 0xFFU - (UINT8)(((byte >> 6) & 0x03U) * 0x55U); byte <<= 2; + case 2: *out++ = 0xFFU - (UINT8)(((byte >> 6) & 0x03U) * 0x55U); byte <<= 2; + case 1: *out++ = 0xFFU - (UINT8)(((byte >> 6) & 0x03U) * 0x55U); + } + pixels -= 4; + } +} + +static void +unpackL2R(UINT8* out, const UINT8* in, int pixels) +{ + /* nibbles (bit order reversed, white is non-zero) */ + while (pixels > 0) { + UINT8 byte = *in++; + byte = BITFLIP[byte]; + switch (pixels) { + default: *out++ = ((byte >> 6) & 0x03U) * 0x55U; byte <<= 2; + case 3: *out++ = ((byte >> 6) & 0x03U) * 0x55U; byte <<= 2; + case 2: *out++ = ((byte >> 6) & 0x03U) * 0x55U; byte <<= 2; + case 1: *out++ = ((byte >> 6) & 0x03U) * 0x55U; + } + pixels -= 4; + } +} + +static void +unpackL2IR(UINT8* out, const UINT8* in, int pixels) +{ + /* nibbles (bit order reversed, white is zero) */ + while (pixels > 0) { + UINT8 byte = *in++; + byte = BITFLIP[byte]; + switch (pixels) { + default: *out++ = 0xFFU - (UINT8)(((byte >> 6) & 0x03U) * 0x55U); byte <<= 2; + case 3: *out++ = 0xFFU - (UINT8)(((byte >> 6) & 0x03U) * 0x55U); byte <<= 2; + case 2: *out++ = 0xFFU - (UINT8)(((byte >> 6) & 0x03U) * 0x55U); byte <<= 2; + case 1: *out++ = 0xFFU - (UINT8)(((byte >> 6) & 0x03U) * 0x55U); } pixels -= 4; } @@ -207,12 +257,56 @@ unpackL2(UINT8* out, const UINT8* in, int pixels) static void unpackL4(UINT8* out, const UINT8* in, int pixels) { - /* nibbles */ + /* nibbles (msb first, white is non-zero) */ while (pixels > 0) { UINT8 byte = *in++; switch (pixels) { - default: *out++ = ((byte >> 4) & 15) * 255 / 15; byte <<= 4; - case 1: *out++ = ((byte >> 4) & 15) * 255 / 15; + default: *out++ = ((byte >> 4) & 0x0FU) * 0x11U; byte <<= 4; + case 1: *out++ = ((byte >> 4) & 0x0FU) * 0x11U; + } + pixels -= 2; + } +} + +static void +unpackL4I(UINT8* out, const UINT8* in, int pixels) +{ + /* nibbles (msb first, white is zero) */ + while (pixels > 0) { + UINT8 byte = *in++; + switch (pixels) { + default: *out++ = 0xFFU - (UINT8)(((byte >> 4) & 0x0FU) * 0x11U); byte <<= 4; + case 1: *out++ = 0xFFU - (UINT8)(((byte >> 4) & 0x0FU) * 0x11U); + } + pixels -= 2; + } +} + +static void +unpackL4R(UINT8* out, const UINT8* in, int pixels) +{ + /* nibbles (bit order reversed, white is non-zero) */ + while (pixels > 0) { + UINT8 byte = *in++; + byte = BITFLIP[byte]; + switch (pixels) { + default: *out++ = ((byte >> 4) & 0x0FU) * 0x11U; byte <<= 4; + case 1: *out++ = ((byte >> 4) & 0x0FU) * 0x11U; + } + pixels -= 2; + } +} + +static void +unpackL4IR(UINT8* out, const UINT8* in, int pixels) +{ + /* nibbles (bit order reversed, white is zero) */ + while (pixels > 0) { + UINT8 byte = *in++; + byte = BITFLIP[byte]; + switch (pixels) { + default: *out++ = 0xFFU - (UINT8)(((byte >> 4) & 0x0FU) * 0x11U); byte <<= 4; + case 1: *out++ = 0xFFU - (UINT8)(((byte >> 4) & 0x0FU) * 0x11U); } pixels -= 2; } @@ -1053,7 +1147,15 @@ static struct { /* greyscale */ {"L", "L;2", 2, unpackL2}, + {"L", "L;2I", 2, unpackL2I}, + {"L", "L;2R", 2, unpackL2R}, + {"L", "L;2IR", 2, unpackL2IR}, + {"L", "L;4", 4, unpackL4}, + {"L", "L;4I", 4, unpackL4I}, + {"L", "L;4R", 4, unpackL4R}, + {"L", "L;4IR", 4, unpackL4IR}, + {"L", "L", 8, copy1}, {"L", "L;I", 8, unpackLI}, {"L", "L;R", 8, unpackLR}, From 46134f78d245509ba4ed4444923b26f2a5255ce5 Mon Sep 17 00:00:00 2001 From: zwhfly Date: Tue, 29 Mar 2016 13:57:28 +0800 Subject: [PATCH 05/61] Rearrange Tiff Encodings List Refined the order of items in the dict 'OPEN_INFO'. --- PIL/TiffImagePlugin.py | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/PIL/TiffImagePlugin.py b/PIL/TiffImagePlugin.py index 096be6f56..a5e58a659 100644 --- a/PIL/TiffImagePlugin.py +++ b/PIL/TiffImagePlugin.py @@ -141,34 +141,41 @@ OPEN_INFO = { (MM, 0, (1,), 1, (1,), ()): ("1", "1;I"), (II, 0, (1,), 2, (1,), ()): ("1", "1;IR"), (MM, 0, (1,), 2, (1,), ()): ("1", "1;IR"), + (II, 1, (1,), 1, (1,), ()): ("1", "1"), + (MM, 1, (1,), 1, (1,), ()): ("1", "1"), + (II, 1, (1,), 2, (1,), ()): ("1", "1;R"), + (MM, 1, (1,), 2, (1,), ()): ("1", "1;R"), + + (II, 1, (1,), 1, (4,), ()): ("L", "L;4"), + # ? + (II, 0, (1,), 1, (8,), ()): ("L", "L;I"), (MM, 0, (1,), 1, (8,), ()): ("L", "L;I"), (II, 0, (1,), 2, (8,), ()): ("L", "L;IR"), (MM, 0, (1,), 2, (8,), ()): ("L", "L;IR"), - (II, 0, (3,), 1, (32,), ()): ("F", "F;32F"), - (MM, 0, (3,), 1, (32,), ()): ("F", "F;32BF"), - (II, 1, (1,), 1, (1,), ()): ("1", "1"), - (MM, 1, (1,), 1, (1,), ()): ("1", "1"), - (II, 1, (1,), 1, (4,), ()): ("L", "L;4"), - # ? - (II, 1, (1,), 2, (1,), ()): ("1", "1;R"), - (MM, 1, (1,), 2, (1,), ()): ("1", "1;R"), (II, 1, (1,), 1, (8,), ()): ("L", "L"), (MM, 1, (1,), 1, (8,), ()): ("L", "L"), - (II, 1, (1,), 1, (8, 8), (2,)): ("LA", "LA"), - (MM, 1, (1,), 1, (8, 8), (2,)): ("LA", "LA"), (II, 1, (1,), 2, (8,), ()): ("L", "L;R"), (MM, 1, (1,), 2, (8,), ()): ("L", "L;R"), + (II, 1, (1,), 1, (12,), ()): ("I;16", "I;12"), + (II, 1, (1,), 1, (16,), ()): ("I;16", "I;16"), (MM, 1, (1,), 1, (16,), ()): ("I;16B", "I;16B"), (II, 1, (2,), 1, (16,), ()): ("I;16S", "I;16S"), (MM, 1, (2,), 1, (16,), ()): ("I;16BS", "I;16BS"), + + (II, 0, (3,), 1, (32,), ()): ("F", "F;32F"), + (MM, 0, (3,), 1, (32,), ()): ("F", "F;32BF"), (II, 1, (1,), 1, (32,), ()): ("I", "I;32N"), (II, 1, (2,), 1, (32,), ()): ("I", "I;32S"), (MM, 1, (2,), 1, (32,), ()): ("I;32BS", "I;32BS"), (II, 1, (3,), 1, (32,), ()): ("F", "F;32F"), (MM, 1, (3,), 1, (32,), ()): ("F", "F;32BF"), + + (II, 1, (1,), 1, (8, 8), (2,)): ("LA", "LA"), + (MM, 1, (1,), 1, (8, 8), (2,)): ("LA", "LA"), + (II, 2, (1,), 1, (8, 8, 8), ()): ("RGB", "RGB"), (MM, 2, (1,), 1, (8, 8, 8), ()): ("RGB", "RGB"), (II, 2, (1,), 2, (8, 8, 8), ()): ("RGB", "RGB;R"), @@ -183,6 +190,7 @@ OPEN_INFO = { (MM, 2, (1,), 1, (8, 8, 8, 8), (2,)): ("RGBA", "RGBA"), (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, 3, (1,), 1, (1,), ()): ("P", "P;1"), (MM, 3, (1,), 1, (1,), ()): ("P", "P;1"), (II, 3, (1,), 2, (1,), ()): ("P", "P;1R"), @@ -201,10 +209,13 @@ OPEN_INFO = { (MM, 3, (1,), 1, (8, 8), (2,)): ("PA", "PA"), (II, 3, (1,), 2, (8,), ()): ("P", "P;R"), (MM, 3, (1,), 2, (8,), ()): ("P", "P;R"), + (II, 5, (1,), 1, (8, 8, 8, 8), ()): ("CMYK", "CMYK"), (MM, 5, (1,), 1, (8, 8, 8, 8), ()): ("CMYK", "CMYK"), + (II, 6, (1,), 1, (8, 8, 8), ()): ("YCbCr", "YCbCr"), (MM, 6, (1,), 1, (8, 8, 8), ()): ("YCbCr", "YCbCr"), + (II, 8, (1,), 1, (8, 8, 8), ()): ("LAB", "LAB"), (MM, 8, (1,), 1, (8, 8, 8), ()): ("LAB", "LAB"), } From aa0636d81152130ba1fa71d401a908995ab0ac8b Mon Sep 17 00:00:00 2001 From: zwhfly Date: Tue, 29 Mar 2016 14:21:42 +0800 Subject: [PATCH 06/61] Add Tiff Encodings for 2/4 Bit Grayscale Images Added decoding support for 2/4 bit grayscale tiff images, including inverted and/or bit-order-reversed formats. --- PIL/TiffImagePlugin.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/PIL/TiffImagePlugin.py b/PIL/TiffImagePlugin.py index a5e58a659..0f9515ded 100644 --- a/PIL/TiffImagePlugin.py +++ b/PIL/TiffImagePlugin.py @@ -146,8 +146,23 @@ OPEN_INFO = { (II, 1, (1,), 2, (1,), ()): ("1", "1;R"), (MM, 1, (1,), 2, (1,), ()): ("1", "1;R"), + (II, 0, (1,), 1, (2,), ()): ("L", "L;2I"), + (MM, 0, (1,), 1, (2,), ()): ("L", "L;2I"), + (II, 0, (1,), 2, (2,), ()): ("L", "L;2IR"), + (MM, 0, (1,), 2, (2,), ()): ("L", "L;2IR"), + (II, 1, (1,), 1, (2,), ()): ("L", "L;2"), + (MM, 1, (1,), 1, (2,), ()): ("L", "L;2"), + (II, 1, (1,), 2, (2,), ()): ("L", "L;2R"), + (MM, 1, (1,), 2, (2,), ()): ("L", "L;2R"), + + (II, 0, (1,), 1, (4,), ()): ("L", "L;4I"), + (MM, 0, (1,), 1, (4,), ()): ("L", "L;4I"), + (II, 0, (1,), 2, (4,), ()): ("L", "L;4IR"), + (MM, 0, (1,), 2, (4,), ()): ("L", "L;4IR"), (II, 1, (1,), 1, (4,), ()): ("L", "L;4"), - # ? + (MM, 1, (1,), 1, (4,), ()): ("L", "L;4"), + (II, 1, (1,), 2, (4,), ()): ("L", "L;4R"), + (MM, 1, (1,), 2, (4,), ()): ("L", "L;4R"), (II, 0, (1,), 1, (8,), ()): ("L", "L;I"), (MM, 0, (1,), 1, (8,), ()): ("L", "L;I"), From 124bee04852f158146549084a6b799e7c04f6d7e Mon Sep 17 00:00:00 2001 From: zwhfly Date: Tue, 29 Mar 2016 18:56:37 +0800 Subject: [PATCH 07/61] Add Tests for 2/4 bpp Tiff Grayscale Images Including inverted and/or bit-order-reversed formats. --- Tests/images/tiff_gray_2_4_bpp/hopper2.tif | Bin 0 -> 4266 bytes Tests/images/tiff_gray_2_4_bpp/hopper2I.tif | Bin 0 -> 4266 bytes Tests/images/tiff_gray_2_4_bpp/hopper2IR.tif | Bin 0 -> 4266 bytes Tests/images/tiff_gray_2_4_bpp/hopper2R.tif | Bin 0 -> 4266 bytes Tests/images/tiff_gray_2_4_bpp/hopper4.tif | Bin 0 -> 8362 bytes Tests/images/tiff_gray_2_4_bpp/hopper4I.tif | Bin 0 -> 8362 bytes Tests/images/tiff_gray_2_4_bpp/hopper4IR.tif | Bin 0 -> 8362 bytes Tests/images/tiff_gray_2_4_bpp/hopper4R.tif | Bin 0 -> 8362 bytes Tests/test_file_libtiff.py | 33 +++++++++++++++++++ Tests/test_file_tiff.py | 33 +++++++++++++++++++ 10 files changed, 66 insertions(+) create mode 100644 Tests/images/tiff_gray_2_4_bpp/hopper2.tif create mode 100644 Tests/images/tiff_gray_2_4_bpp/hopper2I.tif create mode 100644 Tests/images/tiff_gray_2_4_bpp/hopper2IR.tif create mode 100644 Tests/images/tiff_gray_2_4_bpp/hopper2R.tif create mode 100644 Tests/images/tiff_gray_2_4_bpp/hopper4.tif create mode 100644 Tests/images/tiff_gray_2_4_bpp/hopper4I.tif create mode 100644 Tests/images/tiff_gray_2_4_bpp/hopper4IR.tif create mode 100644 Tests/images/tiff_gray_2_4_bpp/hopper4R.tif diff --git a/Tests/images/tiff_gray_2_4_bpp/hopper2.tif b/Tests/images/tiff_gray_2_4_bpp/hopper2.tif new file mode 100644 index 0000000000000000000000000000000000000000..70057219aa1a4f0339f62f05328f00b4061bf6cf GIT binary patch literal 4266 zcmai%&u<&Y702JwBIS}OA_t-Z(?xUfArj!^PskdzQn;s;!P$b_LuEir!T}Op93V(g zlYasecm;^P=%6LMW5Bv3K%D@h{{$b}9CC61yGWcva&Q96hB*1Yncd|qB{&bz?#z7N zuX*!hsjFAl=McF6hVNgk%b1E!uuYm*+Jyer`xx^yZc) z+H(pS_lC4dJzD*u+bk=%{3CDr)$}D?F8-u{{5&Z+aO^$U9(FdSv8%9P6*&Hd_E+P~rxR}uEt^|5#G;>G$zy8#-zIe$;5^r?PMef^8$pm9VO zt^M}%fWFo*{D0^phrjiV-l)Q3y7HCJoP44Mkz&ZT)L(5r*K7`hc zSBX}uMT*xMg9IM#jgQb%^^=J8g zx0i7*EbNuTe|=ypw^?wc5fsxGdT?WbJrq0+Rod?53ZeEtKF>U;hAQC{Q34V4a)n6y z|N0N}A$T0ZH(xOAZf>viu>Xi?nS!QhQ#Dd)C_gwS}38{0@g-7VVX>g|OeFKJ0zE-W5&GaU`($I{=vk^yVXK z5?zPKb`v#1W{BLI@i(@NeH;oADmfY_QbkdY716~7YT|Yg5pd>Lb{xLR)nT5%N*W;T zi`!(bAHooEb|b&5IwFX7+dO@OY=d1%Fp{RCITI$7FB{hi^Gj z06ew4e2#xKrGYUNPI8Yqub5#Y^fJlvtD%dxQq{yp3s@-)7G46U@)>n9T~==bOjy zUd!e+<|-Dl?}1m*O$7K@av;~kzURXp!$}9;`B=!3{rAkP%*8wQdQl~w<~;US5XDHC zH}GDsWcE7&uYnPllQ+PnkI-?#S;m-sTH-uE!_@{jAGh7Q&p1o<^g;r0ZP&_5Gqy&;sVKCAQUWOf^j`mVqjM(VtA^?t3mr0N>$#t<-^jR_JpPhxURpV}1Pu+>}4l zQEJcOZ)^ShuiBKq;QKRg^p<|?Q&Bz!xGNq0I#0cS-x-68#i92x5obKM>r@9ya_fKq$0#7zlqj(f7PFZb71el zrZeL$<}LnRViLb=w_{fboJ60I;q3o5dL+%$ySKZ$lSspPfIlCWuWq7CP3CdrquDYB zxMD3oZ_*Z`*Tqf3su@RXnY&dV4^M{UFB1{+K)qZ~{+Lo#iE(l|XA@M%3zmG-oVT}w z&a+nb?-1MkUH(VJJ7W&j02ZFpu4L^B#?NGJK0!67U3c2&yanUuEOcIV#+y!iC2Od@Wvx+vyL^kI68#{UB-2eap literal 0 HcmV?d00001 diff --git a/Tests/images/tiff_gray_2_4_bpp/hopper2I.tif b/Tests/images/tiff_gray_2_4_bpp/hopper2I.tif new file mode 100644 index 0000000000000000000000000000000000000000..9feaa08f0667f274342db70b1892558034a8553e GIT binary patch literal 4266 zcmai&&u<$=6vxLQO`#RyhX@rdf)fYe&_AJ$1Vz9ll{#B_bI1ip%2wb%Aua+T(Mv!Y z1CG>iU@dkmvL_@6sLP)KNG*q6K&mU^NQ8rpVh8Wz`(}36vrbf=l--&4dGF1eH$OJX zn{U1%9(_^>vhs&VTld9zeM~ZbH%PWd)fbOpo$-F-Xp1&a)9qP{jQ`c3E&63E)!i9` zjHeCSrWW0OyWKAvxcuX^@_OYVTpd0so_W_V1#tXR_%3yJDuHWoWDR)y`*V|}#ibvr zr7HY0<;}UYDk^cc;`;xc&;d-~e@o1z%k%TQRpAaWSj+k6!lMtwDQb!{PJqDz-Lw9i zr($|d%qL%o1&9B9ntmJ80pf4ILUdIu{*aausGg-?TeJ<{jK_4Nx||&J+ytu&yev1t zZ=~PsD_?eR-L5+E|9mz@h>vuGKAXtus|R~a%fV(aH8{L}UtFXQ8x72{_Dp4GbAIu1 zZ^z-uNL-*B?}5|!TVIElV|6{9@=-#YXZK!Dm{US@q&=t{PV}p{w`4in&?m5(@-flf zF}ZvnHdBt6_YQ1+?3{_i2^))Ua{i8#cucf<@DL8a2EoXYl0Wnb58}uyH%U0WUl`=d zZEom<#+r}R$vl#Q)=FMKi6g&}wBnt_F+Y`Y89VV49v8ArI>$0__{PC;?j_UwURcd| z8WsN1;g4OkmD?^j(uj-cYq4?jh$9p{h@{tTqx44%~vuEb1aGO9Z?^*iw=RaxT@puZLSV;A707;WnbJT zbNyiaF!WT-g9bl!mvi+{f9A|sLS|jb z^71+H(NqQoFgVUr=DcEt)zQl&%Ws4(7FS8>=fu7<-a`*5ph#HPY?j6#|qomQQp9N zcar(9$GiqcTu$i*E`1Cg_?%^c*?T3<^D|uTfb+4N;e_MM{xZn6wfBV`#ymlB-63KS z!qteoe0G2G$yrlD-Qr^$Czkn^-FCtBaKWC#kGst4zHbb4%MN3oW_T3U>&S1gw>;Ew z3)vRJoQv*-^&h=muK(^zQ7Bje^VbsFYHg%$>)lvKE7@){F~G;V+wFLr?oeseN{1_? zity}@n@xkq;9Ud@uTjtCW89bhj;Cp;0*zp5#q5X7gs2A&|AYqMG5FilPYLHIb-&y1 zbcqJI7$Nd3#w;?x-h`L=XbpM+bH$w3+6Ya+ySM<^A9tYESD8~@BXA#|J(j_G035yZ z1b6ZpfO{C5W$^ME^UW7cZ?A}t@12p+dH6>W?qef%m$AR?)8QFD-x~M56%zq`HRp5u zRf)uM@0(?yNmBHy6}9%c%P~OW@TQP*S)4BHxrhyWK^a|BEP|WzXEsu< zI{YUgPJJg#`3t@>jYdC<^9dE@V}QHT;lK0Lo0lBT4Ckr+zTxmYn836<;M5Ks1#e`h zd&n#26lg7V@F&Tb0HiRmHi7@u3jzdc#ze=8NeSyE%`K_b|v# z=t$sin35R(VFjNTR!^!63BPgUWp;Ns{%`>Yg+W@y27^qr-sU&a9o}EVQ{X&sx@^;# z@*eXZ|6XDezhbvzTWg%egpuJK{~CIv%rm{bwzlpo!&$+f56kavqf33}L71S~GY+_7 zEq`Fr*1FZkO~R%bM{A$E;{=aXMYXql9kF6qt|xy?X)JZkKbf-&s*}bCiD}OITcz_H zmE$|aHvgADE=1)KQ4vBk@l$cyb6I;1`bV-h+bv{mG{qT5|5Rn(#Ca6@ryc#G(|$Jh XMWAz;y}*AVo_B0sMw`b(Hs<*sCcY69 literal 0 HcmV?d00001 diff --git a/Tests/images/tiff_gray_2_4_bpp/hopper2IR.tif b/Tests/images/tiff_gray_2_4_bpp/hopper2IR.tif new file mode 100644 index 0000000000000000000000000000000000000000..46241695570bbfe4a0193cf2ba2e882e5bb4fd32 GIT binary patch literal 4266 zcmai&&u<$=6vxL~el$UdA5y6*fl`nl&`bUTL^xKxK*g+^l_E!#oZ{_)Q-B<*b#pUFj3{J0 z7}7qq=<+W!^{Rr+KMvYA+yBGkiR0qkpS_9$%RYeZQgfm0+6p^Hf#Xk3_m^%h{pM7v z@L9=g(}5$}iPN_2UrK2YDzIM^)4}-Z)3c7S15C~5{FLzNO>u*2;v>t!)Eqr9_G32^ zdP|&6-xhNgf8inh-Jm`AANz#pjJWk%P)WeKOXpg&4_-?ebk!M8_j-1M&Kz&cJ@Bi+ zoz2)&gT*V3<^SZT0bKkphxAupIlu0$E{(fm)&eFrCdDKAVK~GZJMXp^#!lb5*jp$a zOr%|LpRRrmPK}>D8C^``jiBV+l*aC^-b|TOO0*+=Oj(@hoWHtcIP1{Y&? zz6qU@!{>uNlOG#rVsS!a(LK)Jk_u0V4)*?s!){1WvZP{<`ILiLGRk!l7B8DPpVam; zrH14qbuk4)wE3yw6BvOeO;y&dg8=WeL{K`U1XMf&?C=1C(|9;e8?nY40+NTeVB!F&kr zhVVTAAI#+TN(^iFi8d*z%Ka8!GM^rzc5V=+Izqho#8%i0fc&+2bDvENfh#u@v9k+{&fHS{w)8gDY33CrtCT?7WhrQXr z#VGRQjt@Kht=XKbhy7*Fj3qkEwf(ZDs;_Or&xRAx25ZSvNpRldud-FsM{=5Fa6qiw!o)73mE`mm7MerCUt zbn{7@Q}6_rK0>=5XX#?~eueY;G*=7YeC$Rz>a)rA%FWu^|2_|dZ(UwKS8fDTE%x>q z&L?L+c1_#(hd53w^DWbMZZq?vzu13czZo-&A+dTR!Tzg=`C9doH>k zt-bHha{Xtwi$XyQ7~v(_YQ7s^k+X>mw}Zl3^M)J@ntpSz9!u0pM%(30t~qWt37&ut z;4IoD?)FTOJ?_hT)0ea!yAn_Fw(f_5_rPJF(iC_C{!95PVgE|j2leKFXbKl2MBPQs zXc!~tO<3ud)>M!0W*IZ*z1Bi~@BuDBw%0$+&M>FEM&KS^dn{8cY#+Y!4?pBJ0QV7_ zW$N2`=3|fbQ`U{l^)r&b0Q)e+eXIq04zc*eM|{2|?t3HJ19Z=eXooX0JR#7~MtC2opPSPM;zum-Sz%TK6hwutchFTy8PLsQU?}4Cd7?5gf4%< zw@Y(+L0m|wC?5mdl@@=VmtHH%cbN0io-fvm2i%M0@@R@vo3JLhk*&uG-njsOh2Y+` zxivN_D4;bL6n6Qb%6WDtNBX;8u}AP_RpHnGdpXn<<^nB&<};!6CkBmOKIkE(oK2z$RZxAn2SqMOZp%=K7zvlH4C_%}>N3~%H0!qa_c zPL~5WUZ!_j+t1;kFbEtp80$%y{hq$f{k47roC62rru-%EG4Cyd>%^D&kqAHka1z;- z;p~5xL99Q6i}UjOne@`2JNvADkYX&z7JM3wPJlf=s2HOO2 z*g5aXkSErw^$eIdlfa(}_*DL)5Vd2XCWL6?uV#&% zZ0unEST<(8=dv+|V%*YsrS^>Wa~$)pTKXrf@oTv)9G%Sc1^yS}bxY?xj5#K<(VzbT D0104I literal 0 HcmV?d00001 diff --git a/Tests/images/tiff_gray_2_4_bpp/hopper2R.tif b/Tests/images/tiff_gray_2_4_bpp/hopper2R.tif new file mode 100644 index 0000000000000000000000000000000000000000..65e0f623e2692b7b3b5e346198169dd31bb7f3dc GIT binary patch literal 4266 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 literal 0 HcmV?d00001 diff --git a/Tests/images/tiff_gray_2_4_bpp/hopper4I.tif b/Tests/images/tiff_gray_2_4_bpp/hopper4I.tif new file mode 100644 index 0000000000000000000000000000000000000000..5c3a17f52dd7e19dcdc0e4ba00bc07997f4a0d1e GIT binary patch literal 8362 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 literal 0 HcmV?d00001 diff --git a/Tests/images/tiff_gray_2_4_bpp/hopper4IR.tif b/Tests/images/tiff_gray_2_4_bpp/hopper4IR.tif new file mode 100644 index 0000000000000000000000000000000000000000..7652f5e6d878fb2fa7b52f662330891f45bcdaa1 GIT binary patch literal 8362 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 z zZ~KBRX-RyI8T*~7V%S|5)AFdT9A<2RkT(4wCmQ7HH(m941i*LWbZqaFj0JvWCuKR0 z%!-Vro3-qJGxp~c5LD8o0tnBiY3^Z?ax!!}HifsH!aiF{r8{uAnoh+^+I8q>^Ej5) zX^H-kvMa!Z3@LbeoJ8)vYfI_$4BiW;{b@_vPI$)MVn8-D;0`tC%A3Q`oyR4KN8Q)I z-K}N3WzKYji@oWTqYT%U_=2rqXK@`+69W9HQ28s@e*ARQ-a2=WD3U)d7klMY(r*Q$ zM@WB#vsT0aaj+Xkp!tGPZYcr_{p4_WH61G|j+m5ZMq??QcaL}CWL%}Uu?CjuzYtLS zwg665oL&=&jz1O0Avq?e@QP_kC!*C>s*^o10H+bH<^ptFK-s?qcx?>Lpz@=K79_m> z$@s>QwBpgnYGP@~e8~;t68yw3P3o$ASGAt8&n8<*f6SjQC9P+o4^eNOcsH%AS`5&5 zA(NTdTI;OT?mH4wjyMK9z3d-L{A;bbdgH7IZy41iM9Tr3@*Bq2@x#9^!Tvea&-9_; z#NRBz!wqJC%>{%HU8$Sh81~cQ$!5!n&B>|K+%t*9-!?jkA!WS3>Hx6sU0kl6vF8&* zzi^!7Txv#44G%?+60AY)jz3?G02<$WafN#J-rA;5N@Z~_CQCb-gvkcfWk{XQ+TG(U z*jHcwc4V$yr&{>T1!!pwE!J)zV)_EWPi6|7dGnh4?P~$3b-Uew_IKH#|S}0O6O`o+YZdf-fA^ zt!+uW`=GP4Sc60FuNHk8q}hhLs(gMO>WBVqrQ~}pab;CJ*Y}+Oe)4sGZ}FkfgJzxRIC=xH$fp}!j6N-bk>uZiFf10VI(!_R4Z#drDovn%6}VklK% zgO1cSlPA7z0sj+}fP+sm?hdH_y6mE#eGR<6Nw}kA1F93N)cX${6QU=N@aiLOv(v?5 zv9;do-Vfl6U+e!u_`afqa9Vz?ZosMSiC6sf^oJL|mSs70Zi)S0EA{&Gaj5fPE)>8w zTlxw_#M=X%Wt@*{0G+)GynKEMeuHAXTpithqwSR(KDOe8^FOOCjD7KlMxWHG#P_FT z$yk@u9Ge+U*K_8SV%(~B&*nOPnqq|T264r0;Y|O$&$+kp_8dPw)-rbb=Z`z71+~5* z>`~MYtN8Y29P_Gg%vC&^|F~trwU&O`Q^!t^t&>i#J1@nWl{&s%scFNAL42l5;oV93 zs45Zl@vFD%EbC4;%W*00A4{cXf65l*tXCr4+c_DOYdoSJ#WVvb< z`nX~&TizA?KS_h;|HEam33YE$<>p}j^;9_)BYZu^in7}BB_yxg$?^5nj7*#J_|V7E zUZGwhrQyozv&T+e?|?M?x#?VKw8b0Czt&b^_c|M+!00A@BZEOCp>7sq{SAC=aK#&r zUS9tPzCL|+==TL-&G&>gRB3RnS;XI0*g&*L5cNdL$96ZT`HSX{K0JgsVH2?qr literal 0 HcmV?d00001 diff --git a/Tests/images/tiff_gray_2_4_bpp/hopper4R.tif b/Tests/images/tiff_gray_2_4_bpp/hopper4R.tif new file mode 100644 index 0000000000000000000000000000000000000000..0cdf4d26e3ec7804048b402db4966230ebddf197 GIT binary patch literal 8362 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 literal 0 HcmV?d00001 diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index 313fb545f..36fa2496a 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -421,6 +421,39 @@ class TestFileLibTiff(LibTiffTestCase): self.assertEqual(im.mode, "L") self.assert_image_similar(im, original, 7.3) + def test_gray_semibyte_per_pixel(self): + test_files = ( + ( + 24.8,#epsilon + (#group + "Tests/images/tiff_gray_2_4_bpp/hopper2.tif", + "Tests/images/tiff_gray_2_4_bpp/hopper2I.tif", + "Tests/images/tiff_gray_2_4_bpp/hopper2R.tif", + "Tests/images/tiff_gray_2_4_bpp/hopper2IR.tif", + ) + ), + ( + 7.3,#epsilon + (#group + "Tests/images/tiff_gray_2_4_bpp/hopper4.tif", + "Tests/images/tiff_gray_2_4_bpp/hopper4I.tif", + "Tests/images/tiff_gray_2_4_bpp/hopper4R.tif", + "Tests/images/tiff_gray_2_4_bpp/hopper4IR.tif", + ) + ), + ) + original = hopper("L") + for epsilon, group in test_files: + im = Image.open(group[0]) + self.assertEqual(im.size, (128, 128)) + self.assertEqual(im.mode, "L") + self.assert_image_similar(im, original, epsilon) + for file in group[1:]: + im2 = Image.open(file) + self.assertEqual(im2.size, (128, 128)) + self.assertEqual(im2.mode, "L") + self.assert_image_equal(im, im2) + def test_save_bytesio(self): # PR 1011 # Test TIFF saving to io.BytesIO() object. diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index 26b6bd4c3..f943d8c92 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -323,6 +323,39 @@ class TestFileTiff(PillowTestCase): self.assertEqual(im.mode, "L") self.assert_image_similar(im, original, 7.3) + def test_gray_semibyte_per_pixel(self): + test_files = ( + ( + 24.8,#epsilon + (#group + "Tests/images/tiff_gray_2_4_bpp/hopper2.tif", + "Tests/images/tiff_gray_2_4_bpp/hopper2I.tif", + "Tests/images/tiff_gray_2_4_bpp/hopper2R.tif", + "Tests/images/tiff_gray_2_4_bpp/hopper2IR.tif", + ) + ), + ( + 7.3,#epsilon + (#group + "Tests/images/tiff_gray_2_4_bpp/hopper4.tif", + "Tests/images/tiff_gray_2_4_bpp/hopper4I.tif", + "Tests/images/tiff_gray_2_4_bpp/hopper4R.tif", + "Tests/images/tiff_gray_2_4_bpp/hopper4IR.tif", + ) + ), + ) + original = hopper("L") + for epsilon, group in test_files: + im = Image.open(group[0]) + self.assertEqual(im.size, (128, 128)) + self.assertEqual(im.mode, "L") + self.assert_image_similar(im, original, epsilon) + for file in group[1:]: + im2 = Image.open(file) + self.assertEqual(im2.size, (128, 128)) + self.assertEqual(im2.mode, "L") + self.assert_image_equal(im, im2) + def test_page_number_x_0(self): # Issue 973 # Test TIFF with tag 297 (Page Number) having value of 0 0. From f869ecd8084e1d1310e6fde6bb6d278e72d28357 Mon Sep 17 00:00:00 2001 From: Eric Soroos Date: Wed, 30 Mar 2016 08:19:23 -0700 Subject: [PATCH 08/61] Dir is not a variable name --- setup.py | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/setup.py b/setup.py index b252bc620..75e6a9322 100644 --- a/setup.py +++ b/setup.py @@ -38,15 +38,15 @@ _LIB_IMAGING = ( "Jpeg2KDecode", "Jpeg2KEncode", "BoxBlur") -def _add_directory(path, dir, where=None): - if dir is None: +def _add_directory(path, subdir, where=None): + if subdir is None: return - dir = os.path.realpath(dir) - if os.path.isdir(dir) and dir not in path: + subdir = os.path.realpath(subdir) + if os.path.isdir(subdir) and subdir not in path: if where is None: - path.append(dir) + path.append(subdir) else: - path.insert(where, dir) + path.insert(where, subdir) def _find_include_file(self, include): @@ -448,20 +448,20 @@ class pil_build_ext(build_ext): if _find_library_file(self, "freetype"): # look for freetype2 include files freetype_version = 0 - for dir in self.compiler.include_dirs: - if os.path.isfile(os.path.join(dir, "ft2build.h")): + for subdir in self.compiler.include_dirs: + if os.path.isfile(os.path.join(subdir, "ft2build.h")): freetype_version = 21 - dir = os.path.join(dir, "freetype2") + subdir = os.path.join(subdir, "freetype2") break - dir = os.path.join(dir, "freetype2") - if os.path.isfile(os.path.join(dir, "ft2build.h")): + subdir = os.path.join(subdir, "freetype2") + if os.path.isfile(os.path.join(subdir, "ft2build.h")): freetype_version = 21 break if freetype_version: feature.freetype = "freetype" feature.freetype_version = freetype_version - if dir: - _add_directory(self.compiler.include_dirs, dir, 0) + if subdir: + _add_directory(self.compiler.include_dirs, subdir, 0) if feature.want('lcms'): if _find_include_file(self, "lcms2.h"): @@ -592,10 +592,10 @@ class pil_build_ext(build_ext): if (os.path.exists(root_tcl) and os.path.exists(root_tk)): print("--- using frameworks at %s" % root) frameworks = ["-framework", "Tcl", "-framework", "Tk"] - dir = os.path.join(root_tcl, "Headers") - _add_directory(self.compiler.include_dirs, dir, 0) - dir = os.path.join(root_tk, "Headers") - _add_directory(self.compiler.include_dirs, dir, 1) + subdir = os.path.join(root_tcl, "Headers") + _add_directory(self.compiler.include_dirs, subdir, 0) + subdir = os.path.join(root_tk, "Headers") + _add_directory(self.compiler.include_dirs, subdir, 1) break if frameworks: exts.append(Extension("PIL._imagingtk", @@ -689,8 +689,8 @@ class pil_build_ext(build_ext): def check_zlib_version(self, include_dirs): # look for unsafe versions of zlib - for dir in include_dirs: - zlibfile = os.path.join(dir, "zlib.h") + for subdir in include_dirs: + zlibfile = os.path.join(subdir, "zlib.h") if os.path.isfile(zlibfile): break else: From bf2df86807597384126842f35132bf4f935332ec Mon Sep 17 00:00:00 2001 From: Eric Soroos Date: Wed, 30 Mar 2016 08:20:27 -0700 Subject: [PATCH 09/61] require, required, and want are not features --- setup.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/setup.py b/setup.py index 75e6a9322..88ad75387 100644 --- a/setup.py +++ b/setup.py @@ -100,10 +100,15 @@ LCMS_ROOT = None class pil_build_ext(build_ext): class feature: - zlib = jpeg = tiff = freetype = tcl = tk = lcms = webp = webpmux = None - jpeg2000 = None + features = ['zlib', 'jpeg', 'tiff', 'freetype', 'tcl', 'tk', + 'lcms', 'webp', 'webpmux', 'jpeg2000'] + required = set(['jpeg', 'zlib']) + def __init__(self): + for f in self.features: + setattr(self, f, None) + def require(self, feat): return feat in self.required @@ -111,9 +116,8 @@ class pil_build_ext(build_ext): return getattr(self, feat) is None def __iter__(self): - for x in dir(self): - if x[1] != '_': - yield x + for x in self.features: + yield x feature = feature() From 999b0a1e8c3d9c265c71370a452acf3e6e9555c0 Mon Sep 17 00:00:00 2001 From: Eric Soroos Date: Wed, 30 Mar 2016 09:13:10 -0700 Subject: [PATCH 10/61] file is not a variable name --- setup.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index 88ad75387..2ab9c870b 100644 --- a/setup.py +++ b/setup.py @@ -522,10 +522,10 @@ class pil_build_ext(build_ext): # core library files = ["_imaging.c"] - for file in _IMAGING: - files.append(file + ".c") - for file in _LIB_IMAGING: - files.append(os.path.join("libImaging", file + ".c")) + for src_file in _IMAGING: + files.append(src_file + ".c") + for src_file in _LIB_IMAGING: + files.append(os.path.join("libImaging", src_file + ".c")) libs = [] defs = [] From d07ab52c66d71e98cbe34f4d9400e8012549783b Mon Sep 17 00:00:00 2001 From: Jonathan Michalon Date: Tue, 23 Feb 2016 14:08:39 +0100 Subject: [PATCH 11/61] SpiderImagePlugin: raise an error when seeking in a non-stack file Using ImageSequence.Iterator on a non-stack SPIDER image leads to infinite loop. EOFError (which stops the iteration) is never raised because when the image isn't a stack, seek() returns gently without error. --- PIL/SpiderImagePlugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PIL/SpiderImagePlugin.py b/PIL/SpiderImagePlugin.py index d5457893c..a59329497 100644 --- a/PIL/SpiderImagePlugin.py +++ b/PIL/SpiderImagePlugin.py @@ -173,7 +173,7 @@ class SpiderImageFile(ImageFile.ImageFile): def seek(self, frame): if self.istack == 0: - return + raise EOFError("attempt to seek in a non-stack file") if frame >= self._nimages: raise EOFError("attempt to seek past end of file") self.stkoffset = self.hdrlen + frame * (self.hdrlen + self.imgbytes) From 6f9fb2eefdfbabcfa0b8438eb460bac0249c0d9e Mon Sep 17 00:00:00 2001 From: wiredfool Date: Sun, 3 Apr 2016 19:20:36 +0100 Subject: [PATCH 12/61] Update CHANGES.rst [ci skip] --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 5741de86b..11454c2ad 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,9 @@ Changelog (Pillow) 3.3.0 (unreleased) ------------------ +- Removed unused variable from selftest #1788 + [radarhere] + - Added warning for as_dict method (deprecated in 3.0.0) #1799 [radarhere] From b0e8e2d0a868e2f476fcfa1a7c269489de89e538 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Sun, 3 Apr 2016 20:08:40 +0100 Subject: [PATCH 13/61] Update CHANGES.rst [ci skip] --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 11454c2ad..c56f2aece 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,9 @@ Changelog (Pillow) 3.3.0 (unreleased) ------------------ +- Add Support for 2/4 bpp Tiff Grayscale Images #1789 + [zwhfly] + - Removed unused variable from selftest #1788 [radarhere] From 8e5cf79a7967c9fc36c1746d1b4863c2baa820f5 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Sun, 3 Apr 2016 20:22:39 +0100 Subject: [PATCH 14/61] Update CHANGES.rst [ci skip] --- CHANGES.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index c56f2aece..7dfef9e55 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,7 +4,7 @@ Changelog (Pillow) 3.3.0 (unreleased) ------------------ -- Add Support for 2/4 bpp Tiff Grayscale Images #1789 +- Added Support for 2/4 bpp Tiff Grayscale Images #1789 [zwhfly] - Removed unused variable from selftest #1788 From dabb68a61e3f3a890286573d2c1bdb758ea9cbfe Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 4 Apr 2016 18:48:21 +1000 Subject: [PATCH 15/61] Added tests --- Tests/test_file_spider.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Tests/test_file_spider.py b/Tests/test_file_spider.py index 53cf3915b..956063167 100644 --- a/Tests/test_file_spider.py +++ b/Tests/test_file_spider.py @@ -1,6 +1,7 @@ from helper import unittest, PillowTestCase, hopper from PIL import Image +from PIL import ImageSequence from PIL import SpiderImagePlugin TEST_FILE = "Tests/images/hopper.spider" @@ -85,6 +86,17 @@ class TestImageSpider(PillowTestCase): self.assertRaises(IOError, lambda: Image.open(invalid_file)) + def test_nonstack_file(self): + im = Image.open(TEST_FILE) + + self.assertRaises(EOFError, lambda: im.seek(0)) + + def test_nonstack_dos(self): + im = Image.open(TEST_FILE) + for i, frame in enumerate(ImageSequence.Iterator(im)): + if i > 1: + self.fail("Non-stack DOS file test failed") + if __name__ == '__main__': unittest.main() From 6899adc346812ed157235a058b6ffad8885cbaad Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 4 Apr 2016 10:07:48 +0100 Subject: [PATCH 16/61] Updated Changes.rst [ci skip] --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 7dfef9e55..3a38dd014 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,9 @@ Changelog (Pillow) 3.3.0 (unreleased) ------------------ +- SpiderImagePlugin: raise an error when seeking in a non-stack file #1794 + [radarhere, jmichalon] + - Added Support for 2/4 bpp Tiff Grayscale Images #1789 [zwhfly] From 77da73c90fc9d3d5715ccf1361bda311350a394f Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 4 Apr 2016 03:08:22 -0700 Subject: [PATCH 17/61] Catch struct.errors when verifying png files, convert to SyntaxErrors, fixes #1755 --- PIL/PngImagePlugin.py | 40 ++++++++++++++++++++++++---------------- Tests/test_file_png.py | 16 ++++++++++++++++ 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/PIL/PngImagePlugin.py b/PIL/PngImagePlugin.py index d6778821b..87847eebd 100644 --- a/PIL/PngImagePlugin.py +++ b/PIL/PngImagePlugin.py @@ -36,6 +36,7 @@ from __future__ import print_function import logging import re import zlib +import struct from PIL import Image, ImageFile, ImagePalette, _binary @@ -106,17 +107,20 @@ class ChunkStream(object): def read(self): "Fetch a new chunk. Returns header information." - - if self.queue: - cid, pos, length = self.queue[-1] - del self.queue[-1] - self.fp.seek(pos) - else: - s = self.fp.read(8) - cid = s[4:] - pos = self.fp.tell() - length = i32(s) - + cid = None + try: + if self.queue: + cid, pos, length = self.queue[-1] + del self.queue[-1] + self.fp.seek(pos) + else: + s = self.fp.read(8) + cid = s[4:] + pos = self.fp.tell() + length = i32(s) + except struct.error: + SyntaxError("truncated PNG file (chunk %s)" % repr(cid)) + if not is_cid(cid): raise SyntaxError("broken PNG file (chunk %s)" % repr(cid)) @@ -138,11 +142,15 @@ class ChunkStream(object): def crc(self, cid, data): "Read and verify checksum" - crc1 = Image.core.crc32(data, Image.core.crc32(cid)) - crc2 = i16(self.fp.read(2)), i16(self.fp.read(2)) - if crc1 != crc2: - raise SyntaxError("broken PNG file" - "(bad header checksum in %s)" % cid) + try: + crc1 = Image.core.crc32(data, Image.core.crc32(cid)) + crc2 = i16(self.fp.read(2)), i16(self.fp.read(2)) + if crc1 != crc2: + raise SyntaxError("broken PNG file (bad header checksum in %s)" + % cid) + except struct.error: + raise SyntaxError("broken PNG file (incomplete checksum in %s)" + % cid) def crc_skip(self, cid, data): "Read checksum. Used if the C module is not present" diff --git a/Tests/test_file_png.py b/Tests/test_file_png.py index cb72b2d73..63ec8a303 100644 --- a/Tests/test_file_png.py +++ b/Tests/test_file_png.py @@ -253,6 +253,22 @@ class TestFilePng(PillowTestCase): im.load() self.assertRaises(RuntimeError, im.verify) + def test_verify_struct_error(self): + # Check open/load/verify exception (#1755) + + # offsets to test, -10: breaks in i32() in read. + # -13: breaks in crc, txt chunk. + # -14: malformed chunk + + for offset in (-10, -13, -14): + with open(TEST_PNG_FILE,'rb') as f: + test_file = f.read()[:offset] + + im = Image.open(BytesIO(test_file)) + self.assertTrue(im.fp is not None) + self.assertRaises(SyntaxError, im.verify) + + def test_roundtrip_dpi(self): # Check dpi roundtripping From 90378c8298313bf9d4e2a99473e6210b859f9b43 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 4 Apr 2016 05:40:37 -0700 Subject: [PATCH 18/61] Fixing compatibility with the truncated images tests --- PIL/PngImagePlugin.py | 28 +++++++++++++++------------- Tests/test_file_png.py | 4 ++-- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/PIL/PngImagePlugin.py b/PIL/PngImagePlugin.py index 87847eebd..cc58fbbc4 100644 --- a/PIL/PngImagePlugin.py +++ b/PIL/PngImagePlugin.py @@ -108,18 +108,16 @@ class ChunkStream(object): def read(self): "Fetch a new chunk. Returns header information." cid = None - try: - if self.queue: - cid, pos, length = self.queue[-1] - del self.queue[-1] - self.fp.seek(pos) - else: - s = self.fp.read(8) - cid = s[4:] - pos = self.fp.tell() - length = i32(s) - except struct.error: - SyntaxError("truncated PNG file (chunk %s)" % repr(cid)) + + if self.queue: + cid, pos, length = self.queue[-1] + del self.queue[-1] + self.fp.seek(pos) + else: + s = self.fp.read(8) + cid = s[4:] + pos = self.fp.tell() + length = i32(s) if not is_cid(cid): raise SyntaxError("broken PNG file (chunk %s)" % repr(cid)) @@ -165,7 +163,11 @@ class ChunkStream(object): cids = [] while True: - cid, pos, length = self.read() + try: + cid, pos, length = self.read() + except struct.error: + raise IOError("truncated PNG file") + if cid == endchunk: break self.crc(cid, ImageFile._safe_read(self.fp, length)) diff --git a/Tests/test_file_png.py b/Tests/test_file_png.py index 63ec8a303..f6a47c464 100644 --- a/Tests/test_file_png.py +++ b/Tests/test_file_png.py @@ -256,7 +256,7 @@ class TestFilePng(PillowTestCase): def test_verify_struct_error(self): # Check open/load/verify exception (#1755) - # offsets to test, -10: breaks in i32() in read. + # offsets to test, -10: breaks in i32() in read. (IOError) # -13: breaks in crc, txt chunk. # -14: malformed chunk @@ -266,7 +266,7 @@ class TestFilePng(PillowTestCase): im = Image.open(BytesIO(test_file)) self.assertTrue(im.fp is not None) - self.assertRaises(SyntaxError, im.verify) + self.assertRaises((IOError, SyntaxError), im.verify) def test_roundtrip_dpi(self): From 2fdb3868823a28f10bb82668180bdea5314f31a4 Mon Sep 17 00:00:00 2001 From: Hugo Date: Mon, 4 Apr 2016 16:39:35 +0300 Subject: [PATCH 19/61] Update CHANGES.rst [CI skip] --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 3a38dd014..08dc2efd9 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,9 @@ Changelog (Pillow) 3.3.0 (unreleased) ------------------ +- Catch struct.errors when verifying png files #1805 + [wiredfool] + - SpiderImagePlugin: raise an error when seeking in a non-stack file #1794 [radarhere, jmichalon] From 619d5effa60dc1a9997b7edc68c71856cea25e01 Mon Sep 17 00:00:00 2001 From: Hugo Date: Mon, 4 Apr 2016 18:25:31 +0300 Subject: [PATCH 20/61] Tabulate badges Inspired by https://github.com/pytest-dev/pytest-cov/blob/master/README.rst [CI skip] --- README.rst | 47 +++++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/README.rst b/README.rst index e996ed4f7..63bc62604 100644 --- a/README.rst +++ b/README.rst @@ -6,41 +6,56 @@ Python Imaging Library (Fork) Pillow is the friendly PIL fork by `Alex Clark and Contributors `_. PIL is the Python Imaging Library by Fredrik Lundh and Contributors. -.. image:: https://zenodo.org/badge/17549/python-pillow/Pillow.svg - :target: https://zenodo.org/badge/latestdoi/17549/python-pillow/Pillow +.. start-badges -.. image:: https://readthedocs.org/projects/pillow/badge/?version=latest +.. list-table:: + :stub-columns: 1 + + * - docs + - |docs| + * - tests + - | |linux| |osx| |windows| |coverage| |health| + * - package + - |zenodo| |version| |downloads| + +.. |docs| image:: https://readthedocs.org/projects/pillow/badge/?version=latest :target: http://pillow.readthedocs.org/?badge=latest :alt: Documentation Status -.. image:: https://img.shields.io/travis/python-pillow/Pillow/master.svg?label=Linux%20build +.. |linux| image:: https://img.shields.io/travis/python-pillow/Pillow/master.svg?label=Linux%20build :target: https://travis-ci.org/python-pillow/Pillow :alt: Travis CI build status (Linux) -.. image:: https://img.shields.io/travis/python-pillow/pillow-wheels/latest.svg?label=OS%20X%20build +.. |osx| image:: https://img.shields.io/travis/python-pillow/pillow-wheels/latest.svg?label=OS%20X%20build :target: https://travis-ci.org/python-pillow/pillow-wheels :alt: Travis CI build status (OS X) -.. image:: https://img.shields.io/appveyor/ci/python-pillow/Pillow/master.svg?label=Windows%20build +.. |windows| image:: https://img.shields.io/appveyor/ci/python-pillow/Pillow/master.svg?label=Windows%20build :target: https://ci.appveyor.com/project/python-pillow/Pillow :alt: AppVeyor CI build status (Windows) -.. image:: https://img.shields.io/pypi/v/pillow.svg - :target: https://pypi.python.org/pypi/Pillow/ - :alt: Latest PyPI version - -.. image:: https://img.shields.io/pypi/dm/pillow.svg - :target: https://pypi.python.org/pypi/Pillow/ - :alt: Number of PyPI downloads - -.. image:: https://coveralls.io/repos/python-pillow/Pillow/badge.svg?branch=master&service=github +.. |coverage| image:: https://coveralls.io/repos/python-pillow/Pillow/badge.svg?branch=master&service=github :target: https://coveralls.io/github/python-pillow/Pillow?branch=master :alt: Code coverage -.. image:: https://landscape.io/github/python-pillow/Pillow/master/landscape.svg +.. |health| image:: https://landscape.io/github/python-pillow/Pillow/master/landscape.svg :target: https://landscape.io/github/python-pillow/Pillow/master :alt: Code health +.. |zenodo| image:: https://zenodo.org/badge/17549/python-pillow/Pillow.svg + :target: https://zenodo.org/badge/latestdoi/17549/python-pillow/Pillow + +.. |version| image:: https://img.shields.io/pypi/v/pillow.svg + :target: https://pypi.python.org/pypi/Pillow/ + :alt: Latest PyPI version + +.. |downloads| image:: https://img.shields.io/pypi/dm/pillow.svg + :target: https://pypi.python.org/pypi/Pillow/ + :alt: Number of PyPI downloads + +.. end-badges + + More Information ---------------- From 7d64ab3b9b2c0a47f3142bc309b2eb7660e41595 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 5 Apr 2016 19:32:24 +1000 Subject: [PATCH 21/61] Fixed typo [ci skip] --- CHANGES.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 08dc2efd9..2344a1931 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -46,7 +46,7 @@ Changelog (Pillow) - Fixed documented name of JPEG property #1783 [radarhere] -- Fixed UnboundLocalErrorwhen loading a corrupt jpeg2k file #1780 +- Fixed UnboundLocalError when loading a corrupt jpeg2k file #1780 [wiredfool] - Fixed integer overflow in path.c #1773 From 3478464ce881ee05c4bd31f1d9c8dad3f097649e Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 5 Apr 2016 20:42:24 +1000 Subject: [PATCH 22/61] Fixed typo --- PIL/ImageCms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PIL/ImageCms.py b/PIL/ImageCms.py index ba5504acb..5eea2fd38 100644 --- a/PIL/ImageCms.py +++ b/PIL/ImageCms.py @@ -1,7 +1,7 @@ # The Python Imaging Library. # $Id$ -# Optional color managment support, based on Kevin Cazabon's PyCMS +# Optional color management support, based on Kevin Cazabon's PyCMS # library. # History: From 1888d605049a3cbfe36cdf38dc79a6a239601547 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 5 Apr 2016 23:01:39 +1000 Subject: [PATCH 23/61] Added PixarImagePlugin file extension --- PIL/PixarImagePlugin.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/PIL/PixarImagePlugin.py b/PIL/PixarImagePlugin.py index db2ee55f8..783462a9a 100644 --- a/PIL/PixarImagePlugin.py +++ b/PIL/PixarImagePlugin.py @@ -64,5 +64,4 @@ class PixarImageFile(ImageFile.ImageFile): Image.register_open(PixarImageFile.format, PixarImageFile) -# -# FIXME: what's the standard extension? +Image.register_extension(PixarImageFile.format, ".pxr") From 8c9e64de6dcb03216638b92154b6d162eef77415 Mon Sep 17 00:00:00 2001 From: Hugo Date: Tue, 5 Apr 2016 16:11:28 +0300 Subject: [PATCH 24/61] Update CHANGES.rst [CI skip] --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 2344a1931..e2d37e2ad 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,9 @@ Changelog (Pillow) 3.3.0 (unreleased) ------------------ +- Add PixarImagePlugin file extension #1809 + [radarhere] + - Catch struct.errors when verifying png files #1805 [wiredfool] From 8754f65a428e8bc72d6be18e2d7606dbb5fc97c6 Mon Sep 17 00:00:00 2001 From: anatoly techtonik Date: Wed, 6 Apr 2016 14:36:12 +0300 Subject: [PATCH 25/61] README.rst fix contribution link --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 63bc62604..13fd77a78 100644 --- a/README.rst +++ b/README.rst @@ -65,7 +65,7 @@ More Information - `Installation `_ - `Handbook `_ -- `Contribute `_ +- `Contribute `_ - `Issues `_ - `Pull requests `_ From e84e02997c6c54dd550e75061a7ee4cd5b6b53b9 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Wed, 6 Apr 2016 06:22:12 -0700 Subject: [PATCH 26/61] Fixes DIB image format The DIB image format uses the 40 byte BMP header, followed by 3 masks for RGB channels. We were reading 4 masks, consuming the first pixel of the image. Mostly fixes issue #1293. Remaining issue: alpha channel is actually a transparency mask. --- PIL/BmpImagePlugin.py | 6 +++++- Tests/images/clipboard.dib | Bin 0 -> 208436 bytes Tests/images/clipboard_target.png | Bin 0 -> 9493 bytes Tests/test_file_bmp.py | 7 +++++++ 4 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 Tests/images/clipboard.dib create mode 100644 Tests/images/clipboard_target.png diff --git a/PIL/BmpImagePlugin.py b/PIL/BmpImagePlugin.py index e398445fa..950ee13a1 100644 --- a/PIL/BmpImagePlugin.py +++ b/PIL/BmpImagePlugin.py @@ -109,7 +109,11 @@ class BmpImageFile(ImageFile.ImageFile): for idx, mask in enumerate(['r_mask', 'g_mask', 'b_mask', 'a_mask']): file_info[mask] = i32(header_data[36+idx*4:40+idx*4]) else: - for mask in ['r_mask', 'g_mask', 'b_mask', 'a_mask']: + # 40 byte headers only have the three components in the bitfields masks, + # ref: https://msdn.microsoft.com/en-us/library/windows/desktop/dd183376(v=vs.85).aspx + # See also https://github.com/python-pillow/Pillow/issues/1293 + file_info['a_mask'] = 0xff000000 + for mask in ['r_mask', 'g_mask', 'b_mask']: file_info[mask] = i32(read(4)) file_info['rgb_mask'] = (file_info['r_mask'], file_info['g_mask'], file_info['b_mask']) file_info['rgba_mask'] = (file_info['r_mask'], file_info['g_mask'], file_info['b_mask'], file_info['a_mask']) diff --git a/Tests/images/clipboard.dib b/Tests/images/clipboard.dib new file mode 100644 index 0000000000000000000000000000000000000000..03dcab81d0d3c0b53227930815216ddbc4d22223 GIT binary patch literal 208436 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 literal 0 HcmV?d00001 diff --git a/Tests/images/clipboard_target.png b/Tests/images/clipboard_target.png new file mode 100644 index 0000000000000000000000000000000000000000..46a69654340344332751d73e276bfc83dcbe95af GIT binary patch literal 9493 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 snR%T;3;!R0jh(TDsmFf;SU9- Date: Wed, 6 Apr 2016 07:38:24 -0700 Subject: [PATCH 27/61] Added Transparency mask unpacker for BMP files --- PIL/BmpImagePlugin.py | 17 ++++++++++++++--- libImaging/Unpack.c | 16 ++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/PIL/BmpImagePlugin.py b/PIL/BmpImagePlugin.py index 950ee13a1..94764855d 100644 --- a/PIL/BmpImagePlugin.py +++ b/PIL/BmpImagePlugin.py @@ -112,7 +112,8 @@ class BmpImageFile(ImageFile.ImageFile): # 40 byte headers only have the three components in the bitfields masks, # ref: https://msdn.microsoft.com/en-us/library/windows/desktop/dd183376(v=vs.85).aspx # See also https://github.com/python-pillow/Pillow/issues/1293 - file_info['a_mask'] = 0xff000000 + # Note below, None is a key in the SUPPORTED and MASK_MODES structures. + file_info['a_mask'] = None for mask in ['r_mask', 'g_mask', 'b_mask']: file_info[mask] = i32(read(4)) file_info['rgb_mask'] = (file_info['r_mask'], file_info['g_mask'], file_info['b_mask']) @@ -134,12 +135,22 @@ class BmpImageFile(ImageFile.ImageFile): # ----------------- Process BMP with Bitfields compression (not palette) if file_info['compression'] == self.BITFIELDS: SUPPORTED = { - 32: [(0xff0000, 0xff00, 0xff, 0x0), (0xff0000, 0xff00, 0xff, 0xff000000), (0x0, 0x0, 0x0, 0x0)], + 32: [(0xff0000, 0xff00, 0xff, 0x0), + (0xff0000, 0xff00, 0xff, None), + (0xff0000, 0xff00, 0xff, 0xff000000), + (0x0, 0x0, 0x0, 0x0)], 24: [(0xff0000, 0xff00, 0xff)], 16: [(0xf800, 0x7e0, 0x1f), (0x7c00, 0x3e0, 0x1f)] } + # From inspecting DIB files from Vista screenshots, the + # file format is a 32 bit color image, where the 'Alpha' + # channel for screenshots is actually a transparency mask + # (255-alpha) where 00 is solid and ff is transparent. I + # can't find documentation of this, but it matches + # imagemagick's conversion of the .dib file into a .png. MASK_MODES = { (32, (0xff0000, 0xff00, 0xff, 0x0)): "BGRX", + (32, (0xff0000, 0xff00, 0xff, None)): "BGRT", (32, (0xff0000, 0xff00, 0xff, 0xff000000)): "BGRA", (32, (0x0, 0x0, 0x0, 0x0)): "BGRA", (24, (0xff0000, 0xff00, 0xff)): "BGR", @@ -149,7 +160,7 @@ class BmpImageFile(ImageFile.ImageFile): if file_info['bits'] in SUPPORTED: if file_info['bits'] == 32 and file_info['rgba_mask'] in SUPPORTED[file_info['bits']]: raw_mode = MASK_MODES[(file_info['bits'], file_info['rgba_mask'])] - self.mode = "RGBA" if raw_mode in ("BGRA",) else self.mode + self.mode = "RGBA" if raw_mode in ("BGRA", "BGRT") else self.mode elif file_info['bits'] in (24, 16) and file_info['rgb_mask'] in SUPPORTED[file_info['bits']]: raw_mode = MASK_MODES[(file_info['bits'], file_info['rgb_mask'])] else: diff --git a/libImaging/Unpack.c b/libImaging/Unpack.c index 3fab73cec..9b3e666e8 100644 --- a/libImaging/Unpack.c +++ b/libImaging/Unpack.c @@ -738,6 +738,21 @@ unpackBGRA(UINT8* out, const UINT8* in, int pixels) } } +static void +unpackBGRT(UINT8* out, const UINT8* in, int pixels) +{ + int i; + /* RGBA, reversed bytes */ + /* Transparency map, rather than an alpha channel */ + for (i = 0; i < pixels; i++) { + out[R] = in[2]; + out[G] = in[1]; + out[B] = in[0]; + out[A] = 255 - in[3]; + out += 4; in += 4; + } +} + /* Unpack to "CMYK" image */ @@ -1111,6 +1126,7 @@ static struct { {"RGBA", "RGBA;4B", 16, ImagingUnpackRGBA4B}, {"RGBA", "RGBA;16B", 64, unpackRGBA16B}, {"RGBA", "BGRA", 32, unpackBGRA}, + {"RGBA", "BGRT", 32, unpackBGRT}, {"RGBA", "ARGB", 32, unpackARGB}, {"RGBA", "ABGR", 32, unpackABGR}, {"RGBA", "YCCA;P", 32, ImagingUnpackYCCA}, From 9fa3fb98f3d7786adcefa11c3763446056c7256b Mon Sep 17 00:00:00 2001 From: Hugo Date: Wed, 6 Apr 2016 19:59:40 +0300 Subject: [PATCH 28/61] Update CHANGES.rst [CI skip] --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index e2d37e2ad..1385cd6ad 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,9 @@ Changelog (Pillow) 3.3.0 (unreleased) ------------------ +- Fix for DIB/BMP images #1813 + [wiredfool] + - Add PixarImagePlugin file extension #1809 [radarhere] From b38c32ed70e6cd425dd1af80df2f7d2d7364fc06 Mon Sep 17 00:00:00 2001 From: Stephen Arthur Date: Wed, 6 Apr 2016 18:47:51 -0700 Subject: [PATCH 29/61] Valid range for baseline jpeg qtables 0 to 255, fixed issue from using signed char instead of unsigned char. added test --- PIL/JpegImagePlugin.py | 2 +- Tests/test_file_jpeg.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/PIL/JpegImagePlugin.py b/PIL/JpegImagePlugin.py index 386939ba7..0ed1fc73f 100644 --- a/PIL/JpegImagePlugin.py +++ b/PIL/JpegImagePlugin.py @@ -640,7 +640,7 @@ def _save(im, fp, filename): try: if len(table) != 64: raise - table = array.array('b', table) + table = array.array('B', table) except TypeError: raise ValueError("Invalid quantization table") else: diff --git a/Tests/test_file_jpeg.py b/Tests/test_file_jpeg.py index 7b60f60b1..342fe74db 100644 --- a/Tests/test_file_jpeg.py +++ b/Tests/test_file_jpeg.py @@ -314,6 +314,10 @@ class TestFileJpeg(PillowTestCase): 30) self.assert_image_similar(im, self.roundtrip(im, qtables='keep'), 30) + # valid bounds for baseline qtable + bounds_qtable = [int(s) for s in ("255 0 " * 32).split(None)] + self.roundtrip(im, qtables=[bounds_qtable]) + # values from wizard.txt in jpeg9-a src package. standard_l_qtable = [int(s) for s in """ 16 11 10 16 24 40 51 61 From 5025bdd4879a16f794c109e4b8d87bd29869bab5 Mon Sep 17 00:00:00 2001 From: Stephen Arthur Date: Thu, 7 Apr 2016 09:35:14 -0700 Subject: [PATCH 30/61] Valid range for baseline jpeg qtables 1 to 255, fixed overflow from using signed char instead of unsigned char. added test --- Tests/test_file_jpeg.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/test_file_jpeg.py b/Tests/test_file_jpeg.py index 342fe74db..3b2e6cb20 100644 --- a/Tests/test_file_jpeg.py +++ b/Tests/test_file_jpeg.py @@ -315,7 +315,7 @@ class TestFileJpeg(PillowTestCase): self.assert_image_similar(im, self.roundtrip(im, qtables='keep'), 30) # valid bounds for baseline qtable - bounds_qtable = [int(s) for s in ("255 0 " * 32).split(None)] + bounds_qtable = [int(s) for s in ("255 1 " * 32).split(None)] self.roundtrip(im, qtables=[bounds_qtable]) # values from wizard.txt in jpeg9-a src package. From 6ab84373be8f43aa779ca433855694994b1f7716 Mon Sep 17 00:00:00 2001 From: Eric Soroos Date: Wed, 30 Mar 2016 09:16:10 -0700 Subject: [PATCH 31/61] debug logging for setup.py --- setup.py | 87 +++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 67 insertions(+), 20 deletions(-) diff --git a/setup.py b/setup.py index 2ab9c870b..1e55855a9 100644 --- a/setup.py +++ b/setup.py @@ -37,6 +37,15 @@ _LIB_IMAGING = ( "XbmEncode", "ZipDecode", "ZipEncode", "TiffDecode", "Incremental", "Jpeg2KDecode", "Jpeg2KEncode", "BoxBlur") +DEBUG = False + +def _dbg(s, tp=None): + if DEBUG: + if tp: + print(s % tp) + return + print(s) + def _add_directory(path, subdir, where=None): if subdir is None: @@ -44,14 +53,18 @@ def _add_directory(path, subdir, where=None): subdir = os.path.realpath(subdir) if os.path.isdir(subdir) and subdir not in path: if where is None: + _dbg('Appending path %s', subdir) path.append(subdir) else: + _dbg('Inserting path %s', subdir) path.insert(where, subdir) def _find_include_file(self, include): for directory in self.compiler.include_dirs: + _dbg('Checking for include file %s in %s', (include, directory)) if os.path.isfile(os.path.join(directory, include)): + _dbg('Found %s', include) return 1 return 0 @@ -61,15 +74,22 @@ def _find_library_file(self, library): # lib extension, not the system shared lib extension: e.g. .cpython-33.so # vs .so. See Python bug http://bugs.python.org/16754 if 'cpython' in self.compiler.shared_lib_extension: + _dbg('stripping cpython from shared library extension %s', + self.compiler.shared_lib_extension) existing = self.compiler.shared_lib_extension self.compiler.shared_lib_extension = "." + existing.split('.')[-1] ret = self.compiler.find_library_file(self.compiler.library_dirs, library) self.compiler.shared_lib_extension = existing - return ret else: - return self.compiler.find_library_file(self.compiler.library_dirs, - library) + ret = self.compiler.find_library_file(self.compiler.library_dirs, + library) + if ret: + _dbg('Found library %s at %s', (library, ret)) + else: + _dbg("Couldn't find library %s in %s", + (library, self.compiler.library_dirs)) + return ret def _lib_include(root): @@ -125,7 +145,7 @@ class pil_build_ext(build_ext): ('disable-%s' % x, None, 'Disable support for %s' % x) for x in feature ] + [ ('enable-%s' % x, None, 'Enable support for %s' % x) for x in feature - ] + ] + [('debug', None, 'Debug logging')] def initialize_options(self): build_ext.initialize_options(self) @@ -135,15 +155,20 @@ class pil_build_ext(build_ext): def finalize_options(self): build_ext.finalize_options(self) + if self.debug: + global DEBUG + DEBUG = True for x in self.feature: if getattr(self, 'disable_%s' % x): setattr(self.feature, x, False) self.feature.required.discard(x) + _dbg('Disabling %s', x) if getattr(self, 'enable_%s' % x): raise ValueError( 'Conflicting options: --enable-%s and --disable-%s' % (x, x)) if getattr(self, 'enable_%s' % x): + _dbg('Requiring %s', x) self.feature.required.add(x) def build_extensions(self): @@ -318,6 +343,9 @@ class pil_build_ext(build_ext): if _tkinter: TCL_VERSION = _tkinter.TCL_VERSION[:3] + _dbg('Tkinter found, will check for Tcl/Tk') + else: + _dbg('Tkinter not found') if _tkinter and not TCL_ROOT: # we have Tkinter but the TCL_ROOT variable was not set; @@ -338,6 +366,7 @@ class pil_build_ext(build_ext): ] for TCL_ROOT in roots: TCL_ROOT = os.path.abspath(TCL_ROOT) + _dbg('Checking %s for tk.h', TCL_ROOT) if os.path.isfile(os.path.join(TCL_ROOT, "include", "tk.h")): # FIXME: use distutils logging (?) print("--- using Tcl/Tk libraries at", TCL_ROOT) @@ -346,6 +375,7 @@ class pil_build_ext(build_ext): break else: TCL_ROOT = None + _dbg('Tcl/tk not found') # add standard directories @@ -377,6 +407,7 @@ class pil_build_ext(build_ext): best_path = os.path.join(program_files, name) if best_path: + _dbg('Adding %s to search list', best_path) _add_directory(library_dirs, os.path.join(best_path, 'lib')) _add_directory(include_dirs, os.path.join(best_path, 'include')) @@ -394,6 +425,7 @@ class pil_build_ext(build_ext): feature = self.feature if feature.want('zlib'): + _dbg('Looking for zlib') if _find_include_file(self, "zlib.h"): if _find_library_file(self, "z"): feature.zlib = "z" @@ -402,6 +434,7 @@ class pil_build_ext(build_ext): feature.zlib = "zlib" # alternative name if feature.want('jpeg'): + _dbg('Looking for jpeg') if _find_include_file(self, "jpeglib.h"): if _find_library_file(self, "jpeg"): feature.jpeg = "jpeg" @@ -411,11 +444,13 @@ class pil_build_ext(build_ext): feature.openjpeg_version = None if feature.want('jpeg2000'): + _dbg('Looking for jpeg2000') best_version = None best_path = None # Find the best version for directory in self.compiler.include_dirs: + _dbg('Checking for openjpeg-#.# in %s', directory) try: listdir = os.listdir(directory) except Exception: @@ -425,10 +460,12 @@ class pil_build_ext(build_ext): if name.startswith('openjpeg-') and \ os.path.isfile(os.path.join(directory, name, 'openjpeg.h')): + _dbg('Found openjpeg.h in %s/%s',(directory, name)) version = tuple([int(x) for x in name[9:].split('.')]) if best_version is None or version > best_version: best_version = version best_path = os.path.join(directory, name) + _dbg('Best openjpeg version %s so far in %s', (best_version, best_path)) if best_version and _find_library_file(self, 'openjp2'): # Add the directory to the include path so we can include @@ -440,25 +477,32 @@ class pil_build_ext(build_ext): best_version]) if feature.want('tiff'): - if _find_library_file(self, "tiff"): - feature.tiff = "tiff" - if sys.platform == "win32" and _find_library_file(self, "libtiff"): - feature.tiff = "libtiff" - if (sys.platform == "darwin" and - _find_library_file(self, "libtiff")): - feature.tiff = "libtiff" + _dbg('Looking for tiff') + if _find_include_file(self, 'tiff.h'): + if _find_library_file(self, "tiff"): + feature.tiff = "tiff" + if sys.platform == "win32" and _find_library_file(self, "libtiff"): + feature.tiff = "libtiff" + if (sys.platform == "darwin" and + _find_library_file(self, "libtiff")): + feature.tiff = "libtiff" if feature.want('freetype'): + _dbg('Looking for freetype') if _find_library_file(self, "freetype"): # look for freetype2 include files freetype_version = 0 for subdir in self.compiler.include_dirs: + _dbg('Checking for include file %s in %s', ("ft2build.h", subdir)) if os.path.isfile(os.path.join(subdir, "ft2build.h")): + _dbg('Found %s in %s', ("ft2build.h", subdir)) freetype_version = 21 subdir = os.path.join(subdir, "freetype2") break subdir = os.path.join(subdir, "freetype2") + _dbg('Checking for include file %s in %s', ("ft2build.h", subdir)) if os.path.isfile(os.path.join(subdir, "ft2build.h")): + _dbg('Found %s in %s', ("ft2build.h", subdir)) freetype_version = 21 break if freetype_version: @@ -468,6 +512,7 @@ class pil_build_ext(build_ext): _add_directory(self.compiler.include_dirs, subdir, 0) if feature.want('lcms'): + _dbg('Looking for lcms') if _find_include_file(self, "lcms2.h"): if _find_library_file(self, "lcms2"): feature.lcms = "lcms2" @@ -479,17 +524,20 @@ class pil_build_ext(build_ext): # the library names may vary somewhat (e.g. tcl85 or tcl8.5) version = TCL_VERSION[0] + TCL_VERSION[2] if feature.want('tcl'): + _dbg('Looking for TCL') if _find_library_file(self, "tcl" + version): feature.tcl = "tcl" + version elif _find_library_file(self, "tcl" + TCL_VERSION): feature.tcl = "tcl" + TCL_VERSION if feature.want('tk'): + _dbg('Looking for TK') if _find_library_file(self, "tk" + version): feature.tk = "tk" + version elif _find_library_file(self, "tk" + TCL_VERSION): feature.tk = "tk" + TCL_VERSION if feature.want('webp'): + _dbg('Looking for webp') if (_find_include_file(self, "webp/encode.h") and _find_include_file(self, "webp/decode.h")): # In Google's precompiled zip it is call "libwebp": @@ -499,6 +547,7 @@ class pil_build_ext(build_ext): feature.webp = "libwebp" if feature.want('webpmux'): + _dbg('Looking for webpmux') if (_find_include_file(self, "webp/mux.h") and _find_include_file(self, "webp/demux.h")): if (_find_library_file(self, "webpmux") and @@ -561,7 +610,7 @@ class pil_build_ext(build_ext): ["_imagingft.c"], libraries=["freetype"])) - if os.path.isfile("_imagingcms.c") and feature.lcms: + if feature.lcms: extra = [] if sys.platform == "win32": extra.extend(["user32", "gdi32"]) @@ -569,7 +618,7 @@ class pil_build_ext(build_ext): ["_imagingcms.c"], libraries=[feature.lcms] + extra)) - if os.path.isfile("_webp.c") and feature.webp: + if feature.webp: libs = [feature.webp] defs = [] @@ -590,6 +639,7 @@ class pil_build_ext(build_ext): framework_roots = [ "/Library/Frameworks", "/System/Library/Frameworks" ] + _dbg('Looking for TclTk Framework Build') for root in framework_roots: root_tcl = os.path.join(root, "Tcl.framework") root_tk = os.path.join(root, "Tk.framework") @@ -611,11 +661,8 @@ class pil_build_ext(build_ext): ["_imagingtk.c", "Tk/tkImaging.c"], libraries=[feature.tcl, feature.tk])) - if os.path.isfile("_imagingmath.c"): - exts.append(Extension("PIL._imagingmath", ["_imagingmath.c"])) - - if os.path.isfile("_imagingmorph.c"): - exts.append(Extension("PIL._imagingmorph", ["_imagingmorph.c"])) + exts.append(Extension("PIL._imagingmath", ["_imagingmath.c"])) + exts.append(Extension("PIL._imagingmorph", ["_imagingmorph.c"])) self.extensions[:] = exts @@ -684,8 +731,8 @@ class pil_build_ext(build_ext): if not all: print("To add a missing option, make sure you have the required") - print("library, and set the corresponding ROOT variable in the") - print("setup.py script.") + print("library and headers.") + print("See http://pillow.readthedocs.org/en/latest/installation.html#building-from-source") print("") print("To check the build, run the selftest.py script.") From 33ed45c762959b1b6fa20ca29dd8f66dba9e1301 Mon Sep 17 00:00:00 2001 From: Alex Clark Date: Wed, 30 Mar 2016 15:47:27 -0400 Subject: [PATCH 32/61] Clean up (yapf) Sorry, couldn't resist. As for the issues you raised, they are unfortunately not surprising. Our setup.py has to be complex, but doesn't need to be complicated. I've been trying to avoid a complete rewrite, but maybe it's time. --- setup.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index 1e55855a9..c618a56e7 100644 --- a/setup.py +++ b/setup.py @@ -39,6 +39,7 @@ _LIB_IMAGING = ( DEBUG = False + def _dbg(s, tp=None): if DEBUG: if tp: @@ -83,12 +84,12 @@ def _find_library_file(self, library): self.compiler.shared_lib_extension = existing else: ret = self.compiler.find_library_file(self.compiler.library_dirs, - library) + library) if ret: _dbg('Found library %s at %s', (library, ret)) else: _dbg("Couldn't find library %s in %s", - (library, self.compiler.library_dirs)) + (library, self.compiler.library_dirs)) return ret @@ -120,8 +121,8 @@ LCMS_ROOT = None class pil_build_ext(build_ext): class feature: - features = ['zlib', 'jpeg', 'tiff', 'freetype', 'tcl', 'tk', - 'lcms', 'webp', 'webpmux', 'jpeg2000'] + features = ['zlib', 'jpeg', 'tiff', 'freetype', 'tcl', 'tk', 'lcms', + 'webp', 'webpmux', 'jpeg2000'] required = set(['jpeg', 'zlib']) @@ -460,12 +461,13 @@ class pil_build_ext(build_ext): if name.startswith('openjpeg-') and \ os.path.isfile(os.path.join(directory, name, 'openjpeg.h')): - _dbg('Found openjpeg.h in %s/%s',(directory, name)) + _dbg('Found openjpeg.h in %s/%s', (directory, name)) version = tuple([int(x) for x in name[9:].split('.')]) if best_version is None or version > best_version: best_version = version best_path = os.path.join(directory, name) - _dbg('Best openjpeg version %s so far in %s', (best_version, best_path)) + _dbg('Best openjpeg version %s so far in %s', + (best_version, best_path)) if best_version and _find_library_file(self, 'openjp2'): # Add the directory to the include path so we can include From 233afecb905617f02270458a1c7ca3c6757bf851 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Sat, 9 Apr 2016 08:15:24 -0700 Subject: [PATCH 33/61] Documentation of --debug flag --- docs/installation.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/installation.rst b/docs/installation.rst index 45b0c3351..1f4e8038e 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -181,6 +181,11 @@ Build Options the libraries are not found. Webpmux (WebP metadata) relies on WebP support. Tcl and Tk also must be used together. +* Build flags: ``--debug``. Adds a debugging flag to the include and + library search process to dump all paths searched for and found to + stdout. + + Sample Usage:: $ MAX_CONCURRENCY=1 python setup.py build_ext --enable-[feature] install From 78a626d343fe03d5a7baeb947c3f336e60d2f831 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Thu, 7 Apr 2016 01:11:13 -0700 Subject: [PATCH 34/61] Pushing build to s3 as artifact --- appveyor.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 81f62dfdd..045346047 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -21,6 +21,7 @@ install: build_script: - '%PYTHON%\python.exe c:\pillow\winbuild\build.py' - cd c:\pillow +- dir dist\*.egg - '%PYTHON%\python.exe selftest.py --installed' test_script: - cd c:\pillow @@ -28,3 +29,17 @@ test_script: - '%PYTHON%\python.exe test-installed.py' matrix: fast_finish: true +artifacts: +- path: pillow\dist\*.egg + name: build +after_test: + - ps: Get-ChildItem .\dist\*.egg | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name } +deploy: + provider: S3 + access_key_id: AKIAIRAXC62ZNTVQJMOQ + secret_access_key: + secure: KpFJ5pGNJBIfy0yNX0rC/K661aaf789Ey+f7sZ7NN50SdK8Iz5WoZSke7PpGdAGe + bucket: pillow-nightly + folder: win/$(APPVEYOR_BUILD_NUMBER)/ + artifact: /.*egg/ + From 21af360812d49d2e2ab716cfe07ac8d86d9c4968 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Sat, 9 Apr 2016 08:21:11 -0700 Subject: [PATCH 35/61] secret value for python-pillow account, not wf --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 045346047..39ee1f5cf 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -38,7 +38,7 @@ deploy: provider: S3 access_key_id: AKIAIRAXC62ZNTVQJMOQ secret_access_key: - secure: KpFJ5pGNJBIfy0yNX0rC/K661aaf789Ey+f7sZ7NN50SdK8Iz5WoZSke7PpGdAGe + secure: Hwb6klTqtBeMgxAjRoDltiiqpuH8xbwD4UooDzBSiCWXjuFj1lyl4kHgHwTCCGqi bucket: pillow-nightly folder: win/$(APPVEYOR_BUILD_NUMBER)/ artifact: /.*egg/ From af57c0cfda24e7b1a28295176da37a7322d05f01 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Sat, 9 Apr 2016 20:28:43 +0100 Subject: [PATCH 36/61] refactor doccheck from travis -> makefile --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index 148a70070..0424742ac 100644 --- a/Makefile +++ b/Makefile @@ -26,6 +26,10 @@ coverage: doc: $(MAKE) -C docs html +doccheck: + $(MAKE) -C docs html + $(MAKE) -C docs linkcheck + docserve: cd docs/_build/html && python -mSimpleHTTPServer 2> /dev/null& From 66c7bc42e7c43e15d225c2caf7e8f3a9a48368fc Mon Sep 17 00:00:00 2001 From: wiredfool Date: Sat, 9 Apr 2016 20:29:26 +0100 Subject: [PATCH 37/61] only run docs on python 2.7, install all the requirements for it --- .travis.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index b76f5dbdb..8b6c9e55d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,6 @@ install: - "travis_retry pip install cffi" - "travis_retry pip install nose" - "travis_retry pip install check-manifest" - - "travis_retry pip install Sphinx" # Pyroma tests sometimes hang on PyPy and Python 2.6; skip for those - if [ $TRAVIS_PYTHON_VERSION != "pypy" && $TRAVIS_PYTHON_VERSION != "2.6" ]; then travis_retry pip install pyroma; fi @@ -33,6 +32,9 @@ install: # Coverage 4.0 doesn't support Python 3.2 - if [ "$TRAVIS_PYTHON_VERSION" == "3.2" ]; then travis_retry pip install coverage==3.7.1; fi - if [ "$TRAVIS_PYTHON_VERSION" != "3.2" ]; then travis_retry pip install coverage; fi + + # docs only on python 2.7 + - if [ "$TRAVIS_PYTHON_VERSION" == "2.7" ]; then travis_retry pip install -r requirements.txt ; fi # clean checkout for manifest - mkdir /tmp/check-manifest && cp -a . /tmp/check-manifest @@ -51,9 +53,9 @@ script: - if [ "$TRAVIS_PYTHON_VERSION" != "nightly" ]; then coverage run --append --include=PIL/* selftest.py; fi - if [ "$TRAVIS_PYTHON_VERSION" != "nightly" ]; then coverage run --append --include=PIL/* -m nose -vx Tests/test_*.py; fi - pushd /tmp/check-manifest && check-manifest --ignore ".coveragerc,.editorconfig,*.yml,*.yaml,tox.ini" && popd - # Sphinx - - make install - - pushd docs; make html; make linkcheck; popd + + # Docs + - if [ "$TRAVIS_PYTHON_VERSION" == "2.7" ]; then make install && make doccheck; fi after_success: # gather the coverage data From a2bc14c52611398b7e92c698f49b671eadcb19ed Mon Sep 17 00:00:00 2001 From: wiredfool Date: Sun, 10 Apr 2016 02:11:56 -0700 Subject: [PATCH 38/61] changed docs link to https --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index c618a56e7..844206a7b 100644 --- a/setup.py +++ b/setup.py @@ -734,7 +734,7 @@ class pil_build_ext(build_ext): if not all: print("To add a missing option, make sure you have the required") print("library and headers.") - print("See http://pillow.readthedocs.org/en/latest/installation.html#building-from-source") + print("See https://pillow.readthedocs.org/en/latest/installation.html#building-from-source") print("") print("To check the build, run the selftest.py script.") From d2a7de2c25056c8631b3bb478f8b5a067c4208b3 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Sun, 10 Apr 2016 10:15:59 +0100 Subject: [PATCH 39/61] Updated Changes.rst [ci skip] --- CHANGES.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 1385cd6ad..dd9344f19 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,12 @@ Changelog (Pillow) 3.3.0 (unreleased) ------------------ +- Added debug option for setup.py to trace header and library finding #1790 + [wiredfool] + +- Fix doc building on travis #1820 + [wiredfool] + - Fix for DIB/BMP images #1813 [wiredfool] From 18d596e3208418c75d7e9a064b2a753e7af25247 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sun, 10 Apr 2016 21:31:04 +1000 Subject: [PATCH 40/61] Added TIFF Tags --- PIL/TiffTags.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/PIL/TiffTags.py b/PIL/TiffTags.py index bee921dcd..23433a120 100644 --- a/PIL/TiffTags.py +++ b/PIL/TiffTags.py @@ -188,10 +188,28 @@ TAGS = {347: 'JPEGTables', 700: 'XMP', # Additional Exif Info + 32932: 'Wang Annotation', 33434: 'ExposureTime', 33437: 'FNumber', + 33445: 'MD FileTag', + 33446: 'MD ScalePixel', + 33447: 'MD ColorTable', + 33448: 'MD LabName', + 33449: 'MD SampleInfo', + 33450: 'MD PrepDate', + 33451: 'MD PrepTime', + 33452: 'MD FileUnits', + 33550: 'ModelPixelScaleTag', 33723: 'IptcNaaInfo', + 33918: 'INGR Packet Data Tag', + 33919: 'INGR Flag Registers', + 33920: 'IrasB Transformation Matrix', + 33922: 'ModelTiepointTag', + 34264: 'ModelTransformationTag', 34377: 'PhotoshopInfo', + 34735: 'GeoKeyDirectoryTag', + 34736: 'GeoDoubleParamsTag', + 34737: 'GeoAsciiParamsTag', 34850: 'ExposureProgram', 34852: 'SpectralSensitivity', 34855: 'ISOSpeedRatings', @@ -202,11 +220,15 @@ TAGS = {347: 'JPEGTables', 34867: 'ISOSpeed', 34868: 'ISOSpeedLatitudeyyy', 34869: 'ISOSpeedLatitudezzz', + 34908: 'HylaFAX FaxRecvParams', + 34909: 'HylaFAX FaxSubAddress', + 34910: 'HylaFAX FaxRecvTime', 36864: 'ExifVersion', 36867: 'DateTimeOriginal', 36868: 'DateTImeDigitized', 37121: 'ComponentsConfiguration', 37122: 'CompressedBitsPerPixel', + 37724: 'ImageSourceData', 37377: 'ShutterSpeedValue', 37378: 'ApertureValue', 37379: 'BrightnessValue', @@ -259,7 +281,13 @@ TAGS = {347: 'JPEGTables', 42035: 'LensMake', 42036: 'LensModel', 42037: 'LensSerialNumber', + 42112: 'GDAL_METADATA', + 42113: 'GDAL_NODATA', 42240: 'Gamma', + 50215: 'Oce Scanjob Description', + 50216: 'Oce Application Selector', + 50217: 'Oce Identification Number', + 50218: 'Oce ImageLogic Characteristics', # Adobe DNG 50706: 'DNGVersion', @@ -298,6 +326,7 @@ TAGS = {347: 'JPEGTables', 50740: 'DNGPrivateData', 50778: 'CalibrationIlluminant1', 50779: 'CalibrationIlluminant2', + 50784: 'Alias Layer Metadata' } From dbecf25945fda24f04d2c7c74b52cbb040945cc2 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 11 Apr 2016 00:16:02 +1000 Subject: [PATCH 41/61] Removed outdated classifier --- setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.py b/setup.py index 44c226092..64d6a9c09 100644 --- a/setup.py +++ b/setup.py @@ -741,7 +741,6 @@ setup(name=NAME, "Development Status :: 6 - Mature", "Topic :: Multimedia :: Graphics", "Topic :: Multimedia :: Graphics :: Capture :: Digital Camera", - "Topic :: Multimedia :: Graphics :: Capture :: Scanners", "Topic :: Multimedia :: Graphics :: Capture :: Screen Capture", "Topic :: Multimedia :: Graphics :: Graphics Conversion", "Topic :: Multimedia :: Graphics :: Viewers", From d6846403dd04981e0d04550a47155e5079343276 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 12 Apr 2016 17:51:55 +1000 Subject: [PATCH 42/61] Combined identical error messages in _imaging --- _imaging.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/_imaging.c b/_imaging.c index aaa11d8d9..12ed32168 100644 --- a/_imaging.c +++ b/_imaging.c @@ -280,6 +280,8 @@ int PyImaging_GetBuffer(PyObject* buffer, Py_buffer *view) /* error messages */ static const char* must_be_sequence = "argument must be a sequence"; +static const char* must_be_two_coordinates = + "coordinate list must contain exactly 2 coordinates"; static const char* wrong_mode = "unrecognized image mode"; static const char* wrong_raw_mode = "unrecognized raw mode"; static const char* outside_image = "image index out of range"; @@ -2398,9 +2400,7 @@ _draw_arc(ImagingDrawObject* self, PyObject* args) if (n < 0) return NULL; if (n != 2) { - PyErr_SetString(PyExc_TypeError, - "coordinate list must contain exactly 2 coordinates" - ); + PyErr_SetString(PyExc_TypeError, must_be_two_coordinates); return NULL; } @@ -2472,9 +2472,7 @@ _draw_chord(ImagingDrawObject* self, PyObject* args) if (n < 0) return NULL; if (n != 2) { - PyErr_SetString(PyExc_TypeError, - "coordinate list must contain exactly 2 coordinates" - ); + PyErr_SetString(PyExc_TypeError, must_be_two_coordinates); return NULL; } @@ -2509,9 +2507,7 @@ _draw_ellipse(ImagingDrawObject* self, PyObject* args) if (n < 0) return NULL; if (n != 2) { - PyErr_SetString(PyExc_TypeError, - "coordinate list must contain exactly 2 coordinates" - ); + PyErr_SetString(PyExc_TypeError, must_be_two_coordinates); return NULL; } @@ -2692,9 +2688,7 @@ _draw_pieslice(ImagingDrawObject* self, PyObject* args) if (n < 0) return NULL; if (n != 2) { - PyErr_SetString(PyExc_TypeError, - "coordinate list must contain exactly 2 coordinates" - ); + PyErr_SetString(PyExc_TypeError, must_be_two_coordinates); return NULL; } @@ -2774,9 +2768,7 @@ _draw_rectangle(ImagingDrawObject* self, PyObject* args) if (n < 0) return NULL; if (n != 2) { - PyErr_SetString(PyExc_TypeError, - "coordinate list must contain exactly 2 coordinates" - ); + PyErr_SetString(PyExc_TypeError, must_be_two_coordinates); return NULL; } From c43106374a2112f85b047a399840cbfbeac074c1 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 12 Apr 2016 20:55:12 +0100 Subject: [PATCH 43/61] Update CHANGES.rst [ci skip] --- CHANGES.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index dd9344f19..5c8dfeb18 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,12 @@ Changelog (Pillow) 3.3.0 (unreleased) ------------------ +- Removed outdated scanner classifier #1823 + [radarhere] + +- Combined identical error messages in _imaging #1825 + [radarhere] + - Added debug option for setup.py to trace header and library finding #1790 [wiredfool] From 435858afaa3088d54dc280f4a512786f0e404177 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Wed, 13 Apr 2016 17:33:33 +1000 Subject: [PATCH 44/61] Fixed typo --- PIL/GbrImagePlugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PIL/GbrImagePlugin.py b/PIL/GbrImagePlugin.py index 5fef39960..d62981c28 100644 --- a/PIL/GbrImagePlugin.py +++ b/PIL/GbrImagePlugin.py @@ -55,7 +55,7 @@ class GbrImageFile(ImageFile.ImageFile): if width <= 0 or height <= 0: raise SyntaxError("not a GIMP brush") if color_depth not in (1, 4): - raise SyntaxError("Unsupported GMP brush color depth: %s" % color_depth) + raise SyntaxError("Unsupported GIMP brush color depth: %s" % color_depth) if version == 1: comment_length = header_size-20 From 47379441974436fef90c7af2ba81b6311d40b682 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Thu, 14 Apr 2016 00:08:44 +1000 Subject: [PATCH 45/61] Minor grammar fix --- Tests/test_bmp_reference.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/test_bmp_reference.py b/Tests/test_bmp_reference.py index 79ad439ba..885bd4996 100644 --- a/Tests/test_bmp_reference.py +++ b/Tests/test_bmp_reference.py @@ -24,7 +24,7 @@ class TestBmpReference(PillowTestCase): # print ("Bad Image %s: %s" %(f,msg)) def test_questionable(self): - """ These shouldn't crash/dos, but its not well defined that these + """ These shouldn't crash/dos, but it's not well defined that these are in spec """ for f in self.get_files('q'): try: From 89901e089c1737c7dda547b9eac3d02a2c345d02 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 16 Apr 2016 01:09:46 +1000 Subject: [PATCH 46/61] Updated redirected URL --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index b5bfb80b3..21119293b 100644 --- a/setup.py +++ b/setup.py @@ -755,7 +755,7 @@ class pil_build_ext(build_ext): if m.group(1) < "1.2.3": return m.group(1) - # http://hg.python.org/users/barry/rev/7e8deab93d5a + # https://hg.python.org/users/barry/rev/7e8deab93d5a def add_multiarch_paths(self): # Debian/Ubuntu multiarch support. # https://wiki.ubuntu.com/MultiarchSpec From ea3dcfda0ca48998de9bebc801d843172a9a9e33 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 16 Apr 2016 11:43:28 +1000 Subject: [PATCH 47/61] Changed documentation to refer to ImageSequence Iterator class [ci skip] --- docs/handbook/tutorial.rst | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/docs/handbook/tutorial.rst b/docs/handbook/tutorial.rst index 914f7cde8..2777feaee 100644 --- a/docs/handbook/tutorial.rst +++ b/docs/handbook/tutorial.rst @@ -400,26 +400,15 @@ Note that most drivers in the current version of the library only allow you to seek to the next frame (as in the above example). To rewind the file, you may have to reopen it. -The following iterator class lets you use the for-statement to loop over the -sequence: +The following class lets you use the for-statement to loop over the sequence: -A sequence iterator class -^^^^^^^^^^^^^^^^^^^^^^^^^ +Using the ImageSequence Iterator class +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: - class ImageSequence: - def __init__(self, im): - self.im = im - def __getitem__(self, ix): - try: - if ix: - self.im.seek(ix) - return self.im - except EOFError: - raise IndexError # end of sequence - - for frame in ImageSequence(im): + from PIL import ImageSequence + for frame in ImageSequence.Iterator(im): # ...do something to frame... From ecd4d5a186dacc1670d0a32fbc4320377e16bdec Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sun, 17 Apr 2016 23:27:09 +1000 Subject: [PATCH 48/61] Removed unused test helper --- Tests/test_file_iptc.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/Tests/test_file_iptc.py b/Tests/test_file_iptc.py index 84fa873be..374b9989d 100644 --- a/Tests/test_file_iptc.py +++ b/Tests/test_file_iptc.py @@ -7,18 +7,6 @@ TEST_FILE = "Tests/images/iptc.jpg" class TestFileIptc(PillowTestCase): - # Helpers - - def dummy_IptcImagePlugin(self): - # Create an IptcImagePlugin object without initializing it - class FakeImage(object): - pass - im = FakeImage() - im.__class__ = IptcImagePlugin.IptcImageFile - return im - - # Tests - def test_getiptcinfo_jpg_none(self): # Arrange im = hopper() From 7938202a1b6e5f2bcd838c35cd00f93d9d365ac8 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 19 Apr 2016 18:09:04 +1000 Subject: [PATCH 49/61] Fixed length of title underline [ci skip] --- docs/releasenotes/3.1.1.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/releasenotes/3.1.1.rst b/docs/releasenotes/3.1.1.rst index 969bbb7ca..8c32a43e7 100644 --- a/docs/releasenotes/3.1.1.rst +++ b/docs/releasenotes/3.1.1.rst @@ -48,7 +48,7 @@ off the end of the memory buffer, causing a segfault. This issue was found by Alyssa Besseling at Atlassian CVE-2016-2533 -- Buffer overflow in PcdDecode.c ----------------------------------------------- +----------------------------------------------- In all versions of Pillow, dating back at least to the last PIL 1.1.7 release, ``PcdDecode.c`` has a buffer overflow error. @@ -64,7 +64,7 @@ Integer overflow in Resample.c If a large value was passed into the new size for an image, it is possible to overflow an int32 value passed into malloc. - + kk = malloc(xsize * kmax * sizeof(float)); ... xbounds = malloc(xsize * 2 * sizeof(int)); From 521c7e9bdfeef0431f0f8c5f2f26ca4227d7937a Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 19 Apr 2016 19:49:58 +1000 Subject: [PATCH 50/61] Added EXIF tags --- PIL/ExifTags.py | 124 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 123 insertions(+), 1 deletion(-) diff --git a/PIL/ExifTags.py b/PIL/ExifTags.py index 72e629dc5..172de2c8e 100644 --- a/PIL/ExifTags.py +++ b/PIL/ExifTags.py @@ -20,6 +20,7 @@ TAGS = { # possibly incomplete + 0x000b: "ProcessingSoftware", 0x00fe: "NewSubfileType", 0x00ff: "SubfileType", 0x0100: "ImageWidth", @@ -50,31 +51,69 @@ TAGS = { 0x0121: "FreeByteCounts", 0x0122: "GrayResponseUnit", 0x0123: "GrayResponseCurve", + 0x0124: "T4Options", + 0x0125: "T6Options", 0x0128: "ResolutionUnit", + 0x0129: "PageNumber", 0x012d: "TransferFunction", 0x0131: "Software", 0x0132: "DateTime", 0x013b: "Artist", 0x013c: "HostComputer", + 0x013d: "Predictor", 0x013e: "WhitePoint", 0x013f: "PrimaryChromaticities", 0x0140: "ColorMap", + 0x0141: "HalftoneHints", + 0x0142: "TileWidth", + 0x0143: "TileLength", + 0x0144: "TileOffsets", + 0x0145: "TileByteCounts", + 0x014a: "SubIFDs", + 0x014c: "InkSet", + 0x014d: "InkNames", + 0x014e: "NumberOfInks", + 0x0150: "DotRange", + 0x0151: "TargetPrinter", 0x0152: "ExtraSamples", + 0x0153: "SampleFormat", + 0x0154: "SMinSampleValue", + 0x0155: "SMaxSampleValue", + 0x0156: "TransferRange", + 0x0157: "ClipPath", + 0x0158: "XClipPathUnits", + 0x0159: "YClipPathUnits", + 0x015a: "Indexed", + 0x015b: "JPEGTables", + 0x015f: "OPIProxy", + 0x0200: "JPEGProc", 0x0201: "JpegIFOffset", 0x0202: "JpegIFByteCount", + 0x0203: "JpegRestartInterval", + 0x0205: "JpegLosslessPredictors", + 0x0206: "JpegPointTransforms", + 0x0207: "JpegQTables", + 0x0208: "JpegDCTables", + 0x0209: "JpegACTables", 0x0211: "YCbCrCoefficients", 0x0212: "YCbCrSubSampling", 0x0213: "YCbCrPositioning", 0x0214: "ReferenceBlackWhite", + 0x02bc: "XMLPacket", 0x1000: "RelatedImageFileFormat", 0x1001: "RelatedImageWidth", 0x1002: "RelatedImageLength", + 0x4746: "Rating", + 0x4749: "RatingPercent", + 0x800d: "ImageID", 0x828d: "CFARepeatPatternDim", 0x828e: "CFAPattern", 0x828f: "BatteryLevel", 0x8298: "Copyright", 0x829a: "ExposureTime", 0x829d: "FNumber", + 0x83bb: "IPTCNAA", + 0x8649: "ImageResources", 0x8769: "ExifOffset", 0x8773: "InterColorProfile", 0x8822: "ExposureProgram", @@ -114,6 +153,11 @@ TAGS = { 0x9290: "SubsecTime", 0x9291: "SubsecTimeOriginal", 0x9292: "SubsecTimeDigitized", + 0x9c9b: "XPTitle", + 0x9c9c: "XPComment", + 0x9c9d: "XPAuthor", + 0x9c9e: "XPKeywords", + 0x9c9f: "XPSubject", 0xa000: "FlashPixVersion", 0xa001: "ColorSpace", 0xa002: "ExifImageWidth", @@ -151,7 +195,85 @@ TAGS = { 0xa434: "LensModel", 0xa435: "LensSerialNumber", 0xa500: "Gamma", - + 0xc4a5: "PrintImageMatching", + 0xc612: "DNGVersion", + 0xc613: "DNGBackwardVersion", + 0xc614: "UniqueCameraModel", + 0xc615: "LocalizedCameraModel", + 0xc616: "CFAPlaneColor", + 0xc617: "CFALayout", + 0xc618: "LinearizationTable", + 0xc619: "BlackLevelRepeatDim", + 0xc61a: "BlackLevel", + 0xc61b: "BlackLevelDeltaH", + 0xc61c: "BlackLevelDeltaV", + 0xc61d: "WhiteLevel", + 0xc61e: "DefaultScale", + 0xc61f: "DefaultCropOrigin", + 0xc620: "DefaultCropSize", + 0xc621: "ColorMatrix1", + 0xc622: "ColorMatrix2", + 0xc623: "CameraCalibration1", + 0xc624: "CameraCalibration2", + 0xc625: "ReductionMatrix1", + 0xc626: "ReductionMatrix2", + 0xc627: "AnalogBalance", + 0xc628: "AsShotNeutral", + 0xc629: "AsShotWhiteXY", + 0xc62a: "BaselineExposure", + 0xc62b: "BaselineNoise", + 0xc62c: "BaselineSharpness", + 0xc62d: "BayerGreenSplit", + 0xc62e: "LinearResponseLimit", + 0xc62f: "CameraSerialNumber", + 0xc630: "LensInfo", + 0xc631: "ChromaBlurRadius", + 0xc632: "AntiAliasStrength", + 0xc633: "ShadowScale", + 0xc634: "DNGPrivateData", + 0xc635: "MakerNoteSafety", + 0xc65a: "CalibrationIlluminant1", + 0xc65b: "CalibrationIlluminant2", + 0xc65c: "BestQualityScale", + 0xc65d: "RawDataUniqueID", + 0xc68b: "OriginalRawFileName", + 0xc68c: "OriginalRawFileData", + 0xc68d: "ActiveArea", + 0xc68e: "MaskedAreas", + 0xc68f: "AsShotICCProfile", + 0xc690: "AsShotPreProfileMatrix", + 0xc691: "CurrentICCProfile", + 0xc692: "CurrentPreProfileMatrix", + 0xc6bf: "ColorimetricReference", + 0xc6f3: "CameraCalibrationSignature", + 0xc6f4: "ProfileCalibrationSignature", + 0xc6f6: "AsShotProfileName", + 0xc6f7: "NoiseReductionApplied", + 0xc6f8: "ProfileName", + 0xc6f9: "ProfileHueSatMapDims", + 0xc6fa: "ProfileHueSatMapData1", + 0xc6fb: "ProfileHueSatMapData2", + 0xc6fc: "ProfileToneCurve", + 0xc6fd: "ProfileEmbedPolicy", + 0xc6fe: "ProfileCopyright", + 0xc714: "ForwardMatrix1", + 0xc715: "ForwardMatrix2", + 0xc716: "PreviewApplicationName", + 0xc717: "PreviewApplicationVersion", + 0xc718: "PreviewSettingsName", + 0xc719: "PreviewSettingsDigest", + 0xc71a: "PreviewColorSpace", + 0xc71b: "PreviewDateTime", + 0xc71c: "RawImageDigest", + 0xc71d: "OriginalRawFileDigest", + 0xc71e: "SubTileBlockSize", + 0xc71f: "RowInterleaveFactor", + 0xc725: "ProfileLookTableDims", + 0xc726: "ProfileLookTableData", + 0xc740: "OpcodeList1", + 0xc741: "OpcodeList2", + 0xc74e: "OpcodeList3", + 0xc761: "NoiseProfile" } ## From 34c02e321d5df3e616729a1b31c47f1c0fff6019 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 19 Apr 2016 19:50:28 +1000 Subject: [PATCH 51/61] Moved EXIF tag to be in hex order --- PIL/ExifTags.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PIL/ExifTags.py b/PIL/ExifTags.py index 172de2c8e..a8ad26bcc 100644 --- a/PIL/ExifTags.py +++ b/PIL/ExifTags.py @@ -33,7 +33,6 @@ TAGS = { 0x0109: "CellLength", 0x010a: "FillOrder", 0x010d: "DocumentName", - 0x011d: "PageName", 0x010e: "ImageDescription", 0x010f: "Make", 0x0110: "Model", @@ -47,6 +46,7 @@ TAGS = { 0x011a: "XResolution", 0x011b: "YResolution", 0x011c: "PlanarConfiguration", + 0x011d: "PageName", 0x0120: "FreeOffsets", 0x0121: "FreeByteCounts", 0x0122: "GrayResponseUnit", From 5877a4313ba68c7e4411da2618faf41cd4580909 Mon Sep 17 00:00:00 2001 From: Daniel Harding Date: Tue, 19 Apr 2016 11:34:44 +0100 Subject: [PATCH 52/61] Fix Fedora prerequisites [ci skip] zlib-devel is needed, but not libzip-devel. --- docs/installation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.rst b/docs/installation.rst index c065ef2bc..4b4d6d07e 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -293,7 +293,7 @@ Prerequisites are installed on **Ubuntu 14.04 LTS** with:: Prerequisites are installed on **Fedora 23** with:: - $ sudo dnf install libtiff-devel libjpeg-devel libzip-devel freetype-devel \ + $ sudo dnf install libtiff-devel libjpeg-devel zlib-devel freetype-devel \ lcms2-devel libwebp-devel tcl-devel tk-devel From 53197808f5e5b8a78570ea2221f91684e0553259 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 19 Apr 2016 20:59:32 +1000 Subject: [PATCH 53/61] Added _accept hook for PixarImagePlugin --- PIL/PixarImagePlugin.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/PIL/PixarImagePlugin.py b/PIL/PixarImagePlugin.py index 783462a9a..fd002d9cf 100644 --- a/PIL/PixarImagePlugin.py +++ b/PIL/PixarImagePlugin.py @@ -29,6 +29,10 @@ __version__ = "0.1" i16 = _binary.i16le +def _accept(prefix): + return prefix[:4] == b"\200\350\000\000" + + ## # Image plugin for PIXAR raster images. @@ -39,7 +43,7 @@ class PixarImageFile(ImageFile.ImageFile): def _open(self): - # assuming a 4-byte magic label (FIXME: add "_accept" hook) + # assuming a 4-byte magic label s = self.fp.read(4) if s != b"\200\350\000\000": raise SyntaxError("not a PIXAR file") @@ -62,6 +66,6 @@ class PixarImageFile(ImageFile.ImageFile): # # -------------------------------------------------------------------- -Image.register_open(PixarImageFile.format, PixarImageFile) +Image.register_open(PixarImageFile.format, PixarImageFile, _accept) Image.register_extension(PixarImageFile.format, ".pxr") From c5a801b836b521b384d0b061470b817c64bc07c4 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 19 Apr 2016 07:29:33 -0700 Subject: [PATCH 54/61] Allow linkcheck to fail --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0424742ac..e4ead2923 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,9 @@ doc: doccheck: $(MAKE) -C docs html - $(MAKE) -C docs linkcheck +# Don't make our test rely on the links in the docs being up every single build. +# We don't control them. But do check, and update them to the target of their redirectes. + $(MAKE) -C docs linkcheck || true docserve: cd docs/_build/html && python -mSimpleHTTPServer 2> /dev/null& From 1762bff3afa4b93ce2097d29d8cdcde625d654d2 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 19 Apr 2016 07:29:59 -0700 Subject: [PATCH 55/61] Fix warnings in docs, we're not using terms or keywords --- docs/handbook/concepts.rst | 2 +- docs/reference/ImageMath.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/handbook/concepts.rst b/docs/handbook/concepts.rst index b5ad9331a..9ad83f1d9 100644 --- a/docs/handbook/concepts.rst +++ b/docs/handbook/concepts.rst @@ -24,7 +24,7 @@ To get the number and names of bands in an image, use the Modes ----- -The :term:`mode` of an image defines the type and depth of a pixel in the +The ``mode`` of an image defines the type and depth of a pixel in the image. The current release supports the following standard modes: * ``1`` (1-bit pixels, black and white, stored with one pixel per byte) diff --git a/docs/reference/ImageMath.rst b/docs/reference/ImageMath.rst index 5d7345d79..445a7e277 100644 --- a/docs/reference/ImageMath.rst +++ b/docs/reference/ImageMath.rst @@ -81,13 +81,13 @@ Bitwise operators don’t work on floating point images. Logical Operators ^^^^^^^^^^^^^^^^^ -Logical operators like :keyword:`and`, :keyword:`or`, and :keyword:`not` work +Logical operators like ``and``, ``or``, and ``not`` work on entire images, rather than individual pixels. An empty image (all pixels zero) is treated as false. All other images are treated as true. -Note that :keyword:`and` and :keyword:`or` return the last evaluated operand, +Note that ``and`` and ``or`` return the last evaluated operand, while not always returns a boolean value. Built-in Functions From bbd4337fbba787374318a9d835f9a0808a6e21bd Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 19 Apr 2016 07:41:14 -0700 Subject: [PATCH 56/61] Updated OleFileIO doc links --- PIL/OleFileIO.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/PIL/OleFileIO.py b/PIL/OleFileIO.py index 4cf106d97..1998e3c10 100755 --- a/PIL/OleFileIO.py +++ b/PIL/OleFileIO.py @@ -540,16 +540,16 @@ class OleMetadata(object): OLE file. References for SummaryInformation stream: - - http://msdn.microsoft.com/en-us/library/dd942545.aspx - - http://msdn.microsoft.com/en-us/library/dd925819%28v=office.12%29.aspx - - http://msdn.microsoft.com/en-us/library/windows/desktop/aa380376%28v=vs.85%29.aspx - - http://msdn.microsoft.com/en-us/library/aa372045.aspx - - http://sedna-soft.de/summary-information-stream/ + - https://msdn.microsoft.com/en-us/library/dd942545.aspx + - https://msdn.microsoft.com/en-us/library/dd925819%28v=office.12%29.aspx + - https://msdn.microsoft.com/en-us/library/windows/desktop/aa380376%28v=vs.85%29.aspx + - https://msdn.microsoft.com/en-us/library/aa372045.aspx + - http://sedna-soft.de/articles/summary-information-stream/ - http://poi.apache.org/apidocs/org/apache/poi/hpsf/SummaryInformation.html References for DocumentSummaryInformation stream: - - http://msdn.microsoft.com/en-us/library/dd945671%28v=office.12%29.aspx - - http://msdn.microsoft.com/en-us/library/windows/desktop/aa380374%28v=vs.85%29.aspx + - https://msdn.microsoft.com/en-us/library/dd945671%28v=office.12%29.aspx + - https://msdn.microsoft.com/en-us/library/windows/desktop/aa380374%28v=vs.85%29.aspx - http://poi.apache.org/apidocs/org/apache/poi/hpsf/DocumentSummaryInformation.html new in version 0.25 From b178f5ff9bd442a65e98675e698d375f57173452 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 19 Apr 2016 07:56:23 -0700 Subject: [PATCH 57/61] libzip != zlib, in depends script as well --- depends/fedora_23.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/depends/fedora_23.sh b/depends/fedora_23.sh index 2825eba56..72032cd2e 100755 --- a/depends/fedora_23.sh +++ b/depends/fedora_23.sh @@ -13,6 +13,6 @@ sudo dnf install redhat-rpm-config sudo dnf install python-devel python3-devel python-virtualenv make gcc -sudo dnf install libtiff-devel libjpeg-devel libzip-devel freetype-devel \ +sudo dnf install libtiff-devel libjpeg-devel zlib-devel freetype-devel \ lcms2-devel libwebp-devel openjpeg2-devel tkinter python3-tkinter \ tcl-devel tk-devel \ No newline at end of file From c1be4486c1e0f3a940ceeb6cc8b60024ae38a5ce Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 19 Apr 2016 16:24:34 +0100 Subject: [PATCH 58/61] Updated Changes.rst [ci skip] --- CHANGES.rst | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 5c8dfeb18..ed4ea8bcb 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,18 @@ Changelog (Pillow) 3.3.0 (unreleased) ------------------ +- Added additional EXIF tags #1841 + [radarhere] + +- Changed documentation to refer to ImageSequence Iterator #1833 + [radarhere] + +- Fix Fedora prerequisites in installation docs, depends script #1842 + [living180] + +- Added _accept hook for PixarImagePlugin #1843 + [radarhere] + - Removed outdated scanner classifier #1823 [radarhere] From e2fb83f0897cea7b4ff731aaa8314d36d639d9a1 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 19 Apr 2016 16:32:51 +0100 Subject: [PATCH 59/61] Updated Changes.rst [ci skip] --- CHANGES.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index ed4ea8bcb..e7019b8fd 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,7 +4,7 @@ Changelog (Pillow) 3.3.0 (unreleased) ------------------ -- Added additional EXIF tags #1841 +- Added additional EXIF tags #1841, TIFF Tags #1821 [radarhere] - Changed documentation to refer to ImageSequence Iterator #1833 From 0fbadde5807aa9716f377149d8fb947c9d083bff Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 19 Apr 2016 16:34:20 +0100 Subject: [PATCH 60/61] Updated Changes.rst [ci skip] --- CHANGES.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index e7019b8fd..4c9c48450 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -25,7 +25,7 @@ Changelog (Pillow) - Added debug option for setup.py to trace header and library finding #1790 [wiredfool] -- Fix doc building on travis #1820 +- Fix doc building on travis #1820, #1844 [wiredfool] - Fix for DIB/BMP images #1813 From 90955e49531dc917095ea2b858963033a7a37ede Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 19 Apr 2016 16:49:55 +0100 Subject: [PATCH 61/61] Updated Changes.rst [ci skip] --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 4c9c48450..04ee11b4b 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,9 @@ Changelog (Pillow) 3.3.0 (unreleased) ------------------ +- Jpeg qtables are unsigned chars #1814 + [thebostik] + - Added additional EXIF tags #1841, TIFF Tags #1821 [radarhere]