From 175c57243272a2f3263a44d83804b987f5db94a1 Mon Sep 17 00:00:00 2001 From: Eric Soroos Date: Sat, 19 Oct 2013 03:28:31 +0000 Subject: [PATCH 01/12] I;16 images are little endian, not native endian --- PIL/Image.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/PIL/Image.py b/PIL/Image.py index 6f53d5148..e1d88fe59 100644 --- a/PIL/Image.py +++ b/PIL/Image.py @@ -226,16 +226,17 @@ _MODE_CONV = { "CMYK": ('|u1', 4), "YCbCr": ('|u1', 3), "LAB": ('|u1', 3), # UNDONE - unsigned |u1i1i1 - "I;16": ('=u2', None), + # I;16 == I;16L, and I;32 == I;32L + "I;16": ('u2', None), "I;16L": ('i2', None), "I;16LS": ('u4', None), "I;32L": ('i4', None), "I;32LS": (' Date: Sat, 19 Oct 2013 03:30:02 +0000 Subject: [PATCH 02/12] uint16 varies from platform to platform, u2'), - ("I;16L", 'uint16'), + ("I;16L", ' Date: Mon, 21 Oct 2013 05:19:52 +0000 Subject: [PATCH 03/12] Tests for endian issues in decoding 16bit tif images --- Tests/images/12bit.MM.cropped.tif | Bin 0 -> 8448 bytes Tests/images/12bit.MM.deflate.tif | Bin 0 -> 5230 bytes Tests/images/12bit.deflate.tif | Bin 0 -> 5112 bytes Tests/test_file_libtiff.py | 22 ++++++++++++++++++++++ Tests/test_file_tiff.py | 25 +++++++++++++++++++++++++ 5 files changed, 47 insertions(+) create mode 100644 Tests/images/12bit.MM.cropped.tif create mode 100644 Tests/images/12bit.MM.deflate.tif create mode 100644 Tests/images/12bit.deflate.tif diff --git a/Tests/images/12bit.MM.cropped.tif b/Tests/images/12bit.MM.cropped.tif new file mode 100644 index 0000000000000000000000000000000000000000..c4c24e2eb97b134e15079c31cd02a30cc145c8df GIT binary patch literal 8448 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%0DTfbAD2!(pR(-y~XQ_PpKao33!_w?!6A% zgXz=4IHd!vniw|Jbn149dAB2Im^s0TKBBXpgXg^=oW#@8S68aAyKM<6RGs2K8*;tm z5$#YM2(IyQ*+Qt`$9hbG%rZqqx0ZZ2ZmvCMi+J@=-2ZmceYiQcic`O+KkxC})@QP! zmpC@qrtY!OS-3EER=}Ns^@D#Up$52);XSm}i^38p_J%I3j^-zD2~BOpE0W*U zfyYT9)-w^U4+KJl-aa>+i@JD1(7n^sLFX?R0swfG1=kSFH{}sP`I0|QhuIRf#5*CN z1V@C#ixjSDSwWqwnvNZk~nsr;WS0%nxeETlT0%%`ly4 zBLp1gZ&RX}JBps{)sGNPl*f(IRt~m`Rw9+hPFU4)fNcn9x4YX`F33vEH6?x{b{Hx= z93;rLzW+#&Y-?#Qm4JV_=Lv{^HI#3FEST|dGdnb5ZxzADdjgN^4npo0na|74V)LQj z%iElD%8mT>s5HaRg!vw7YxORG{K=m&oV!^^<muKdw(EL!9K9~gmO_^ zB%hFkC>&*F&HYcBmaaj3ekGs)%6&ntLng0DF21@7B|Xu z3_AMlk|XU}3=Q;n$J^;y9`Jbi*_q~2JSGM;mg2Ou8`k-D9lrDKM#qlD+hwsd53xOp z8tdMhO=UlZ#9&&rG?G1;kSCv!fRL2mjh>khH_sOTx*?m;4Ky_(?%@>xpSze`b1;Y@vu3SW@lSB(q!m^MDL-qduZooop!MGj z0uS^5P+L3xm5IMwz422TE>hC&8)?S9_CnQxsX=-kUF|DVUFmI7sDL;d1A-sT)_*+b z>LI*HT9I*E#Mlj|`=IaZ>B4yRpXZcIa-JI$NJr2V9@6g-4v?=&!amasqKL=x4jI`c zO-s7;9aOCm5Y+TZszVu%U|l<}aI~4;##FAWb`?Z_3SVKmZ-uR`TqGzwVubd~+(s<$ zTdJ4)l@-MuH=eo$C{0h#H;+XWI%sy2NswLiU6SJSH@-YoO z6hCxDCe@}!`TOEC+bcUv^))KT=5AVW8zigw`_ujtG0dc8FbAd!i-t-fZ7xweOII#P zbqg{81dIKZjVN-0ROkRvRVr=r6DyXh17I2GXKh#Q;6C|HW|8+uh;CTazO?qTYW||- z@kOTQF6^qg;`6MvVE>&{jbcr``jU%rie__Cc26H*JB-OD%%meY9x$Iafg@W|`#Q$7 zJquyV-~3~uq*Gy-+NB|$W?r#-hj}(q^F(||x_-+i8)oTmYN&Xz|Jwsrtom4M z@$!_=_VnutO84k260_paa-NXnotU@IId;+Z>}lkR|3507S(AT~_mh5KXx8s~OCkEX z-q_p?C)a#I%$Q8G?G(7i88BZSJH*JkD_5r)vb|fDL|yb3?rW{_{?@|%DcCyJx-|N9 z5MM+l#9MwAiY#FTv1%h{5}& zw0xBdu(m8L^9<8u9Sd%3+tMn6jSm;Sa~Z`QsD#4yF1Y2xes&l;p88$ZUY1*P>(*2T zv-8^+km8V`sprr>x|k9xno_pw=3TRu2v*GZs`ag@)l-=R3y2jRiaUQV^4BHBS;Mg< zBLxK|H3cOF1%=+~T}toPS*|C@RJ O_rG`JKbgNPivI(%CH_wU literal 0 HcmV?d00001 diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index 037fc022d..d4767c95a 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -105,3 +105,25 @@ def test_adobe_deflate_tiff(): assert_no_exception(lambda: im.load()) +def test_little_endian(): + im = Image.open('Tests/images/12bit.deflate.tif') + assert_equal(im.getpixel((0,0)), 480) + assert_equal(im.mode, 'I;16') + + b = im.tobytes() + # Bytes are in image native order (little endian) + assert_equal(b[0], b'\xe0') + assert_equal(b[1], b'\x01') + +def test_big_endian(): + im = Image.open('Tests/images/12bit.MM.deflate.tif') + + assert_equal(im.getpixel((0,0)), 480) + assert_equal(im.mode, 'I;16B') + + b = im.tobytes() + + # Bytes are in image native order (big endian) + assert_equal(b[0], b'\x01') + assert_equal(b[1], b'\xe0') + diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index ddca24876..c88e103b4 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -71,3 +71,28 @@ def test_xyres_tiff(): im.tag.tags[Y_RESOLUTION] = (72,) im._setup() assert_equal(im.info['dpi'], (72., 72.)) + + +def test_little_endian(): + im = Image.open('Tests/images/12bit.cropped.tif') + assert_equal(im.getpixel((0,0)), 480) + assert_equal(im.mode, 'I;16') + + b = im.tobytes() + # Bytes are in image native order (little endian) + assert_equal(b[0], b'\xe0') + assert_equal(b[1], b'\x01') + +def test_big_endian(): + im = Image.open('Tests/images/12bit.MM.cropped.tif') + assert_equal(im.getpixel((0,0)), 480) + assert_equal(im.mode, 'I;16B') + + b = im.tobytes() + + # Bytes are in image native order (big endian) + assert_equal(b[0], b'\x01') + assert_equal(b[1], b'\xe0') + + + From 6f8d968cbbe1d00ffebf28768aad01178c00bc0c Mon Sep 17 00:00:00 2001 From: Eric Soroos Date: Mon, 21 Oct 2013 22:17:33 +0000 Subject: [PATCH 04/12] MM and II 16 bit integer tiffs unpack properly using libtiff on bigendian platform --- PIL/TiffImagePlugin.py | 6 ++++++ libImaging/Storage.c | 3 ++- libImaging/Unpack.c | 24 ++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/PIL/TiffImagePlugin.py b/PIL/TiffImagePlugin.py index 25ad3578e..f4a68d1fd 100644 --- a/PIL/TiffImagePlugin.py +++ b/PIL/TiffImagePlugin.py @@ -804,6 +804,12 @@ class TiffImageFile(ImageFile.ImageFile): # fillorder==2 modes have a corresponding # fillorder=1 mode self.mode, rawmode = OPEN_INFO[key] + # libtiff always returns the bytes in native order. + # we're expecting image byte order. So, if the rawmode + # contains I;16, we need to convert from native to image + # byte order. + if self.mode in ('I;16B', 'I;16'): + rawmode = 'I;16N' # Offset in the tile tuple is 0, we go from 0,0 to # w,h, and we only do this once -- eds diff --git a/libImaging/Storage.c b/libImaging/Storage.c index 50259be47..314f462c8 100644 --- a/libImaging/Storage.c +++ b/libImaging/Storage.c @@ -105,7 +105,8 @@ ImagingNewPrologueSubtype(const char *mode, unsigned xsize, unsigned ysize, im->linesize = xsize * 4; im->type = IMAGING_TYPE_INT32; - } else if (strcmp(mode, "I;16") == 0 || strcmp(mode, "I;16L") == 0 || strcmp(mode, "I;16B") == 0) { + } else if (strcmp(mode, "I;16") == 0 || strcmp(mode, "I;16L") == 0 \ + || strcmp(mode, "I;16B") == 0 || strcmp(mode, "I;16N") == 0) { /* EXPERIMENTAL */ /* 16-bit raw integer images */ im->bands = 1; diff --git a/libImaging/Unpack.c b/libImaging/Unpack.c index 2fba92e98..f6d6718d1 100644 --- a/libImaging/Unpack.c +++ b/libImaging/Unpack.c @@ -775,6 +775,26 @@ ImagingUnpackLAB(UINT8* out, const UINT8* in, int pixels) } } +static void +unpackI16N_I16B(UINT8* out, const UINT8* in, int pixels){ + int i; + UINT8* tmp = (UINT8*) out; + for (i = 0; i < pixels; i++) { + C16B; + in += 2; tmp += 2; + } + +} +static void +unpackI16N_I16(UINT8* out, const UINT8* in, int pixels){ + int i; + UINT8* tmp = (UINT8*) out; + for (i = 0; i < pixels; i++) { + C16L; + in += 2; tmp += 2; + } +} + static void copy1(UINT8* out, const UINT8* in, int pixels) { @@ -1139,6 +1159,10 @@ static struct { {"I;16B", "I;16B", 16, copy2}, {"I;16L", "I;16L", 16, copy2}, + {"I;16", "I;16N", 16, unpackI16N_I16}, // LibTiff native->image endian. + {"I;16L", "I;16N", 16, unpackI16N_I16}, // LibTiff native->image endian. + {"I;16B", "I;16N", 16, unpackI16N_I16B}, + {NULL} /* sentinel */ }; From 3128a7649547a59cfe5f4a54361958acf1992fb2 Mon Sep 17 00:00:00 2001 From: Eric Soroos Date: Mon, 21 Oct 2013 22:37:20 +0000 Subject: [PATCH 05/12] MM and II 16 bit integer tiffs pack/write properly using libtiff on bigendian platform --- PIL/TiffImagePlugin.py | 8 ++++++++ Tests/test_file_libtiff.py | 17 +++++++++++++++++ libImaging/Pack.c | 24 ++++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/PIL/TiffImagePlugin.py b/PIL/TiffImagePlugin.py index f4a68d1fd..54c7f1e26 100644 --- a/PIL/TiffImagePlugin.py +++ b/PIL/TiffImagePlugin.py @@ -1040,6 +1040,14 @@ def _save(im, fp, filename): pass if Image.DEBUG: print (atts) + + # libtiff always returns the bytes in native order. + # we're expecting image byte order. So, if the rawmode + # contains I;16, we need to convert from native to image + # byte order. + if im.mode in ('I;16B', 'I;16'): + rawmode = 'I;16N' + a = (rawmode, compression, _fp, filename, atts) e = Image._getencoder(im.mode, compression, a, im.encoderconfig) e.setimage(im.im, (0,0)+im.size) diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index d4767c95a..6b3ab114e 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -115,6 +115,16 @@ def test_little_endian(): assert_equal(b[0], b'\xe0') assert_equal(b[1], b'\x01') + out = tempfile("temp.tif") + out = "temp.le.tif" + im.save(out) + reread = Image.open(out) + + assert_equal(reread.info['compression'], im.info['compression']) + assert_equal(reread.getpixel((0,0)), 480) + # UNDONE - libtiff defaults to writing in native endian, so + # on big endian, we'll get back mode = 'I;16B' here. + def test_big_endian(): im = Image.open('Tests/images/12bit.MM.deflate.tif') @@ -127,3 +137,10 @@ def test_big_endian(): assert_equal(b[0], b'\x01') assert_equal(b[1], b'\xe0') + out = tempfile("temp.tif") + im.save(out) + reread = Image.open(out) + + assert_equal(reread.info['compression'], im.info['compression']) + assert_equal(reread.getpixel((0,0)), 480) + diff --git a/libImaging/Pack.c b/libImaging/Pack.c index 320e94d67..1cc1f3a94 100644 --- a/libImaging/Pack.c +++ b/libImaging/Pack.c @@ -361,6 +361,27 @@ packI16B(UINT8* out, const UINT8* in_, int pixels) } } +static void +packI16N_I16B(UINT8* out, const UINT8* in, int pixels){ + int i; + UINT8* tmp = (UINT8*) in; + for (i = 0; i < pixels; i++) { + C16B; + out += 2; tmp += 2; + } + +} +static void +packI16N_I16(UINT8* out, const UINT8* in, int pixels){ + int i; + UINT8* tmp = (UINT8*) in; + for (i = 0; i < pixels; i++) { + C16L; + out += 2; tmp += 2; + } +} + + static void packI32S(UINT8* out, const UINT8* in, int pixels) { @@ -560,6 +581,9 @@ static struct { {"I;16", "I;16", 16, copy2}, {"I;16B", "I;16B", 16, copy2}, {"I;16L", "I;16L", 16, copy2}, + {"I;16", "I;16N", 16, packI16N_I16}, // LibTiff native->image endian. + {"I;16L", "I;16N", 16, packI16N_I16}, + {"I;16B", "I;16N", 16, packI16N_I16B}, {"BGR;15", "BGR;15", 16, copy2}, {"BGR;16", "BGR;16", 16, copy2}, {"BGR;24", "BGR;24", 24, copy3}, From 8d21ce1df799dce8608076050044bd8f37844234 Mon Sep 17 00:00:00 2001 From: Eric Soroos Date: Mon, 21 Oct 2013 22:53:35 +0000 Subject: [PATCH 06/12] py3k --- Tests/test_file_libtiff.py | 17 +++++++++++++---- Tests/test_file_tiff.py | 20 +++++++++++++------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index 6b3ab114e..67e351530 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -112,8 +112,13 @@ def test_little_endian(): b = im.tobytes() # Bytes are in image native order (little endian) - assert_equal(b[0], b'\xe0') - assert_equal(b[1], b'\x01') + if py3: + assert_equal(b[0], ord(b'\xe0')) + assert_equal(b[1], ord(b'\x01')) + else: + assert_equal(b[0], b'\xe0') + assert_equal(b[1], b'\x01') + out = tempfile("temp.tif") out = "temp.le.tif" @@ -134,8 +139,12 @@ def test_big_endian(): b = im.tobytes() # Bytes are in image native order (big endian) - assert_equal(b[0], b'\x01') - assert_equal(b[1], b'\xe0') + if py3: + assert_equal(b[0], ord(b'\x01')) + assert_equal(b[1], ord(b'\xe0')) + else: + assert_equal(b[0], b'\x01') + assert_equal(b[1], b'\xe0') out = tempfile("temp.tif") im.save(out) diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index c88e103b4..88c1aa8fd 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -80,8 +80,13 @@ def test_little_endian(): b = im.tobytes() # Bytes are in image native order (little endian) - assert_equal(b[0], b'\xe0') - assert_equal(b[1], b'\x01') + if py3: + assert_equal(b[0], ord(b'\xe0')) + assert_equal(b[1], ord(b'\x01')) + else: + assert_equal(b[0], b'\xe0') + assert_equal(b[1], b'\x01') + def test_big_endian(): im = Image.open('Tests/images/12bit.MM.cropped.tif') @@ -91,8 +96,9 @@ def test_big_endian(): b = im.tobytes() # Bytes are in image native order (big endian) - assert_equal(b[0], b'\x01') - assert_equal(b[1], b'\xe0') - - - + if py3: + assert_equal(b[0], ord(b'\x01')) + assert_equal(b[1], ord(b'\xe0')) + else: + assert_equal(b[0], b'\x01') + assert_equal(b[1], b'\xe0') From 32e2f97b215985933ef3aada4451d03f478f0be4 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 22 Oct 2013 09:18:41 -0700 Subject: [PATCH 07/12] Tag issues with libtiff -- Need to parse the tuples for the ifd and the im.ifd. getattr + default for the im.ifd instead of silent try/except --- PIL/TiffImagePlugin.py | 50 ++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/PIL/TiffImagePlugin.py b/PIL/TiffImagePlugin.py index 54c7f1e26..3a77525f3 100644 --- a/PIL/TiffImagePlugin.py +++ b/PIL/TiffImagePlugin.py @@ -1011,33 +1011,30 @@ def _save(im, fp, filename): _fp = os.dup(fp.fileno()) blocklist = [STRIPOFFSETS, STRIPBYTECOUNTS, ROWSPERSTRIP, ICCPROFILE] # ICC Profile crashes. - atts = dict([(k,v) for (k,(v,)) in ifd.items() if k not in blocklist]) - try: - # pull in more bits from the original file, e.g x,y resolution - # so that we can save(load('')) == original file. - for k,v in im.ifd.items(): - if k not in atts and k not in blocklist: - if type(v[0]) == tuple and len(v) > 1: - # A tuple of more than one rational tuples - # flatten to floats, following tiffcp.c->cpTag->TIFF_RATIONAL - atts[k] = [float(elt[0])/float(elt[1]) for elt in v] - continue - if type(v[0]) == tuple and len(v) == 1: - # A tuple of one rational tuples - # flatten to floats, following tiffcp.c->cpTag->TIFF_RATIONAL - atts[k] = float(v[0][0])/float(v[0][1]) - continue - if type(v) == tuple and len(v) == 1: - # int or similar - atts[k] = v[0] - continue - if type(v) == str: - atts[k] = v - continue + atts={} + # Merge the ones that we have with (optional) more bits from + # the original file, e.g x,y resolution so that we can + # save(load('')) == original file. + for k,v in itertools.chain(ifd.items(), getattr(im, 'ifd', {}).items()): + if k not in atts and k not in blocklist: + if type(v[0]) == tuple and len(v) > 1: + # A tuple of more than one rational tuples + # flatten to floats, following tiffcp.c->cpTag->TIFF_RATIONAL + atts[k] = [float(elt[0])/float(elt[1]) for elt in v] + continue + if type(v[0]) == tuple and len(v) == 1: + # A tuple of one rational tuples + # flatten to floats, following tiffcp.c->cpTag->TIFF_RATIONAL + atts[k] = float(v[0][0])/float(v[0][1]) + continue + if type(v) == tuple and len(v) == 1: + # int or similar + atts[k] = v[0] + continue + if type(v) == str: + atts[k] = bytes(v.encode('ascii', 'replace')) + b"\0" + continue - except: - # if we don't have an ifd here, just punt. - pass if Image.DEBUG: print (atts) @@ -1049,6 +1046,7 @@ def _save(im, fp, filename): rawmode = 'I;16N' a = (rawmode, compression, _fp, filename, atts) + print (im.mode, compression, a, im.encoderconfig) e = Image._getencoder(im.mode, compression, a, im.encoderconfig) e.setimage(im.im, (0,0)+im.size) while 1: From 8655209b4a707dd61105db583089d84fd48e5bcb Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 22 Oct 2013 09:24:51 -0700 Subject: [PATCH 08/12] rm debugging print --- PIL/TiffImagePlugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PIL/TiffImagePlugin.py b/PIL/TiffImagePlugin.py index 3a77525f3..24d177f2d 100644 --- a/PIL/TiffImagePlugin.py +++ b/PIL/TiffImagePlugin.py @@ -1046,7 +1046,7 @@ def _save(im, fp, filename): rawmode = 'I;16N' a = (rawmode, compression, _fp, filename, atts) - print (im.mode, compression, a, im.encoderconfig) + # print (im.mode, compression, a, im.encoderconfig) e = Image._getencoder(im.mode, compression, a, im.encoderconfig) e.setimage(im.im, (0,0)+im.size) while 1: From c41a9b2b233caf25a47f4707a3aa00347be8f0ee Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 22 Oct 2013 09:29:56 -0700 Subject: [PATCH 09/12] correcting debugging strings --- encode.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/encode.c b/encode.c index 783e67a8e..10ed90d12 100644 --- a/encode.c +++ b/encode.c @@ -773,11 +773,10 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args) (ttag_t) PyInt_AsLong(key), PyInt_AsLong(value)); } else if(PyBytes_Check(value)) { - TRACE(("Setting from String: %d, %s \n", (int)PyInt_AsLong(key),PyBytes_AsString(value))); + TRACE(("Setting from Bytes: %d, %s \n", (int)PyInt_AsLong(key),PyBytes_AsString(value))); status = ImagingLibTiffSetField(&encoder->state, (ttag_t) PyInt_AsLong(key), PyBytes_AsString(value)); - } else if(PyList_Check(value)) { int len,i; float *floatav; @@ -795,12 +794,12 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args) free(floatav); } } else if (PyFloat_Check(value)) { - TRACE(("Setting from String: %d, %f \n", (int)PyInt_AsLong(key),PyFloat_AsDouble(value))); + TRACE(("Setting from Float: %d, %f \n", (int)PyInt_AsLong(key),PyFloat_AsDouble(value))); status = ImagingLibTiffSetField(&encoder->state, (ttag_t) PyInt_AsLong(key), (float)PyFloat_AsDouble(value)); } else { - TRACE(("Unhandled type for key %d : %s ", + TRACE(("Unhandled type for key %d : %s \n", (int)PyInt_AsLong(key), PyBytes_AsString(PyObject_Str(value)))); } From 758da6c5819f1827a71497ed0d48192b89086e8a Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 22 Oct 2013 10:06:33 -0700 Subject: [PATCH 10/12] whitespace error --- Tests/test_file_libtiff.py | 76 +++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index 67e351530..c717be1e2 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -106,50 +106,50 @@ def test_adobe_deflate_tiff(): def test_little_endian(): - im = Image.open('Tests/images/12bit.deflate.tif') - assert_equal(im.getpixel((0,0)), 480) - assert_equal(im.mode, 'I;16') + im = Image.open('Tests/images/12bit.deflate.tif') + assert_equal(im.getpixel((0,0)), 480) + assert_equal(im.mode, 'I;16') - b = im.tobytes() - # Bytes are in image native order (little endian) - if py3: - assert_equal(b[0], ord(b'\xe0')) - assert_equal(b[1], ord(b'\x01')) - else: - assert_equal(b[0], b'\xe0') - assert_equal(b[1], b'\x01') - + b = im.tobytes() + # Bytes are in image native order (little endian) + if py3: + assert_equal(b[0], ord(b'\xe0')) + assert_equal(b[1], ord(b'\x01')) + else: + assert_equal(b[0], b'\xe0') + assert_equal(b[1], b'\x01') + - out = tempfile("temp.tif") - out = "temp.le.tif" - im.save(out) - reread = Image.open(out) + out = tempfile("temp.tif") + out = "temp.le.tif" + im.save(out) + reread = Image.open(out) - assert_equal(reread.info['compression'], im.info['compression']) - assert_equal(reread.getpixel((0,0)), 480) - # UNDONE - libtiff defaults to writing in native endian, so - # on big endian, we'll get back mode = 'I;16B' here. - + assert_equal(reread.info['compression'], im.info['compression']) + assert_equal(reread.getpixel((0,0)), 480) + # UNDONE - libtiff defaults to writing in native endian, so + # on big endian, we'll get back mode = 'I;16B' here. + def test_big_endian(): - im = Image.open('Tests/images/12bit.MM.deflate.tif') + im = Image.open('Tests/images/12bit.MM.deflate.tif') - assert_equal(im.getpixel((0,0)), 480) - assert_equal(im.mode, 'I;16B') + assert_equal(im.getpixel((0,0)), 480) + assert_equal(im.mode, 'I;16B') - b = im.tobytes() + b = im.tobytes() - # Bytes are in image native order (big endian) - if py3: - assert_equal(b[0], ord(b'\x01')) - assert_equal(b[1], ord(b'\xe0')) - else: - assert_equal(b[0], b'\x01') - assert_equal(b[1], b'\xe0') - - out = tempfile("temp.tif") - im.save(out) - reread = Image.open(out) + # Bytes are in image native order (big endian) + if py3: + assert_equal(b[0], ord(b'\x01')) + assert_equal(b[1], ord(b'\xe0')) + else: + assert_equal(b[0], b'\x01') + assert_equal(b[1], b'\xe0') + + out = tempfile("temp.tif") + im.save(out) + reread = Image.open(out) - assert_equal(reread.info['compression'], im.info['compression']) - assert_equal(reread.getpixel((0,0)), 480) + assert_equal(reread.info['compression'], im.info['compression']) + assert_equal(reread.getpixel((0,0)), 480) From 6357b4707c492cf2389b995ef620693cc11140f3 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 22 Oct 2013 10:09:25 -0700 Subject: [PATCH 11/12] String attr test case --- Tests/test_file_libtiff.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index c717be1e2..c68633780 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -93,6 +93,8 @@ def test_g4_write(): _assert_noerr(reread) assert_image_equal(reread, rot) + assert_equal(reread.info['compression'], orig.info['compression']) + assert_false(orig.tobytes() == reread.tobytes()) def test_adobe_deflate_tiff(): @@ -153,3 +155,17 @@ def test_big_endian(): assert_equal(reread.info['compression'], im.info['compression']) assert_equal(reread.getpixel((0,0)), 480) +def test_g4_string_info(): + """Tests String data in info directory""" + file = "Tests/images/lena_g4_500.tif" + orig = Image.open(file) + + out = tempfile("temp.tif") + + orig.tag[269] = 'temp.tif' + orig.save(out) + + reread = Image.open(out) + assert_equal('temp.tif', reread.tag[269]) + + From 6a0516d2c9f904d5bc3e38890add4b6b1df093e6 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 22 Oct 2013 10:10:37 -0700 Subject: [PATCH 12/12] final pass through atts: handling single rational tuple, using isStringType, flattening from single element tuple to string or int --- PIL/TiffImagePlugin.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/PIL/TiffImagePlugin.py b/PIL/TiffImagePlugin.py index 24d177f2d..695a2034a 100644 --- a/PIL/TiffImagePlugin.py +++ b/PIL/TiffImagePlugin.py @@ -46,6 +46,7 @@ __version__ = "1.3.5" from PIL import Image, ImageFile from PIL import ImagePalette from PIL import _binary +from PIL._util import isStringType import warnings import array, sys @@ -1027,13 +1028,25 @@ def _save(im, fp, filename): # flatten to floats, following tiffcp.c->cpTag->TIFF_RATIONAL atts[k] = float(v[0][0])/float(v[0][1]) continue - if type(v) == tuple and len(v) == 1: - # int or similar - atts[k] = v[0] + if type(v) == tuple and len(v) > 2: + # List of ints? + # BitsPerSample is one example, I get (8,8,8) + # UNDONE continue - if type(v) == str: + if type(v) == tuple and len(v) == 2: + # one rational tuple + # flatten to float, following tiffcp.c->cpTag->TIFF_RATIONAL + atts[k] = float(v[0])/float(v[1]) + continue + if type(v) == tuple and len(v) == 1: + v = v[0] + # drop through + if isStringType(v): atts[k] = bytes(v.encode('ascii', 'replace')) + b"\0" continue + else: + # int or similar + atts[k] = v if Image.DEBUG: print (atts)