From b917623513466b0067b36964d664228bff34e527 Mon Sep 17 00:00:00 2001 From: Hugo Date: Fri, 18 Apr 2014 15:11:05 +0300 Subject: [PATCH 01/46] Run slow pypy first It's always the slowest and we should give it a head start so we're not waiting for it to finish at the end. It means we're making the most use of our parallel job-runners for the quicker jobs. See also #632. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 34ffcfe1a..07862a6c1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,11 +8,11 @@ notifications: irc: "chat.freenode.net#pil" python: + - "pypy" - 2.6 - 2.7 - 3.2 - 3.3 - - "pypy" install: - "sudo apt-get -qq install libfreetype6-dev liblcms2-dev python-qt4 ghostscript libffi-dev cmake" From 522e0ff31cdb4e0ad40f26526530d3d265744757 Mon Sep 17 00:00:00 2001 From: Hugo Date: Wed, 30 Apr 2014 10:06:35 +0300 Subject: [PATCH 02/46] Python 3.4 is live on Travis CI http://blog.travis-ci.com/2014-04-28-upcoming-build-environment-updates/ https://twitter.com/travisci/status/461365365587456000 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 07862a6c1..937127492 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ python: - 2.7 - 3.2 - 3.3 + - 3.4 install: - "sudo apt-get -qq install libfreetype6-dev liblcms2-dev python-qt4 ghostscript libffi-dev cmake" From d8e4ed11986d410dab77c0c5ff5d9f94d335aafb Mon Sep 17 00:00:00 2001 From: hugovk Date: Wed, 30 Apr 2014 11:05:15 +0300 Subject: [PATCH 03/46] system_site_packages was causing build errors. Allow 3.4 as a failure for now, as a PendingDeprecationWarning is causing failures; this is a problem with the test runner not liking any print output. --- .travis.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 937127492..cc039d91e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,5 @@ language: python -# for python-qt4 -virtualenv: - system_site_packages: true - notifications: irc: "chat.freenode.net#pil" @@ -13,7 +9,6 @@ python: - 2.7 - 3.2 - 3.3 - - 3.4 install: - "sudo apt-get -qq install libfreetype6-dev liblcms2-dev python-qt4 ghostscript libffi-dev cmake" @@ -43,3 +38,4 @@ after_success: matrix: allow_failures: - python: "pypy" + - python: 3.4 From 0de2212653a25190a8e8be61e63cd8607bfb9194 Mon Sep 17 00:00:00 2001 From: hugovk Date: Wed, 30 Apr 2014 11:07:43 +0300 Subject: [PATCH 04/46] Add 3.4 back --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index cc039d91e..ccc6e7abf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,7 @@ python: - 2.7 - 3.2 - 3.3 + - 3.4 install: - "sudo apt-get -qq install libfreetype6-dev liblcms2-dev python-qt4 ghostscript libffi-dev cmake" From d2fbc52d6c88fd01fd8283158ddcb0b45a36c4a4 Mon Sep 17 00:00:00 2001 From: Nicolas F Date: Wed, 30 Apr 2014 11:30:44 +0200 Subject: [PATCH 05/46] Change unsigned INT16 to UINT16 Addresses issue #642 --- libImaging/Gif.h | 2 +- libImaging/Lzw.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libImaging/Gif.h b/libImaging/Gif.h index 85d428b0d..2cb95efd2 100644 --- a/libImaging/Gif.h +++ b/libImaging/Gif.h @@ -59,7 +59,7 @@ typedef struct { unsigned char buffer[GIFTABLE]; /* Symbol table */ - unsigned INT16 link[GIFTABLE]; + UINT16 link[GIFTABLE]; unsigned char data[GIFTABLE]; int next; diff --git a/libImaging/Lzw.h b/libImaging/Lzw.h index 7d087ac47..8fc30bd7f 100644 --- a/libImaging/Lzw.h +++ b/libImaging/Lzw.h @@ -45,7 +45,7 @@ typedef struct { unsigned char buffer[LZWTABLE]; /* Symbol table */ - unsigned INT16 link[LZWTABLE]; + UINT16 link[LZWTABLE]; unsigned char data[LZWTABLE]; int next; From e835dd70a1183aaab7adaa43a7f28221038d28c9 Mon Sep 17 00:00:00 2001 From: hugovk Date: Mon, 5 May 2014 22:09:57 +0300 Subject: [PATCH 06/46] Discard first byte if not 0xFF (for issue #630) --- PIL/JpegImagePlugin.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/PIL/JpegImagePlugin.py b/PIL/JpegImagePlugin.py index da52006ca..757d02519 100644 --- a/PIL/JpegImagePlugin.py +++ b/PIL/JpegImagePlugin.py @@ -290,24 +290,29 @@ class JpegImageFile(ImageFile.ImageFile): while True: - s = s + self.fp.read(1) - - i = i16(s) + i = i8(s) + if i == 0xFF: + s = s + self.fp.read(1) + i = i16(s) + else: + # Skip non-0xFF junk + s = "\xff" + continue if i in MARKER: name, description, handler = MARKER[i] # print hex(i), name, description if handler is not None: handler(self, i) - if i == 0xFFDA: # start of scan + if i == 0xFFDA: # start of scan rawmode = self.mode if self.mode == "CMYK": - rawmode = "CMYK;I" # assume adobe conventions - self.tile = [("jpeg", (0,0) + self.size, 0, (rawmode, ""))] + rawmode = "CMYK;I" # assume adobe conventions + self.tile = [("jpeg", (0, 0) + self.size, 0, (rawmode, ""))] # self.__offset = self.fp.tell() break s = self.fp.read(1) - elif i == 0 or i == 65535: + elif i == 0 or i == 0xFFFF: # padded marker or junk; move on s = "\xff" else: From f4071ade0a995c02fcbc40ff1f3982bbbda2b4ff Mon Sep 17 00:00:00 2001 From: hugovk Date: Mon, 5 May 2014 22:41:09 +0300 Subject: [PATCH 07/46] pep8 --- PIL/JpegImagePlugin.py | 69 +++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/PIL/JpegImagePlugin.py b/PIL/JpegImagePlugin.py index 757d02519..6f32878e5 100644 --- a/PIL/JpegImagePlugin.py +++ b/PIL/JpegImagePlugin.py @@ -34,7 +34,8 @@ __version__ = "0.6" -import array, struct +import array +import struct from PIL import Image, ImageFile, _binary from PIL.JpegPresets import presets from PIL._util import isStringType @@ -44,6 +45,7 @@ o8 = _binary.o8 i16 = _binary.i16be i32 = _binary.i32be + # # Parser @@ -51,6 +53,7 @@ def Skip(self, marker): n = i16(self.fp.read(2))-2 ImageFile._safe_read(self.fp, n) + def APP(self, marker): # # Application marker. Store these in the APP dictionary. @@ -59,14 +62,14 @@ def APP(self, marker): n = i16(self.fp.read(2))-2 s = ImageFile._safe_read(self.fp, n) - app = "APP%d" % (marker&15) + app = "APP%d" % (marker & 15) - self.app[app] = s # compatibility + self.app[app] = s # compatibility self.applist.append((app, s)) if marker == 0xFFE0 and s[:4] == b"JFIF": # extract JFIF information - self.info["jfif"] = version = i16(s, 5) # version + self.info["jfif"] = version = i16(s, 5) # version self.info["jfif_version"] = divmod(version, 256) # extract JFIF properties try: @@ -81,10 +84,10 @@ def APP(self, marker): self.info["jfif_density"] = jfif_density elif marker == 0xFFE1 and s[:5] == b"Exif\0": # extract Exif information (incomplete) - self.info["exif"] = s # FIXME: value will change + self.info["exif"] = s # FIXME: value will change elif marker == 0xFFE2 and s[:5] == b"FPXR\0": # extract FlashPix information (incomplete) - self.info["flashpix"] = s # FIXME: value will change + self.info["flashpix"] = s # FIXME: value will change elif marker == 0xFFE2 and s[:12] == b"ICC_PROFILE\0": # Since an ICC profile can be larger than the maximum size of # a JPEG marker (64K), we need provisions to split it into @@ -108,16 +111,17 @@ def APP(self, marker): else: self.info["adobe_transform"] = adobe_transform + def COM(self, marker): # # Comment marker. Store these in the APP dictionary. - n = i16(self.fp.read(2))-2 s = ImageFile._safe_read(self.fp, n) - self.app["COM"] = s # compatibility + self.app["COM"] = s # compatibility self.applist.append(("COM", s)) + def SOF(self, marker): # # Start of frame marker. Defines the size and mode of the @@ -149,21 +153,22 @@ def SOF(self, marker): if self.icclist: # fixup icc profile - self.icclist.sort() # sort by sequence number + self.icclist.sort() # sort by sequence number if i8(self.icclist[0][13]) == len(self.icclist): profile = [] for p in self.icclist: profile.append(p[14:]) icc_profile = b"".join(profile) else: - icc_profile = None # wrong number of fragments + icc_profile = None # wrong number of fragments self.info["icc_profile"] = icc_profile self.icclist = None for i in range(6, len(s), 3): t = s[i:i+3] # 4-tuples: id, vsamp, hsamp, qtable - self.layer.append((t[0], i8(t[1])//16, i8(t[1])&15, i8(t[2]))) + self.layer.append((t[0], i8(t[1])//16, i8(t[1]) & 15, i8(t[2]))) + def DQT(self, marker): # @@ -181,10 +186,10 @@ def DQT(self, marker): raise SyntaxError("bad quantization table marker") v = i8(s[0]) if v//16 == 0: - self.quantization[v&15] = array.array("b", s[1:65]) + self.quantization[v & 15] = array.array("b", s[1:65]) s = s[65:] else: - return # FIXME: add code to read 16-bit tables! + return # FIXME: add code to read 16-bit tables! # raise SyntaxError, "bad quantization table element size" @@ -261,6 +266,7 @@ MARKER = { def _accept(prefix): return prefix[0:1] == b"\377" + ## # Image plugin for JPEG and JFIF images. @@ -284,7 +290,7 @@ class JpegImageFile(ImageFile.ImageFile): self.huffman_dc = {} self.huffman_ac = {} self.quantization = {} - self.app = {} # compatibility + self.app = {} # compatibility self.applist = [] self.icclist = [] @@ -348,7 +354,8 @@ class JpegImageFile(ImageFile.ImageFile): # ALTERNATIVE: handle JPEGs via the IJG command line utilities - import tempfile, os + import tempfile + import os f, path = tempfile.mkstemp() os.close(f) if os.path.exists(self.filename): @@ -359,8 +366,10 @@ class JpegImageFile(ImageFile.ImageFile): try: self.im = Image.core.open_ppm(path) finally: - try: os.unlink(path) - except: pass + try: + os.unlink(path) + except: + pass self.mode = self.im.mode self.size = self.im.size @@ -377,6 +386,7 @@ def _getexif(self): # version. from PIL import TiffImagePlugin import io + def fixup(value): if len(value) == 1: return value[0] @@ -427,7 +437,7 @@ RAWMODE = { "RGB": "RGB", "RGBA": "RGB", "RGBX": "RGB", - "CMYK": "CMYK;I", # assume adobe conventions + "CMYK": "CMYK;I", # assume adobe conventions "YCbCr": "YCbCr", } @@ -446,16 +456,19 @@ samplings = { (2, 2, 1, 1, 1, 1): 2, } + def convert_dict_qtables(qtables): qtables = [qtables[key] for key in range(len(qtables)) if key in qtables] for idx, table in enumerate(qtables): qtables[idx] = [table[i] for i in zigzag_index] return qtables + def get_sampling(im): sampling = im.layer[0][1:3] + im.layer[1][1:3] + im.layer[2][1:3] return samplings.get(sampling, -1) + def _save(im, fp, filename): try: @@ -568,12 +581,11 @@ def _save(im, fp, filename): info.get("exif", b"") ) - - # if we optimize, libjpeg needs a buffer big enough to hold the whole image in a shot. - # Guessing on the size, at im.size bytes. (raw pizel size is channels*size, this - # is a value that's been used in a django patch. + # if we optimize, libjpeg needs a buffer big enough to hold the whole image + # in a shot. Guessing on the size, at im.size bytes. (raw pizel size is + # channels*size, this is a value that's been used in a django patch. # https://github.com/jdriscoll/django-imagekit/issues/50 - bufsize=0 + bufsize = 0 if "optimize" in info or "progressive" in info or "progression" in info: if quality >= 95: bufsize = 2 * im.size[0] * im.size[1] @@ -582,17 +594,20 @@ def _save(im, fp, filename): # The exif info needs to be written as one block, + APP1, + one spare byte. # Ensure that our buffer is big enough - bufsize = max(ImageFile.MAXBLOCK, bufsize, len(info.get("exif",b"")) + 5 ) + bufsize = max(ImageFile.MAXBLOCK, bufsize, len(info.get("exif", b"")) + 5) + + ImageFile._save(im, fp, [("jpeg", (0, 0)+im.size, 0, rawmode)], bufsize) - ImageFile._save(im, fp, [("jpeg", (0,0)+im.size, 0, rawmode)], bufsize) def _save_cjpeg(im, fp, filename): # ALTERNATIVE: handle JPEGs via the IJG command line utilities. import os file = im._dump() os.system("cjpeg %s >%s" % (file, filename)) - try: os.unlink(file) - except: pass + try: + os.unlink(file) + except: + pass # -------------------------------------------------------------------q- # Registry stuff From 5f195ae1a7d6057be2f8918825041642e0c96163 Mon Sep 17 00:00:00 2001 From: hugovk Date: Fri, 9 May 2014 11:41:43 +0300 Subject: [PATCH 08/46] On Py3.4, a PendingDeprecationWarning comes from Coverage.py for using the imp module. This warning causes 3.4 builds to fail so ignore the warning from importing coverage. --- Tests/tester.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Tests/tester.py b/Tests/tester.py index 32da48e98..815c526c4 100644 --- a/Tests/tester.py +++ b/Tests/tester.py @@ -345,7 +345,10 @@ def _setup(): import sys if "--coverage" in sys.argv: - import coverage + # Temporary: ignore PendingDeprecationWarning from Coverage (Py3.4) + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + import coverage cov = coverage.coverage(auto_data=True, include="PIL/*") cov.start() From 56fe245dd1ed2a8b23e61cc856121384f49a4165 Mon Sep 17 00:00:00 2001 From: hugovk Date: Fri, 9 May 2014 11:53:49 +0300 Subject: [PATCH 09/46] Don't allow 3.4 failures --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ccc6e7abf..d3514b727 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,4 +39,3 @@ after_success: matrix: allow_failures: - python: "pypy" - - python: 3.4 From 53f17f690d930069966de78497606347a9683fbf Mon Sep 17 00:00:00 2001 From: hugovk Date: Fri, 9 May 2014 13:21:26 +0300 Subject: [PATCH 10/46] 'Dummy' commit to force rebuild. Extra reporting may be useful too. --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index d3514b727..1ae6e415c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,6 +35,8 @@ after_success: - pip install pep8 pyflakes - pep8 PIL/*.py - pyflakes PIL/*.py + - pep8 Tests/*.py + - pyflakes Tests/*.py matrix: allow_failures: From 37bb8eec240ebdcdace5b5ddb174c4e69a375aea Mon Sep 17 00:00:00 2001 From: Nicolas F Date: Fri, 9 May 2014 20:14:46 +0200 Subject: [PATCH 11/46] Don't ignore USE_INLINE on Windows --- libImaging/ImPlatform.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libImaging/ImPlatform.h b/libImaging/ImPlatform.h index 7fc5cbdca..81a39b2f7 100644 --- a/libImaging/ImPlatform.h +++ b/libImaging/ImPlatform.h @@ -33,7 +33,8 @@ #if defined(_MSC_VER) #define inline __inline -#elif !defined(USE_INLINE) +#endif +#if !defined(USE_INLINE) #define inline #endif From 052ea606bf9d46fa6dca5e348c766e1c48afa71a Mon Sep 17 00:00:00 2001 From: Nicolas F Date: Fri, 9 May 2014 21:05:30 +0200 Subject: [PATCH 12/46] Clean up defines and includes for Windows 1) Renamed USE_INLINE to PIL_USE_INLINE to avoid conflicts with other headers/libraries. 2) Replace __WIN32__ and WIN32 with _WIN32 3) Don't define WIN32 when the compiler is MSVC but not on Windows Why would you even... 4) Don't define strcasecmp if you're not even going to use it. 5) Don't include Windows.h with undefs for compilers newer than 1998 everywhere. 6) Don't surpress warnings for MSVC++ 4.0. People still using MSVC++ 4.0 deserve it. 7) Don't include things that are already included in Windows.h --- _imaging.c | 6 +++--- _imagingcms.c | 10 ++-------- decode.c | 3 --- display.c | 4 ++-- encode.c | 3 --- libImaging/Dib.c | 4 ++-- libImaging/ImDib.h | 15 ++------------- libImaging/ImPlatform.h | 41 ++++++++++++++++++++-------------------- libImaging/Incremental.c | 1 - map.c | 18 +++--------------- 10 files changed, 34 insertions(+), 71 deletions(-) diff --git a/_imaging.c b/_imaging.c index c47868b81..4f14b7cbd 100644 --- a/_imaging.c +++ b/_imaging.c @@ -3350,7 +3350,7 @@ extern PyObject* PyImaging_ZipEncoderNew(PyObject* self, PyObject* args); extern PyObject* PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args); /* Display support etc (in display.c) */ -#ifdef WIN32 +#ifdef _WIN32 extern PyObject* PyImaging_CreateWindowWin32(PyObject* self, PyObject* args); extern PyObject* PyImaging_DisplayWin32(PyObject* self, PyObject* args); extern PyObject* PyImaging_DisplayModeWin32(PyObject* self, PyObject* args); @@ -3423,14 +3423,14 @@ static PyMethodDef functions[] = { /* Memory mapping */ #ifdef WITH_MAPPING -#ifdef WIN32 +#ifdef _WIN32 {"map", (PyCFunction)PyImaging_Mapper, 1}, #endif {"map_buffer", (PyCFunction)PyImaging_MapBuffer, 1}, #endif /* Display support */ -#ifdef WIN32 +#ifdef _WIN32 {"display", (PyCFunction)PyImaging_DisplayWin32, 1}, {"display_mode", (PyCFunction)PyImaging_DisplayModeWin32, 1}, {"grabscreen", (PyCFunction)PyImaging_GrabScreenWin32, 1}, diff --git a/_imagingcms.c b/_imagingcms.c index 99da647ae..df26e1a2d 100644 --- a/_imagingcms.c +++ b/_imagingcms.c @@ -28,12 +28,6 @@ http://www.cazabon.com\n\ #include "Imaging.h" #include "py3.h" -#ifdef WIN32 -#include -#include -#include -#endif - #define PYCMSVERSION "1.0.0 pil" /* version history */ @@ -450,7 +444,7 @@ cms_profile_is_intent_supported(CmsProfileObject *self, PyObject *args) return PyInt_FromLong(result != 0); } -#ifdef WIN32 +#ifdef _WIN32 static PyObject * cms_get_display_profile_win32(PyObject* self, PyObject* args) { @@ -496,7 +490,7 @@ static PyMethodDef pyCMSdll_methods[] = { {"createProfile", createProfile, 1}, /* platform specific tools */ -#ifdef WIN32 +#ifdef _WIN32 {"get_display_profile_win32", cms_get_display_profile_win32, 1}, #endif diff --git a/decode.c b/decode.c index 77038cc2c..33367dfe3 100644 --- a/decode.c +++ b/decode.c @@ -433,9 +433,6 @@ PyImaging_TiffLzwDecoderNew(PyObject* self, PyObject* args) #include "TiffDecode.h" #include -#ifdef __WIN32__ -#define strcasecmp(s1, s2) stricmp(s1, s2) -#endif PyObject* PyImaging_LibTiffDecoderNew(PyObject* self, PyObject* args) diff --git a/display.c b/display.c index 9cc1ae3ad..e10d72c0d 100644 --- a/display.c +++ b/display.c @@ -31,7 +31,7 @@ /* -------------------------------------------------------------------- */ /* Windows DIB support */ -#ifdef WIN32 +#ifdef _WIN32 #include "ImDib.h" @@ -864,4 +864,4 @@ error: return buffer; } -#endif /* WIN32 */ +#endif /* _WIN32 */ diff --git a/encode.c b/encode.c index d403ab072..b14942376 100644 --- a/encode.c +++ b/encode.c @@ -670,9 +670,6 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args) #include "TiffDecode.h" #include -#ifdef __WIN32__ -#define strcasecmp(s1, s2) stricmp(s1, s2) -#endif PyObject* PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args) diff --git a/libImaging/Dib.c b/libImaging/Dib.c index 6db8c076e..8e138bd6b 100644 --- a/libImaging/Dib.c +++ b/libImaging/Dib.c @@ -22,7 +22,7 @@ #include "Imaging.h" -#ifdef WIN32 +#ifdef _WIN32 #include "ImDib.h" @@ -308,4 +308,4 @@ ImagingDeleteDIB(ImagingDIB dib) free(dib->info); } -#endif /* WIN32 */ +#endif /* _WIN32 */ diff --git a/libImaging/ImDib.h b/libImaging/ImDib.h index 23c660488..55ecb35aa 100644 --- a/libImaging/ImDib.h +++ b/libImaging/ImDib.h @@ -10,20 +10,9 @@ * See the README file for information on usage and redistribution. */ -#ifdef WIN32 +#ifdef _WIN32 -#if (defined(_MSC_VER) && _MSC_VER >= 1200) || (defined __GNUC__) -/* already defined in basetsd.h */ -#undef INT8 -#undef UINT8 -#undef INT16 -#undef UINT16 -#undef INT32 -#undef INT64 -#undef UINT32 -#endif - -#include +#include "ImPlatform.h" #if defined(__cplusplus) extern "C" { diff --git a/libImaging/ImPlatform.h b/libImaging/ImPlatform.h index 81a39b2f7..92c126a10 100644 --- a/libImaging/ImPlatform.h +++ b/libImaging/ImPlatform.h @@ -17,27 +17,22 @@ #error Sorry, this library requires ANSI header files. #endif -#if defined(_MSC_VER) -#ifndef WIN32 -#define WIN32 -#endif -/* VC++ 4.0 is a bit annoying when it comes to precision issues (like - claiming that "float a = 0.0;" would lead to loss of precision). I - don't like to see warnings from my code, but since I still want to - keep it readable, I simply switch off a few warnings instead of adding - the tons of casts that VC++ seem to require. This code is compiled - with numerous other compilers as well, so any real errors are likely - to be catched anyway. */ -#pragma warning(disable: 4244) /* conversion from 'float' to 'int' */ -#endif - -#if defined(_MSC_VER) +#if defined(_MSC_VER) && !defined(__GNUC__) #define inline __inline #endif -#if !defined(USE_INLINE) -#define inline + +#if !defined(PIL_USE_INLINE) +#define inline #endif +#ifdef _WIN32 + +#define WIN32_LEAN_AND_MEAN +#include + +#else +/* For System that are not Windows, we'll need to define these. */ + #if SIZEOF_SHORT == 2 #define INT16 short #elif SIZEOF_INT == 2 @@ -62,12 +57,16 @@ #define INT64 long #endif -/* assume IEEE; tweak if necessary (patches are welcome) */ -#define FLOAT32 float -#define FLOAT64 double - #define INT8 signed char #define UINT8 unsigned char #define UINT16 unsigned INT16 #define UINT32 unsigned INT32 + +#endif + +/* assume IEEE; tweak if necessary (patches are welcome) */ +#define FLOAT32 float +#define FLOAT64 double + + diff --git a/libImaging/Incremental.c b/libImaging/Incremental.c index 9e7fb38ec..206c8130b 100644 --- a/libImaging/Incremental.c +++ b/libImaging/Incremental.c @@ -41,7 +41,6 @@ two cases. */ #ifdef _WIN32 -#include #include #else #include diff --git a/map.c b/map.c index 95d5d1d35..dc9ead0aa 100644 --- a/map.c +++ b/map.c @@ -22,18 +22,6 @@ #include "Imaging.h" -#ifdef WIN32 -#define WIN32_LEAN_AND_MEAN -#undef INT8 -#undef UINT8 -#undef INT16 -#undef UINT16 -#undef INT32 -#undef INT64 -#undef UINT32 -#include "windows.h" -#endif - #include "py3.h" /* compatibility wrappers (defined in _imaging.c) */ @@ -48,7 +36,7 @@ typedef struct { char* base; int size; int offset; -#ifdef WIN32 +#ifdef _WIN32 HANDLE hFile; HANDLE hMap; #endif @@ -71,7 +59,7 @@ PyImaging_MapperNew(const char* filename, int readonly) mapper->base = NULL; mapper->size = mapper->offset = 0; -#ifdef WIN32 +#ifdef _WIN32 mapper->hFile = (HANDLE)-1; mapper->hMap = (HANDLE)-1; @@ -114,7 +102,7 @@ PyImaging_MapperNew(const char* filename, int readonly) static void mapping_dealloc(ImagingMapperObject* mapper) { -#ifdef WIN32 +#ifdef _WIN32 if (mapper->base != 0) UnmapViewOfFile(mapper->base); if (mapper->hMap != (HANDLE)-1) From 22a370afc219af47907b2fe69e791854dd2d9c79 Mon Sep 17 00:00:00 2001 From: hugovk Date: Sat, 10 May 2014 11:46:53 +0300 Subject: [PATCH 13/46] Fix 12-year-old FIXME --- PIL/Image.py | 46 +++++++++++++++++++++------------------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/PIL/Image.py b/PIL/Image.py index 333397701..7736a3718 100644 --- a/PIL/Image.py +++ b/PIL/Image.py @@ -101,7 +101,7 @@ import collections import numbers # works everywhere, win for pypy, not cpython -USE_CFFI_ACCESS = hasattr(sys, 'pypy_version_info') +USE_CFFI_ACCESS = hasattr(sys, 'pypy_version_info') try: import cffi HAS_CFFI=True @@ -233,7 +233,7 @@ _MODE_CONV = { "CMYK": ('|u1', 4), "YCbCr": ('|u1', 3), "LAB": ('|u1', 3), # UNDONE - unsigned |u1i1i1 - # I;16 == I;16L, and I;32 == I;32L + # I;16 == I;16L, and I;32 == I;32L "I;16": ('u2', None), "I;16L": (' 8bit images. + # a gamma function point transform on > 8bit images. scale, offset = _getscaleoffset(lut) return self._new(self.im.point_transform(scale, offset)) # for other modes, convert the function to a table @@ -1420,8 +1420,8 @@ class Image: self._copy() self.pyaccess = None self.load() - - if self.pyaccess: + + if self.pyaccess: return self.pyaccess.putpixel(xy,value) return self.im.putpixel(xy, value) @@ -1667,7 +1667,7 @@ class Image: """ return 0 - def thumbnail(self, size, resample=NEAREST): + def thumbnail(self, size, resample=ANTIALIAS): """ Make this image into a thumbnail. This method modifies the image to contain a thumbnail version of itself, no larger than @@ -1690,14 +1690,10 @@ class Image: of :py:attr:`PIL.Image.NEAREST`, :py:attr:`PIL.Image.BILINEAR`, :py:attr:`PIL.Image.BICUBIC`, or :py:attr:`PIL.Image.ANTIALIAS` (best quality). If omitted, it defaults to - :py:attr:`PIL.Image.NEAREST` (this will be changed to ANTIALIAS in a - future version). + :py:attr:`PIL.Image.ANTIALIAS`. :returns: None """ - # FIXME: the default resampling filter will be changed - # to ANTIALIAS in future versions - # preserve aspect ratio x, y = self.size if x > size[0]: y = int(max(y * size[0] / x, 1)); x = int(size[0]) From 74514fa1f54d82194d9cb2388f6383b6d8ca8df1 Mon Sep 17 00:00:00 2001 From: hugovk Date: Sat, 10 May 2014 12:34:36 +0300 Subject: [PATCH 14/46] Some pep8 and pyflakes cleanup --- PIL/Image.py | 152 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 94 insertions(+), 58 deletions(-) diff --git a/PIL/Image.py b/PIL/Image.py index 7736a3718..80b7258c6 100644 --- a/PIL/Image.py +++ b/PIL/Image.py @@ -30,6 +30,7 @@ from PIL import VERSION, PILLOW_VERSION, _plugins import warnings + class _imaging_not_installed: # module placeholder def __getattr__(self, id): @@ -52,7 +53,7 @@ try: # directly; import Image and use the Image.core variable instead. from PIL import _imaging as core if PILLOW_VERSION != getattr(core, 'PILLOW_VERSION', None): - raise ImportError("The _imaging extension was built for another " + raise ImportError("The _imaging extension was built for another " " version of Pillow or PIL") except ImportError as v: @@ -91,10 +92,13 @@ except ImportError: builtins = __builtin__ from PIL import ImageMode -from PIL._binary import i8, o8 -from PIL._util import isPath, isStringType, deferred_error +from PIL._binary import i8 +from PIL._util import isPath +from PIL._util import isStringType +from PIL._util import deferred_error -import os, sys +import os +import sys # type stuff import collections @@ -104,9 +108,10 @@ import numbers USE_CFFI_ACCESS = hasattr(sys, 'pypy_version_info') try: import cffi - HAS_CFFI=True + HAS_CFFI = True except: - HAS_CFFI=False + HAS_CFFI = False + def isImageType(t): """ @@ -148,16 +153,16 @@ MESH = 4 # resampling filters NONE = 0 NEAREST = 0 -ANTIALIAS = 1 # 3-lobed lanczos +ANTIALIAS = 1 # 3-lobed lanczos LINEAR = BILINEAR = 2 CUBIC = BICUBIC = 3 # dithers NONE = 0 NEAREST = 0 -ORDERED = 1 # Not yet implemented -RASTERIZE = 2 # Not yet implemented -FLOYDSTEINBERG = 3 # default +ORDERED = 1 # Not yet implemented +RASTERIZE = 2 # Not yet implemented +FLOYDSTEINBERG = 3 # default # palettes/quantizers WEB = 0 @@ -222,7 +227,7 @@ else: _MODE_CONV = { # official modes - "1": ('|b1', None), # broken + "1": ('|b1', None), # broken "L": ('|u1', None), "I": (_ENDIAN + 'i4', None), "F": (_ENDIAN + 'f4', None), @@ -232,8 +237,8 @@ _MODE_CONV = { "RGBA": ('|u1', 4), "CMYK": ('|u1', 4), "YCbCr": ('|u1', 3), - "LAB": ('|u1', 3), # UNDONE - unsigned |u1i1i1 - # I;16 == I;16L, and I;32 == I;32L + "LAB": ('|u1', 3), # UNDONE - unsigned |u1i1i1 + # I;16 == I;16L, and I;32 == I;32L "I;16": ('u2', None), "I;16L": (' size[0]: y = int(max(y * size[0] / x, 1)); x = int(size[0]) - if y > size[1]: x = int(max(x * size[1] / y, 1)); y = int(size[1]) + if x > size[0]: + y = int(max(y * size[0] / x, 1)) + x = int(size[0]) + if y > size[1]: + x = int(max(x * size[1] / y, 1)) + y = int(size[1]) size = x, y if size == self.size: @@ -1712,7 +1733,7 @@ class Image: except ValueError: if resample != ANTIALIAS: raise - im = self.resize(size, NEAREST) # fallback + im = self.resize(size, NEAREST) # fallback self.im = im.im self.mode = im.mode @@ -1748,7 +1769,9 @@ class Image: """ if self.mode == 'RGBA': - return self.convert('RGBa').transform(size, method, data, resample, fill).convert('RGBA') + return self.convert('RGBa') \ + .transform(size, method, data, resample, fill) \ + .convert('RGBA') if isinstance(method, ImageTransformHandler): return method.transform(size, self, resample=resample, fill=fill) @@ -1795,8 +1818,13 @@ class Image: elif method == QUAD: # quadrilateral warp. data specifies the four corners # given as NW, SW, SE, and NE. - nw = data[0:2]; sw = data[2:4]; se = data[4:6]; ne = data[6:8] - x0, y0 = nw; As = 1.0 / w; At = 1.0 / h + nw = data[0:2] + sw = data[2:4] + se = data[4:6] + ne = data[6:8] + x0, y0 = nw + As = 1.0 / w + At = 1.0 / h data = (x0, (ne[0]-x0)*As, (sw[0]-x0)*At, (se[0]-sw[0]-ne[0]+x0)*As*At, y0, (ne[1]-y0)*As, (sw[1]-y0)*At, @@ -1830,6 +1858,7 @@ class Image: im = self.im.transpose(method) return self._new(im) + # -------------------------------------------------------------------- # Lazy operations @@ -1865,6 +1894,7 @@ class _ImageCrop(Image): # FIXME: future versions should optimize crop/paste # sequences! + # -------------------------------------------------------------------- # Abstract handlers. @@ -1872,10 +1902,12 @@ class ImagePointHandler: # used as a mixin by point transforms (for use with im.point) pass + class ImageTransformHandler: # used as a mixin by geometry transforms (for use with im.transform) pass + # -------------------------------------------------------------------- # Factories @@ -1951,6 +1983,7 @@ def frombytes(mode, size, data, decoder_name="raw", *args): im.frombytes(data, decoder_name, args) return im + def fromstring(*args, **kw): """Deprecated alias to frombytes. @@ -2013,9 +2046,9 @@ def frombuffer(mode, size, data, decoder_name="raw", *args): " frombuffer(mode, size, data, 'raw', mode, 0, 1)", RuntimeWarning, stacklevel=2 ) - args = mode, 0, -1 # may change to (mode, 0, 1) post-1.1.6 + args = mode, 0, -1 # may change to (mode, 0, 1) post-1.1.6 if args[0] in _MAPMODES: - im = new(mode, (1,1)) + im = new(mode, (1, 1)) im = im._new( core.map_buffer(data, size, decoder_name, None, 0, args) ) @@ -2135,8 +2168,8 @@ def open(fp, mode="r"): fp.seek(0) return factory(fp, filename) except (SyntaxError, IndexError, TypeError): - #import traceback - #traceback.print_exc() + # import traceback + # traceback.print_exc() pass if init(): @@ -2148,13 +2181,14 @@ def open(fp, mode="r"): fp.seek(0) return factory(fp, filename) except (SyntaxError, IndexError, TypeError): - #import traceback - #traceback.print_exc() + # import traceback + # traceback.print_exc() pass raise IOError("cannot identify image file %r" % (filename if filename else fp)) + # # Image processing. @@ -2253,6 +2287,7 @@ def merge(mode, bands): im.putband(bands[i].im, i) return bands[0]._new(im) + # -------------------------------------------------------------------- # Plugin registry @@ -2311,6 +2346,7 @@ def _show(image, **options): # override me, as necessary _showxv(image, **options) + def _showxv(image, title=None, **options): from PIL import ImageShow ImageShow.show(image, title, **options) From 29ddeaa81a0de6a488355bca55dd42a6b28259ff Mon Sep 17 00:00:00 2001 From: Jack Nagel Date: Sat, 10 May 2014 10:11:04 -0500 Subject: [PATCH 15/46] Adjust Homebrew freetype detection logic XQuartz ships an older freetype that still has a top-level "ft2build.h" header file. Homebrew's freetype is newer and does not have this file, it only has "freetype2/ft2build.h". setup.py finds the header in XQuartz first, but Homebrew's compiler wrappers intentionally strip out the XQuartz include paths during the build unless the package depends on it explicitly. We want to prefer Homebrew's freetype anyway, so if it's installed, let's not even bother to search the XQuartz paths. --- setup.py | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/setup.py b/setup.py index 93918debd..50ca985e3 100644 --- a/setup.py +++ b/setup.py @@ -205,25 +205,31 @@ class pil_build_ext(build_ext): # darwin ports installation directories _add_directory(library_dirs, "/opt/local/lib") _add_directory(include_dirs, "/opt/local/include") - - # if homebrew is installed, use its lib and include directories + + # if Homebrew is installed, use its lib and include directories import subprocess try: - prefix = subprocess.check_output(['brew', '--prefix']) - if prefix: - prefix = prefix.strip() - _add_directory(library_dirs, os.path.join(prefix, 'lib')) - _add_directory(include_dirs, os.path.join(prefix, 'include')) - - # freetype2 is a key-only brew under opt/ - _add_directory(library_dirs, os.path.join(prefix, 'opt', 'freetype', 'lib')) - _add_directory(include_dirs, os.path.join(prefix, 'opt', 'freetype', 'include')) + prefix = subprocess.check_output(['brew', '--prefix']).strip() except: - pass # homebrew not installed - - # freetype2 ships with X11 (after homebrew, so that homebrew freetype is preferred) - _add_directory(library_dirs, "/usr/X11/lib") - _add_directory(include_dirs, "/usr/X11/include") + # Homebrew not installed + prefix = None + + ft_prefix = None + + if prefix: + # add Homebrew's include and lib directories + _add_directory(library_dirs, os.path.join(prefix, 'lib')) + _add_directory(include_dirs, os.path.join(prefix, 'include')) + ft_prefix = os.path.join(prefix, 'opt', 'freetype') + + if ft_prefix and os.path.isdir(ft_prefix): + # freetype might not be linked into Homebrew's prefix + _add_directory(library_dirs, os.path.join(ft_prefix, 'lib')) + _add_directory(include_dirs, os.path.join(ft_prefix, 'include')) + else: + # fall back to freetype from XQuartz if Homebrew's freetype is missing + _add_directory(library_dirs, "/usr/X11/lib") + _add_directory(include_dirs, "/usr/X11/include") elif sys.platform.startswith("linux"): arch_tp = (plat.processor(), plat.architecture()[0]) From 84a701a82b33896a4d6997743c2131ab0a40c588 Mon Sep 17 00:00:00 2001 From: Alex Clark Date: Sat, 10 May 2014 13:29:36 -0400 Subject: [PATCH 16/46] Update --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index c774a6ddf..81e388cda 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,9 @@ Changelog (Pillow) 2.5.0 (unreleased) ------------------ +- Adjust Homebrew freetype detection logic + [jacknagel] + - Added Image.close, context manager support. [wiredfool] From f165d2034fc97f172034cadf8c4b3aa3670ae1f3 Mon Sep 17 00:00:00 2001 From: hugovk Date: Sun, 11 May 2014 09:01:09 +0300 Subject: [PATCH 17/46] Simple test for saving to PDF --- Tests/test_file_pdf.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 Tests/test_file_pdf.py diff --git a/Tests/test_file_pdf.py b/Tests/test_file_pdf.py new file mode 100644 index 000000000..7519d270f --- /dev/null +++ b/Tests/test_file_pdf.py @@ -0,0 +1,17 @@ +from tester import * +import os.path + + +def test_to_pdf(): + # Arrange + im = lena() + outfile = tempfile("temp.pdf") + + # Act + im.save(outfile) + + # Assert + assert_true(os.path.isfile(outfile)) + assert_greater(os.path.getsize(outfile), 0) + +# End of file From c15601e0b06f5d6ebf28a0f9d6a9721fa54ed235 Mon Sep 17 00:00:00 2001 From: hugovk Date: Sun, 11 May 2014 17:16:13 +0300 Subject: [PATCH 18/46] Add some more pdf tests --- Tests/test_file_pdf.py | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/Tests/test_file_pdf.py b/Tests/test_file_pdf.py index 7519d270f..c9ab8015a 100644 --- a/Tests/test_file_pdf.py +++ b/Tests/test_file_pdf.py @@ -2,10 +2,10 @@ from tester import * import os.path -def test_to_pdf(): +def helper_save_as_pdf(mode): # Arrange - im = lena() - outfile = tempfile("temp.pdf") + im = lena(mode) + outfile = tempfile("temp_" + mode + ".pdf") # Act im.save(outfile) @@ -14,4 +14,37 @@ def test_to_pdf(): assert_true(os.path.isfile(outfile)) assert_greater(os.path.getsize(outfile), 0) + +def test_greyscale(): + # Arrange + mode = "L" + + # Act / Assert + helper_save_as_pdf(mode) + + +def test_rgb(): + # Arrange + mode = "RGB" + + # Act / Assert + helper_save_as_pdf(mode) + + +def test_p_mode(): + # Arrange + mode = "P" + + # Act / Assert + helper_save_as_pdf(mode) + + +def test_cmyk_mode(): + # Arrange + mode = "P" + + # Act / Assert + helper_save_as_pdf(mode) + + # End of file From 3e2ff13aa8866af18de64a90e52ee8b7772fd907 Mon Sep 17 00:00:00 2001 From: hugovk Date: Sun, 11 May 2014 17:23:10 +0300 Subject: [PATCH 19/46] Fix CMYK test --- Tests/test_file_pdf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/test_file_pdf.py b/Tests/test_file_pdf.py index c9ab8015a..81fd919d2 100644 --- a/Tests/test_file_pdf.py +++ b/Tests/test_file_pdf.py @@ -41,7 +41,7 @@ def test_p_mode(): def test_cmyk_mode(): # Arrange - mode = "P" + mode = "CMYK" # Act / Assert helper_save_as_pdf(mode) From 8f1a00ae92a949da0859114a970c04d8b7194bc4 Mon Sep 17 00:00:00 2001 From: hugovk Date: Sun, 11 May 2014 17:28:41 +0300 Subject: [PATCH 20/46] Temporarily remove failing P-mode PDF test --- Tests/test_file_pdf.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/Tests/test_file_pdf.py b/Tests/test_file_pdf.py index 81fd919d2..4bc70d10c 100644 --- a/Tests/test_file_pdf.py +++ b/Tests/test_file_pdf.py @@ -31,12 +31,17 @@ def test_rgb(): helper_save_as_pdf(mode) -def test_p_mode(): - # Arrange - mode = "P" - - # Act / Assert - helper_save_as_pdf(mode) +# FIXME: P-mode test fails on Python 3. +# https://travis-ci.org/hugovk/Pillow/builds/24915249 +# File "/home/travis/build/hugovk/Pillow/PIL/PdfImagePlugin.py", line 108, in _save +# colorspace = colorspace + b"> ]" +# TypeError: Can't convert 'bytes' object to str implicitly +# def test_p_mode(): +# # Arrange +# mode = "P" +# +# # Act / Assert +# helper_save_as_pdf(mode) def test_cmyk_mode(): From 6520004289648e3611d43fab7190751f18912aef Mon Sep 17 00:00:00 2001 From: hugovk Date: Sun, 11 May 2014 17:35:49 +0300 Subject: [PATCH 21/46] Add monochrome PDF test --- Tests/test_file_pdf.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Tests/test_file_pdf.py b/Tests/test_file_pdf.py index 4bc70d10c..ed6b50b5d 100644 --- a/Tests/test_file_pdf.py +++ b/Tests/test_file_pdf.py @@ -15,6 +15,14 @@ def helper_save_as_pdf(mode): assert_greater(os.path.getsize(outfile), 0) +def test_monochrome(): + # Arrange + mode = "1" + + # Act / Assert + helper_save_as_pdf(mode) + + def test_greyscale(): # Arrange mode = "L" @@ -33,9 +41,11 @@ def test_rgb(): # FIXME: P-mode test fails on Python 3. # https://travis-ci.org/hugovk/Pillow/builds/24915249 -# File "/home/travis/build/hugovk/Pillow/PIL/PdfImagePlugin.py", line 108, in _save +# File "/home/travis/build/hugovk/Pillow/PIL/PdfImagePlugin.py", line 108, +# in _save # colorspace = colorspace + b"> ]" # TypeError: Can't convert 'bytes' object to str implicitly + # def test_p_mode(): # # Arrange # mode = "P" From 741297326a030372fd8dfb6dc6e0a2ecc6dba2f8 Mon Sep 17 00:00:00 2001 From: hugovk Date: Sun, 11 May 2014 17:41:07 +0300 Subject: [PATCH 22/46] Temporarily remove 'failing' 1-mode PDF test --- Tests/test_file_pdf.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Tests/test_file_pdf.py b/Tests/test_file_pdf.py index ed6b50b5d..ddecdd75f 100644 --- a/Tests/test_file_pdf.py +++ b/Tests/test_file_pdf.py @@ -15,6 +15,12 @@ def helper_save_as_pdf(mode): assert_greater(os.path.getsize(outfile), 0) +# FIXME: 1-mode test "fails" because it produces a warning. +# https://travis-ci.org/hugovk/Pillow/builds/24916085 +# /home/travis/build/hugovk/Pillow/PIL/PdfImagePlugin.py:147: +# DeprecationWarning: tostring() is deprecated. Please call tobytes() instead. +# data = im.tostring("raw", "1") + def test_monochrome(): # Arrange mode = "1" From bcb8534dcf8ad5e8b10eece136f18062818b7071 Mon Sep 17 00:00:00 2001 From: hugovk Date: Sun, 11 May 2014 17:46:13 +0300 Subject: [PATCH 23/46] Temporarily remove 'failing' 1-mode PDF test --- Tests/test_file_pdf.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Tests/test_file_pdf.py b/Tests/test_file_pdf.py index ddecdd75f..9a4faff3f 100644 --- a/Tests/test_file_pdf.py +++ b/Tests/test_file_pdf.py @@ -20,13 +20,13 @@ def helper_save_as_pdf(mode): # /home/travis/build/hugovk/Pillow/PIL/PdfImagePlugin.py:147: # DeprecationWarning: tostring() is deprecated. Please call tobytes() instead. # data = im.tostring("raw", "1") - -def test_monochrome(): - # Arrange - mode = "1" - - # Act / Assert - helper_save_as_pdf(mode) +# +# def test_monochrome(): +# # Arrange +# mode = "1" +# +# # Act / Assert +# helper_save_as_pdf(mode) def test_greyscale(): @@ -51,7 +51,7 @@ def test_rgb(): # in _save # colorspace = colorspace + b"> ]" # TypeError: Can't convert 'bytes' object to str implicitly - +# # def test_p_mode(): # # Arrange # mode = "P" From c37aa0a9ca0db921e62ae289f7bc357b7a5aef55 Mon Sep 17 00:00:00 2001 From: hugovk Date: Mon, 12 May 2014 14:30:03 +0300 Subject: [PATCH 24/46] Fix tostring()/tobytes() warning and reinstate test --- PIL/PdfImagePlugin.py | 2 +- Tests/test_file_pdf.py | 18 ++++++------------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/PIL/PdfImagePlugin.py b/PIL/PdfImagePlugin.py index 725f22ecf..2a8a8d443 100644 --- a/PIL/PdfImagePlugin.py +++ b/PIL/PdfImagePlugin.py @@ -144,7 +144,7 @@ def _save(im, fp, filename): if bits == 1: # FIXME: the hex encoder doesn't support packed 1-bit # images; do things the hard way... - data = im.tostring("raw", "1") + data = im.tobytes("raw", "1") im = Image.new("L", (len(data), 1), None) im.putdata(data) ImageFile._save(im, op, [("hex", (0,0)+im.size, 0, im.mode)]) diff --git a/Tests/test_file_pdf.py b/Tests/test_file_pdf.py index 9a4faff3f..e31878aef 100644 --- a/Tests/test_file_pdf.py +++ b/Tests/test_file_pdf.py @@ -15,18 +15,12 @@ def helper_save_as_pdf(mode): assert_greater(os.path.getsize(outfile), 0) -# FIXME: 1-mode test "fails" because it produces a warning. -# https://travis-ci.org/hugovk/Pillow/builds/24916085 -# /home/travis/build/hugovk/Pillow/PIL/PdfImagePlugin.py:147: -# DeprecationWarning: tostring() is deprecated. Please call tobytes() instead. -# data = im.tostring("raw", "1") -# -# def test_monochrome(): -# # Arrange -# mode = "1" -# -# # Act / Assert -# helper_save_as_pdf(mode) +def test_monochrome(): + # Arrange + mode = "1" + + # Act / Assert + helper_save_as_pdf(mode) def test_greyscale(): From 8cda5170c8f1c60f5537b623883ef6a9436f2df6 Mon Sep 17 00:00:00 2001 From: hugovk Date: Mon, 12 May 2014 14:45:54 +0300 Subject: [PATCH 25/46] Fix bytes/str and reinstate test --- PIL/PdfImagePlugin.py | 2 +- Tests/test_file_pdf.py | 19 ++++++------------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/PIL/PdfImagePlugin.py b/PIL/PdfImagePlugin.py index 2a8a8d443..c89ca3ee0 100644 --- a/PIL/PdfImagePlugin.py +++ b/PIL/PdfImagePlugin.py @@ -105,7 +105,7 @@ def _save(im, fp, filename): g = i8(palette[i*3+1]) b = i8(palette[i*3+2]) colorspace = colorspace + "%02x%02x%02x " % (r, g, b) - colorspace = colorspace + b"> ]" + colorspace = colorspace + "> ]" procset = "/ImageI" # indexed color elif im.mode == "RGB": filter = "/DCTDecode" diff --git a/Tests/test_file_pdf.py b/Tests/test_file_pdf.py index e31878aef..e99f22db1 100644 --- a/Tests/test_file_pdf.py +++ b/Tests/test_file_pdf.py @@ -39,19 +39,12 @@ def test_rgb(): helper_save_as_pdf(mode) -# FIXME: P-mode test fails on Python 3. -# https://travis-ci.org/hugovk/Pillow/builds/24915249 -# File "/home/travis/build/hugovk/Pillow/PIL/PdfImagePlugin.py", line 108, -# in _save -# colorspace = colorspace + b"> ]" -# TypeError: Can't convert 'bytes' object to str implicitly -# -# def test_p_mode(): -# # Arrange -# mode = "P" -# -# # Act / Assert -# helper_save_as_pdf(mode) +def test_p_mode(): + # Arrange + mode = "P" + + # Act / Assert + helper_save_as_pdf(mode) def test_cmyk_mode(): From 3ff73688fe12373e4a4d1996962bf107b38a5e89 Mon Sep 17 00:00:00 2001 From: hugovk Date: Mon, 12 May 2014 14:56:55 +0300 Subject: [PATCH 26/46] pep8 and pyflakes --- PIL/PdfImagePlugin.py | 76 ++++++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 30 deletions(-) diff --git a/PIL/PdfImagePlugin.py b/PIL/PdfImagePlugin.py index c89ca3ee0..fcc841438 100644 --- a/PIL/PdfImagePlugin.py +++ b/PIL/PdfImagePlugin.py @@ -46,9 +46,11 @@ def _obj(fp, obj, **dict): fp.write("/%s %s\n" % (k, v)) fp.write(">>\n") + def _endobj(fp): fp.write("endobj\n") + ## # (Internal) Image save plugin for the PDF format. @@ -59,13 +61,15 @@ def _save(im, fp, filename): # make sure image data is available im.load() - xref = [0]*(5+1) # placeholders + xref = [0]*(5+1) # placeholders class TextWriter: def __init__(self, fp): self.fp = fp + def __getattr__(self, name): return getattr(self.fp, name) + def write(self, value): self.fp.write(value.encode('latin-1')) @@ -89,13 +93,13 @@ def _save(im, fp, filename): if im.mode == "1": filter = "/ASCIIHexDecode" colorspace = "/DeviceGray" - procset = "/ImageB" # grayscale + procset = "/ImageB" # grayscale bits = 1 elif im.mode == "L": filter = "/DCTDecode" # params = "<< /Predictor 15 /Columns %d >>" % (width-2) colorspace = "/DeviceGray" - procset = "/ImageB" # grayscale + procset = "/ImageB" # grayscale elif im.mode == "P": filter = "/ASCIIHexDecode" colorspace = "[ /Indexed /DeviceRGB 255 <" @@ -106,15 +110,15 @@ def _save(im, fp, filename): b = i8(palette[i*3+2]) colorspace = colorspace + "%02x%02x%02x " % (r, g, b) colorspace = colorspace + "> ]" - procset = "/ImageI" # indexed color + procset = "/ImageI" # indexed color elif im.mode == "RGB": filter = "/DCTDecode" colorspace = "/DeviceRGB" - procset = "/ImageC" # color images + procset = "/ImageC" # color images elif im.mode == "CMYK": filter = "/DCTDecode" colorspace = "/DeviceCMYK" - procset = "/ImageC" # color images + procset = "/ImageC" # color images else: raise ValueError("cannot save mode %s" % im.mode) @@ -122,17 +126,21 @@ def _save(im, fp, filename): # catalogue xref[1] = fp.tell() - _obj(fp, 1, Type = "/Catalog", - Pages = "2 0 R") + _obj( + fp, 1, + Type="/Catalog", + Pages="2 0 R") _endobj(fp) # # pages xref[2] = fp.tell() - _obj(fp, 2, Type = "/Pages", - Count = 1, - Kids = "[4 0 R]") + _obj( + fp, 2, + Type="/Pages", + Count=1, + Kids="[4 0 R]") _endobj(fp) # @@ -147,26 +155,28 @@ def _save(im, fp, filename): data = im.tobytes("raw", "1") im = Image.new("L", (len(data), 1), None) im.putdata(data) - ImageFile._save(im, op, [("hex", (0,0)+im.size, 0, im.mode)]) + ImageFile._save(im, op, [("hex", (0, 0)+im.size, 0, im.mode)]) elif filter == "/DCTDecode": Image.SAVE["JPEG"](im, op, filename) elif filter == "/FlateDecode": - ImageFile._save(im, op, [("zip", (0,0)+im.size, 0, im.mode)]) + ImageFile._save(im, op, [("zip", (0, 0)+im.size, 0, im.mode)]) elif filter == "/RunLengthDecode": - ImageFile._save(im, op, [("packbits", (0,0)+im.size, 0, im.mode)]) + ImageFile._save(im, op, [("packbits", (0, 0)+im.size, 0, im.mode)]) else: raise ValueError("unsupported PDF filter (%s)" % filter) xref[3] = fp.tell() - _obj(fp, 3, Type = "/XObject", - Subtype = "/Image", - Width = width, # * 72.0 / resolution, - Height = height, # * 72.0 / resolution, - Length = len(op.getvalue()), - Filter = filter, - BitsPerComponent = bits, - DecodeParams = params, - ColorSpace = colorspace) + _obj( + fp, 3, + Type="/XObject", + Subtype="/Image", + Width=width, # * 72.0 / resolution, + Height=height, # * 72.0 / resolution, + Length=len(op.getvalue()), + Filter=filter, + BitsPerComponent=bits, + DecodeParams=params, + ColorSpace=colorspace) fp.write("stream\n") fp.fp.write(op.getvalue()) @@ -179,11 +189,14 @@ def _save(im, fp, filename): xref[4] = fp.tell() _obj(fp, 4) - fp.write("<<\n/Type /Page\n/Parent 2 0 R\n"\ - "/Resources <<\n/ProcSet [ /PDF %s ]\n"\ - "/XObject << /image 3 0 R >>\n>>\n"\ - "/MediaBox [ 0 0 %d %d ]\n/Contents 5 0 R\n>>\n" %\ - (procset, int(width * 72.0 /resolution) , int(height * 72.0 / resolution))) + fp.write( + "<<\n/Type /Page\n/Parent 2 0 R\n" + "/Resources <<\n/ProcSet [ /PDF %s ]\n" + "/XObject << /image 3 0 R >>\n>>\n" + "/MediaBox [ 0 0 %d %d ]\n/Contents 5 0 R\n>>\n" % ( + procset, + int(width * 72.0 / resolution), + int(height * 72.0 / resolution))) _endobj(fp) # @@ -191,10 +204,13 @@ def _save(im, fp, filename): op = TextWriter(io.BytesIO()) - op.write("q %d 0 0 %d 0 0 cm /image Do Q\n" % (int(width * 72.0 / resolution), int(height * 72.0 / resolution))) + op.write( + "q %d 0 0 %d 0 0 cm /image Do Q\n" % ( + int(width * 72.0 / resolution), + int(height * 72.0 / resolution))) xref[5] = fp.tell() - _obj(fp, 5, Length = len(op.fp.getvalue())) + _obj(fp, 5, Length=len(op.fp.getvalue())) fp.write("stream\n") fp.fp.write(op.fp.getvalue()) From 41d3c386a983f3ea716c4a06f83a919485d22615 Mon Sep 17 00:00:00 2001 From: hugovk Date: Wed, 14 May 2014 08:17:49 +0300 Subject: [PATCH 27/46] Don't cover PyPy: it fails intermittently and is x5.8 slower (#640) --- .travis.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1ae6e415c..96c10d0ae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,12 +4,12 @@ notifications: irc: "chat.freenode.net#pil" python: - - "pypy" - 2.6 - 2.7 - 3.2 - 3.3 - 3.4 + - "pypy" install: - "sudo apt-get -qq install libfreetype6-dev liblcms2-dev python-qt4 ghostscript libffi-dev cmake" @@ -26,8 +26,14 @@ script: - coverage erase - python setup.py clean - python setup.py build_ext --inplace - - coverage run --append --include=PIL/* selftest.py - - python Tests/run.py --coverage + + # Don't cover PyPy: it fails intermittently and is x5.8 slower (#640) + - if [ "$TRAVIS_PYTHON_VERSION" == "pypy" ]; then python selftest.py; fi + - if [ "$TRAVIS_PYTHON_VERSION" == "pypy" ]; then python Tests/run.py; fi + + # Cover the others + - if [ "$TRAVIS_PYTHON_VERSION" != "pypy" ]; then coverage run --append --include=PIL/* selftest.py; fi + - if [ "$TRAVIS_PYTHON_VERSION" != "pypy" ]; then python Tests/run.py --coverage; fi after_success: - coverage report @@ -37,7 +43,3 @@ after_success: - pyflakes PIL/*.py - pep8 Tests/*.py - pyflakes Tests/*.py - -matrix: - allow_failures: - - python: "pypy" From 6ca9e9d70383a5be60a69387f99bb08b6847e280 Mon Sep 17 00:00:00 2001 From: hugovk Date: Wed, 14 May 2014 08:47:13 +0300 Subject: [PATCH 28/46] Keep PyPy first, it's still a little slower --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 96c10d0ae..36dae5b7a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,12 +4,12 @@ notifications: irc: "chat.freenode.net#pil" python: + - "pypy" - 2.6 - 2.7 - 3.2 - 3.3 - 3.4 - - "pypy" install: - "sudo apt-get -qq install libfreetype6-dev liblcms2-dev python-qt4 ghostscript libffi-dev cmake" From fc55580a69a56974ee0dc7929834b4cbc3a8f83a Mon Sep 17 00:00:00 2001 From: Alex Clark Date: Wed, 14 May 2014 05:59:48 -0400 Subject: [PATCH 29/46] Update --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 81e388cda..b6eb19b3a 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,9 @@ Changelog (Pillow) 2.5.0 (unreleased) ------------------ +- Clean up preprocessor cruft for Windows + [CounterPillow] + - Adjust Homebrew freetype detection logic [jacknagel] From 55b1accb42a5b2d4e1372546629ff06024863915 Mon Sep 17 00:00:00 2001 From: hugovk Date: Sat, 17 May 2014 19:08:08 +0300 Subject: [PATCH 30/46] Add (failing) test for #664 --- Tests/test_image_convert.py | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/Tests/test_image_convert.py b/Tests/test_image_convert.py index 4d40e43b2..6f170afe2 100644 --- a/Tests/test_image_convert.py +++ b/Tests/test_image_convert.py @@ -45,7 +45,7 @@ def test_16bit(): def test_16bit_workaround(): im = Image.open('Tests/images/16bit.cropped.tif') _test_float_conversion(im.convert('I')) - + def test_rgba_p(): im = lena('RGBA') im.putalpha(lena('L')) @@ -54,8 +54,8 @@ def test_rgba_p(): comparable = converted.convert('RGBA') assert_image_similar(im, comparable, 20) - -def test_trns_p(): + +def test_trns_p(): im = lena('P') im.info['transparency']=0 @@ -69,13 +69,26 @@ def test_trns_p(): rgb = im.convert('RGB') assert_equal(rgb.info['transparency'], (0,0,0)) # undone assert_no_exception(lambda: rgb.save(f)) - + + +def test_trns_p_rgba(): + # Arrange + im = lena('P') + im.info['transparency'] = 128 + + # Act + rgba = im.convert('RGBA') + + # Assert + assert_false('transparency' in rgba.info) + + def test_trns_l(): im = lena('L') im.info['transparency'] = 128 f = tempfile('temp.png') - + rgb = im.convert('RGB') assert_equal(rgb.info['transparency'], (128,128,128)) # undone assert_no_exception(lambda: rgb.save(f)) @@ -89,13 +102,13 @@ def test_trns_l(): assert_false('transparency' in p.info) assert_no_exception(lambda: p.save(f)) - + def test_trns_RGB(): im = lena('RGB') im.info['transparency'] = im.getpixel((0,0)) f = tempfile('temp.png') - + l = im.convert('L') assert_equal(l.info['transparency'], l.getpixel((0,0))) # undone assert_no_exception(lambda: l.save(f)) @@ -103,7 +116,7 @@ def test_trns_RGB(): p = im.convert('P') assert_true('transparency' in p.info) assert_no_exception(lambda: p.save(f)) - + p = assert_warning(UserWarning, lambda: im.convert('P', palette = Image.ADAPTIVE)) assert_false('transparency' in p.info) From ca7608f1d5a0d4322d185da6607fa1db2b418c0f Mon Sep 17 00:00:00 2001 From: hugovk Date: Sat, 17 May 2014 20:36:17 +0300 Subject: [PATCH 31/46] Possible fix for #664 --- PIL/Image.py | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/PIL/Image.py b/PIL/Image.py index 333397701..ec25f1027 100644 --- a/PIL/Image.py +++ b/PIL/Image.py @@ -101,7 +101,7 @@ import collections import numbers # works everywhere, win for pypy, not cpython -USE_CFFI_ACCESS = hasattr(sys, 'pypy_version_info') +USE_CFFI_ACCESS = hasattr(sys, 'pypy_version_info') try: import cffi HAS_CFFI=True @@ -233,7 +233,7 @@ _MODE_CONV = { "CMYK": ('|u1', 4), "YCbCr": ('|u1', 3), "LAB": ('|u1', 3), # UNDONE - unsigned |u1i1i1 - # I;16 == I;16L, and I;32 == I;32L + # I;16 == I;16L, and I;32 == I;32L "I;16": ('u2', None), "I;16L": (' 8bit images. + # a gamma function point transform on > 8bit images. scale, offset = _getscaleoffset(lut) return self._new(self.im.point_transform(scale, offset)) # for other modes, convert the function to a table @@ -1420,8 +1423,8 @@ class Image: self._copy() self.pyaccess = None self.load() - - if self.pyaccess: + + if self.pyaccess: return self.pyaccess.putpixel(xy,value) return self.im.putpixel(xy, value) From a59bc40c38661c92748d8be93ca2e03bdb01f613 Mon Sep 17 00:00:00 2001 From: hugovk Date: Sat, 17 May 2014 23:33:50 +0300 Subject: [PATCH 32/46] flake8 --- Tests/test_image_convert.py | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/Tests/test_image_convert.py b/Tests/test_image_convert.py index 6f170afe2..6a39b0e3b 100644 --- a/Tests/test_image_convert.py +++ b/Tests/test_image_convert.py @@ -2,6 +2,7 @@ from tester import * from PIL import Image + def test_sanity(): def convert(im, mode): @@ -16,6 +17,7 @@ def test_sanity(): for mode in modes: yield_test(convert, im, mode) + def test_default(): im = lena("P") @@ -26,26 +28,29 @@ def test_default(): assert_image(im, "RGB", im.size) - # ref https://github.com/python-imaging/Pillow/issues/274 def _test_float_conversion(im): - orig = im.getpixel((5,5)) - converted = im.convert('F').getpixel((5,5)) + orig = im.getpixel((5, 5)) + converted = im.convert('F').getpixel((5, 5)) assert_equal(orig, converted) + def test_8bit(): im = Image.open('Images/lena.jpg') _test_float_conversion(im.convert('L')) + def test_16bit(): im = Image.open('Tests/images/16bit.cropped.tif') _test_float_conversion(im) + def test_16bit_workaround(): im = Image.open('Tests/images/16bit.cropped.tif') _test_float_conversion(im.convert('I')) + def test_rgba_p(): im = lena('RGBA') im.putalpha(lena('L')) @@ -55,22 +60,24 @@ def test_rgba_p(): assert_image_similar(im, comparable, 20) + def test_trns_p(): im = lena('P') - im.info['transparency']=0 + im.info['transparency'] = 0 f = tempfile('temp.png') l = im.convert('L') - assert_equal(l.info['transparency'], 0) # undone + assert_equal(l.info['transparency'], 0) # undone assert_no_exception(lambda: l.save(f)) - rgb = im.convert('RGB') - assert_equal(rgb.info['transparency'], (0,0,0)) # undone + assert_equal(rgb.info['transparency'], (0, 0, 0)) # undone assert_no_exception(lambda: rgb.save(f)) +# ref https://github.com/python-imaging/Pillow/issues/664 + def test_trns_p_rgba(): # Arrange im = lena('P') @@ -90,7 +97,7 @@ def test_trns_l(): f = tempfile('temp.png') rgb = im.convert('RGB') - assert_equal(rgb.info['transparency'], (128,128,128)) # undone + assert_equal(rgb.info['transparency'], (128, 128, 128)) # undone assert_no_exception(lambda: rgb.save(f)) p = im.convert('P') @@ -98,19 +105,19 @@ def test_trns_l(): assert_no_exception(lambda: p.save(f)) p = assert_warning(UserWarning, - lambda: im.convert('P', palette = Image.ADAPTIVE)) + lambda: im.convert('P', palette=Image.ADAPTIVE)) assert_false('transparency' in p.info) assert_no_exception(lambda: p.save(f)) def test_trns_RGB(): im = lena('RGB') - im.info['transparency'] = im.getpixel((0,0)) + im.info['transparency'] = im.getpixel((0, 0)) f = tempfile('temp.png') l = im.convert('L') - assert_equal(l.info['transparency'], l.getpixel((0,0))) # undone + assert_equal(l.info['transparency'], l.getpixel((0, 0))) # undone assert_no_exception(lambda: l.save(f)) p = im.convert('P') @@ -118,8 +125,6 @@ def test_trns_RGB(): assert_no_exception(lambda: p.save(f)) p = assert_warning(UserWarning, - lambda: im.convert('P', palette = Image.ADAPTIVE)) + lambda: im.convert('P', palette=Image.ADAPTIVE)) assert_false('transparency' in p.info) assert_no_exception(lambda: p.save(f)) - - From 0938145e57e6d4e838f02495da80e03fd2a4cbeb Mon Sep 17 00:00:00 2001 From: hugovk Date: Mon, 19 May 2014 10:04:56 +0300 Subject: [PATCH 33/46] Move to an elif clause of the if in line 778, as it's just another combination of mode,self.mode under the master transparency condition --- PIL/Image.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/PIL/Image.py b/PIL/Image.py index ec25f1027..5d23a278a 100644 --- a/PIL/Image.py +++ b/PIL/Image.py @@ -802,7 +802,8 @@ class Image: # after quantization. trns_im = trns_im.convert('RGB') trns = trns_im.getpixel((0,0)) - + elif self.mode == 'P' and mode == 'RGBA' and 'transparency' in self.info: + delete_trns = True if mode == "P" and palette == ADAPTIVE: im = self.im.quantize(colors) @@ -837,9 +838,6 @@ class Image: except KeyError: raise ValueError("illegal conversion") - if self.mode == 'P' and mode == 'RGBA' and 'transparency' in self.info: - delete_trns = True - new_im = self._new(im) if delete_trns: #crash fail if we leave a bytes transparency in an rgb/l mode. From 88d74883bb507ca42a5f203e46b0ada8a47fc1cc Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 19 May 2014 14:12:43 -0700 Subject: [PATCH 34/46] remove redundant transparency check --- PIL/Image.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PIL/Image.py b/PIL/Image.py index 5d23a278a..08b0dbe7d 100644 --- a/PIL/Image.py +++ b/PIL/Image.py @@ -802,7 +802,7 @@ class Image: # after quantization. trns_im = trns_im.convert('RGB') trns = trns_im.getpixel((0,0)) - elif self.mode == 'P' and mode == 'RGBA' and 'transparency' in self.info: + elif self.mode == 'P' and mode == 'RGBA': delete_trns = True if mode == "P" and palette == ADAPTIVE: From a7cb81ec56107234b012e2f2859a53122045f77b Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 20 May 2014 16:42:18 +0100 Subject: [PATCH 35/46] Update CHANGES.rst --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index b6eb19b3a..8121a9519 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,9 @@ Changelog (Pillow) 2.5.0 (unreleased) ------------------ +- Remove transparency resource after P->RGBA conversion + [hugovk] + - Clean up preprocessor cruft for Windows [CounterPillow] From 9a6e8f8e9dca4587a232bf5c4395b1cad782208b Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 20 May 2014 09:21:12 -0700 Subject: [PATCH 36/46] Noted previous default --- PIL/Image.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/PIL/Image.py b/PIL/Image.py index c6ab76b6d..ec11a1866 100644 --- a/PIL/Image.py +++ b/PIL/Image.py @@ -1710,7 +1710,8 @@ class Image: of :py:attr:`PIL.Image.NEAREST`, :py:attr:`PIL.Image.BILINEAR`, :py:attr:`PIL.Image.BICUBIC`, or :py:attr:`PIL.Image.ANTIALIAS` (best quality). If omitted, it defaults to - :py:attr:`PIL.Image.ANTIALIAS`. + :py:attr:`PIL.Image.ANTIALIAS`. (was `PIL.Image.NEAREST` prior + to version 2.5.0) :returns: None """ From 6ab636fb5ac17bc844400113e69e9c0ee5cf7853 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 20 May 2014 09:27:56 -0700 Subject: [PATCH 37/46] Doc formatting fix --- PIL/Image.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PIL/Image.py b/PIL/Image.py index ec11a1866..2ef226993 100644 --- a/PIL/Image.py +++ b/PIL/Image.py @@ -1710,8 +1710,8 @@ class Image: of :py:attr:`PIL.Image.NEAREST`, :py:attr:`PIL.Image.BILINEAR`, :py:attr:`PIL.Image.BICUBIC`, or :py:attr:`PIL.Image.ANTIALIAS` (best quality). If omitted, it defaults to - :py:attr:`PIL.Image.ANTIALIAS`. (was `PIL.Image.NEAREST` prior - to version 2.5.0) + :py:attr:`PIL.Image.ANTIALIAS`. (was :py:attr:`PIL.Image.NEAREST` + prior to version 2.5.0) :returns: None """ From 24cb7bf3df6660bb2bd705b3197e97947dd40a50 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 20 May 2014 17:32:31 +0100 Subject: [PATCH 38/46] Updated changes [ci-skip] --- CHANGES.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 8121a9519..62d292f72 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,12 @@ Changelog (Pillow) 2.5.0 (unreleased) ------------------ +- Change default interpolation for Image.thumbnail to Image.ANTIALIAS + [hugovk] + +- Add tests and fixes for saving PDFs + [hugovk] + - Remove transparency resource after P->RGBA conversion [hugovk] From 9c048e44d166888b7e6a4e232ed7dafeac67b785 Mon Sep 17 00:00:00 2001 From: hugovk Date: Wed, 21 May 2014 14:30:05 +0300 Subject: [PATCH 39/46] Permission to use and distribute (under the MIT license) this image as a testfile granted by cepreu2github: https://github.com/python-imaging/Pillow/issues/630#issuecomment-43674288 --- Tests/images/junk_jpeg_header.jpg | Bin 0 -> 107466 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Tests/images/junk_jpeg_header.jpg diff --git a/Tests/images/junk_jpeg_header.jpg b/Tests/images/junk_jpeg_header.jpg new file mode 100644 index 0000000000000000000000000000000000000000..564eb3199da25fc050a53940b9c67743896a7e59 GIT binary patch literal 107466 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 JDk3QX|Jm_iy^jC@ literal 0 HcmV?d00001 From aed2646dc21e69d7d7c874778b391f866faf2833 Mon Sep 17 00:00:00 2001 From: hugovk Date: Wed, 21 May 2014 14:32:24 +0300 Subject: [PATCH 40/46] pep8/pyflakes --- Tests/test_file_jpeg.py | 63 +++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/Tests/test_file_jpeg.py b/Tests/test_file_jpeg.py index 095cad359..b5d43749b 100644 --- a/Tests/test_file_jpeg.py +++ b/Tests/test_file_jpeg.py @@ -12,17 +12,19 @@ if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs: test_file = "Images/lena.jpg" + def roundtrip(im, **options): out = BytesIO() im.save(out, "JPEG", **options) bytes = out.tell() out.seek(0) im = Image.open(out) - im.bytes = bytes # for testing only + im.bytes = bytes # for testing only return im # -------------------------------------------------------------------- + def test_sanity(): # internal version number @@ -34,6 +36,7 @@ def test_sanity(): assert_equal(im.size, (128, 128)) assert_equal(im.format, "JPEG") + # -------------------------------------------------------------------- def test_app(): @@ -44,6 +47,7 @@ def test_app(): assert_equal(im.applist[1], ("COM", b"Python Imaging Library")) assert_equal(len(im.applist), 2) + def test_cmyk(): # Test CMYK handling. Thanks to Tim and Charlie for test data, # Michael for getting me to look one more time. @@ -62,6 +66,7 @@ def test_cmyk(): c, m, y, k = [x / 255.0 for x in im.getpixel((im.size[0]-1, im.size[1]-1))] assert_true(k > 0.9) + def test_dpi(): def test(xdpi, ydpi=None): im = Image.open(test_file) @@ -70,7 +75,8 @@ def test_dpi(): assert_equal(test(72), (72, 72)) assert_equal(test(300), (300, 300)) assert_equal(test(100, 200), (100, 200)) - assert_equal(test(0), None) # square pixels + assert_equal(test(0), None) # square pixels + def test_icc(): # Test ICC support @@ -89,6 +95,7 @@ def test_icc(): assert_false(im1.info.get("icc_profile")) assert_true(im2.info.get("icc_profile")) + def test_icc_big(): # Make sure that the "extra" support handles large blocks def test(n): @@ -96,16 +103,20 @@ def test_icc_big(): # using a 4-byte test code should allow us to detect out of # order issues. icc_profile = (b"Test"*int(n/4+1))[:n] - assert len(icc_profile) == n # sanity + assert len(icc_profile) == n # sanity im1 = roundtrip(lena(), icc_profile=icc_profile) assert_equal(im1.info.get("icc_profile"), icc_profile or None) - test(0); test(1) - test(3); test(4); test(5) - test(65533-14) # full JPEG marker block - test(65533-14+1) # full block plus one byte - test(ImageFile.MAXBLOCK) # full buffer block - test(ImageFile.MAXBLOCK+1) # full buffer block plus one byte - test(ImageFile.MAXBLOCK*4+3) # large block + test(0) + test(1) + test(3) + test(4) + test(5) + test(65533-14) # full JPEG marker block + test(65533-14+1) # full block plus one byte + test(ImageFile.MAXBLOCK) # full buffer block + test(ImageFile.MAXBLOCK+1) # full buffer block plus one byte + test(ImageFile.MAXBLOCK*4+3) # large block + def test_optimize(): im1 = roundtrip(lena()) @@ -113,25 +124,29 @@ def test_optimize(): assert_image_equal(im1, im2) assert_true(im1.bytes >= im2.bytes) + def test_optimize_large_buffer(): - #https://github.com/python-imaging/Pillow/issues/148 + # https://github.com/python-imaging/Pillow/issues/148 f = tempfile('temp.jpg') # this requires ~ 1.5x Image.MAXBLOCK - im = Image.new("RGB", (4096,4096), 0xff3333) + im = Image.new("RGB", (4096, 4096), 0xff3333) im.save(f, format="JPEG", optimize=True) + def test_progressive(): im1 = roundtrip(lena()) im2 = roundtrip(lena(), progressive=True) assert_image_equal(im1, im2) assert_true(im1.bytes >= im2.bytes) + def test_progressive_large_buffer(): f = tempfile('temp.jpg') # this requires ~ 1.5x Image.MAXBLOCK - im = Image.new("RGB", (4096,4096), 0xff3333) + im = Image.new("RGB", (4096, 4096), 0xff3333) im.save(f, format="JPEG", progressive=True) + def test_progressive_large_buffer_highest_quality(): f = tempfile('temp.jpg') if py3: @@ -142,16 +157,18 @@ def test_progressive_large_buffer_highest_quality(): # this requires more bytes than pixels in the image im.save(f, format="JPEG", progressive=True, quality=100) + def test_large_exif(): - #https://github.com/python-imaging/Pillow/issues/148 + # https://github.com/python-imaging/Pillow/issues/148 f = tempfile('temp.jpg') im = lena() - im.save(f,'JPEG', quality=90, exif=b"1"*65532) + im.save(f, 'JPEG', quality=90, exif=b"1"*65532) + def test_progressive_compat(): im1 = roundtrip(lena()) im2 = roundtrip(lena(), progressive=1) - im3 = roundtrip(lena(), progression=1) # compatibility + im3 = roundtrip(lena(), progression=1) # compatibility assert_image_equal(im1, im2) assert_image_equal(im1, im3) assert_false(im1.info.get("progressive")) @@ -161,31 +178,34 @@ def test_progressive_compat(): assert_true(im3.info.get("progressive")) assert_true(im3.info.get("progression")) + def test_quality(): im1 = roundtrip(lena()) im2 = roundtrip(lena(), quality=50) assert_image(im1, im2.mode, im2.size) assert_true(im1.bytes >= im2.bytes) + def test_smooth(): im1 = roundtrip(lena()) im2 = roundtrip(lena(), smooth=100) assert_image(im1, im2.mode, im2.size) + def test_subsampling(): def getsampling(im): layer = im.layer return layer[0][1:3] + layer[1][1:3] + layer[2][1:3] # experimental API - im = roundtrip(lena(), subsampling=-1) # default + im = roundtrip(lena(), subsampling=-1) # default assert_equal(getsampling(im), (2, 2, 1, 1, 1, 1)) - im = roundtrip(lena(), subsampling=0) # 4:4:4 + im = roundtrip(lena(), subsampling=0) # 4:4:4 assert_equal(getsampling(im), (1, 1, 1, 1, 1, 1)) - im = roundtrip(lena(), subsampling=1) # 4:2:2 + im = roundtrip(lena(), subsampling=1) # 4:2:2 assert_equal(getsampling(im), (2, 1, 1, 1, 1, 1)) - im = roundtrip(lena(), subsampling=2) # 4:1:1 + im = roundtrip(lena(), subsampling=2) # 4:1:1 assert_equal(getsampling(im), (2, 2, 1, 1, 1, 1)) - im = roundtrip(lena(), subsampling=3) # default (undefined) + im = roundtrip(lena(), subsampling=3) # default (undefined) assert_equal(getsampling(im), (2, 2, 1, 1, 1, 1)) im = roundtrip(lena(), subsampling="4:4:4") @@ -197,6 +217,7 @@ def test_subsampling(): assert_exception(TypeError, lambda: roundtrip(lena(), subsampling="1:1:1")) + def test_exif(): im = Image.open("Tests/images/pil_sample_rgb.jpg") info = im._getexif() From 0c1c620e302574e3527cc1d9460acb37536c9614 Mon Sep 17 00:00:00 2001 From: hugovk Date: Wed, 21 May 2014 14:33:28 +0300 Subject: [PATCH 41/46] Add test for #647. Fails without fix. --- Tests/test_file_jpeg.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Tests/test_file_jpeg.py b/Tests/test_file_jpeg.py index b5d43749b..4871c3fbf 100644 --- a/Tests/test_file_jpeg.py +++ b/Tests/test_file_jpeg.py @@ -228,3 +228,11 @@ def test_quality_keep(): im = Image.open("Images/lena.jpg") f = tempfile('temp.jpg') assert_no_exception(lambda: im.save(f, quality='keep')) + + +def test_junk_jpeg_header(): + # https://github.com/python-imaging/Pillow/issues/630 + filename = "Tests/images/junk_jpeg_header.jpg" + assert_no_exception(lambda: Image.open(filename)) + +# End of file From 8a7974c2882cc66cfa28256fbea0d0d67d344b0e Mon Sep 17 00:00:00 2001 From: hugovk Date: Wed, 21 May 2014 14:35:29 +0300 Subject: [PATCH 42/46] Use bytes for Python 3. It's just an alias to str in Python 2. --- PIL/JpegImagePlugin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PIL/JpegImagePlugin.py b/PIL/JpegImagePlugin.py index 6f32878e5..7b40d5d4f 100644 --- a/PIL/JpegImagePlugin.py +++ b/PIL/JpegImagePlugin.py @@ -302,7 +302,7 @@ class JpegImageFile(ImageFile.ImageFile): i = i16(s) else: # Skip non-0xFF junk - s = "\xff" + s = b"\xff" continue if i in MARKER: @@ -320,7 +320,7 @@ class JpegImageFile(ImageFile.ImageFile): s = self.fp.read(1) elif i == 0 or i == 0xFFFF: # padded marker or junk; move on - s = "\xff" + s = b"\xff" else: raise SyntaxError("no marker found") From d594c0241aabeda6725fefc44ccc7f945c0464c9 Mon Sep 17 00:00:00 2001 From: hugovk Date: Wed, 21 May 2014 20:45:02 +0300 Subject: [PATCH 43/46] Rename len variables as length to avoid the built-in function name. --- PIL/PngImagePlugin.py | 78 +++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/PIL/PngImagePlugin.py b/PIL/PngImagePlugin.py index 2bdf74608..23e77f2fc 100644 --- a/PIL/PngImagePlugin.py +++ b/PIL/PngImagePlugin.py @@ -89,33 +89,33 @@ class ChunkStream: "Fetch a new chunk. Returns header information." if self.queue: - cid, pos, len = self.queue[-1] + 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() - len = i32(s) + length = i32(s) if not is_cid(cid): raise SyntaxError("broken PNG file (chunk %s)" % repr(cid)) - return cid, pos, len + return cid, pos, length def close(self): self.queue = self.crc = self.fp = None - def push(self, cid, pos, len): + def push(self, cid, pos, length): - self.queue.append((cid, pos, len)) + self.queue.append((cid, pos, length)) - def call(self, cid, pos, len): + def call(self, cid, pos, length): "Call the appropriate chunk handler" if Image.DEBUG: - print("STREAM", cid, pos, len) - return getattr(self, "chunk_" + cid.decode('ascii'))(pos, len) + print("STREAM", cid, pos, length) + return getattr(self, "chunk_" + cid.decode('ascii'))(pos, length) def crc(self, cid, data): "Read and verify checksum" @@ -139,10 +139,10 @@ class ChunkStream: cids = [] while True: - cid, pos, len = self.read() + cid, pos, length = self.read() if cid == endchunk: break - self.crc(cid, ImageFile._safe_read(self.fp, len)) + self.crc(cid, ImageFile._safe_read(self.fp, length)) cids.append(cid) return cids @@ -190,10 +190,10 @@ class PngStream(ChunkStream): self.im_tile = None self.im_palette = None - def chunk_iCCP(self, pos, len): + def chunk_iCCP(self, pos, length): # ICC profile - s = ImageFile._safe_read(self.fp, len) + s = ImageFile._safe_read(self.fp, length) # according to PNG spec, the iCCP chunk contains: # Profile name 1-79 bytes (character string) # Null separator 1 byte (null character) @@ -213,10 +213,10 @@ class PngStream(ChunkStream): self.im_info["icc_profile"] = icc_profile return s - def chunk_IHDR(self, pos, len): + def chunk_IHDR(self, pos, length): # image header - s = ImageFile._safe_read(self.fp, len) + s = ImageFile._safe_read(self.fp, length) self.im_size = i32(s), i32(s[4:]) try: self.im_mode, self.im_rawmode = _MODES[(i8(s[8]), i8(s[9]))] @@ -228,30 +228,30 @@ class PngStream(ChunkStream): raise SyntaxError("unknown filter category") return s - def chunk_IDAT(self, pos, len): + def chunk_IDAT(self, pos, length): # image data self.im_tile = [("zip", (0,0)+self.im_size, pos, self.im_rawmode)] - self.im_idat = len + self.im_idat = length raise EOFError - def chunk_IEND(self, pos, len): + def chunk_IEND(self, pos, length): # end of PNG image raise EOFError - def chunk_PLTE(self, pos, len): + def chunk_PLTE(self, pos, length): # palette - s = ImageFile._safe_read(self.fp, len) + s = ImageFile._safe_read(self.fp, length) if self.im_mode == "P": self.im_palette = "RGB", s return s - def chunk_tRNS(self, pos, len): + def chunk_tRNS(self, pos, length): # transparency - s = ImageFile._safe_read(self.fp, len) + s = ImageFile._safe_read(self.fp, length) if self.im_mode == "P": if _simple_palette.match(s): i = s.find(b"\0") @@ -265,17 +265,17 @@ class PngStream(ChunkStream): self.im_info["transparency"] = i16(s), i16(s[2:]), i16(s[4:]) return s - def chunk_gAMA(self, pos, len): + def chunk_gAMA(self, pos, length): # gamma setting - s = ImageFile._safe_read(self.fp, len) + s = ImageFile._safe_read(self.fp, length) self.im_info["gamma"] = i32(s) / 100000.0 return s - def chunk_pHYs(self, pos, len): + def chunk_pHYs(self, pos, length): # pixels per unit - s = ImageFile._safe_read(self.fp, len) + s = ImageFile._safe_read(self.fp, length) px, py = i32(s), i32(s[4:]) unit = i8(s[8]) if unit == 1: # meter @@ -285,10 +285,10 @@ class PngStream(ChunkStream): self.im_info["aspect"] = px, py return s - def chunk_tEXt(self, pos, len): + def chunk_tEXt(self, pos, length): # text - s = ImageFile._safe_read(self.fp, len) + s = ImageFile._safe_read(self.fp, length) try: k, v = s.split(b"\0", 1) except ValueError: @@ -301,10 +301,10 @@ class PngStream(ChunkStream): self.im_info[k] = self.im_text[k] = v return s - def chunk_zTXt(self, pos, len): + def chunk_zTXt(self, pos, length): # compressed text - s = ImageFile._safe_read(self.fp, len) + s = ImageFile._safe_read(self.fp, length) try: k, v = s.split(b"\0", 1) except ValueError: @@ -358,16 +358,16 @@ class PngImageFile(ImageFile.ImageFile): # # get next chunk - cid, pos, len = self.png.read() + cid, pos, length = self.png.read() try: - s = self.png.call(cid, pos, len) + s = self.png.call(cid, pos, length) except EOFError: break except AttributeError: if Image.DEBUG: - print(cid, pos, len, "(unknown)") - s = ImageFile._safe_read(self.fp, len) + print(cid, pos, length, "(unknown)") + s = ImageFile._safe_read(self.fp, length) self.png.crc(cid, s) @@ -388,7 +388,7 @@ class PngImageFile(ImageFile.ImageFile): rawmode, data = self.png.im_palette self.palette = ImagePalette.raw(rawmode, data) - self.__idat = len # used by load_read() + self.__idat = length # used by load_read() def verify(self): @@ -421,13 +421,13 @@ class PngImageFile(ImageFile.ImageFile): self.fp.read(4) # CRC - cid, pos, len = self.png.read() + cid, pos, length = self.png.read() if cid not in [b"IDAT", b"DDAT"]: - self.png.push(cid, pos, len) + self.png.push(cid, pos, length) return b"" - self.__idat = len # empty chunks are allowed + self.__idat = length # empty chunks are allowed # read more data from this chunk if bytes <= 0: @@ -560,7 +560,7 @@ def _save(im, fp, filename, chunk=putchunk, check=0): chunk(fp, b"PLTE", palette_bytes) transparency = im.encoderinfo.get('transparency',im.info.get('transparency', None)) - + if transparency or transparency == 0: if im.mode == "P": # limit to actual palette size @@ -580,7 +580,7 @@ def _save(im, fp, filename, chunk=putchunk, check=0): else: if "transparency" in im.encoderinfo: # don't bother with transparency if it's an RGBA - # and it's in the info dict. It's probably just stale. + # and it's in the info dict. It's probably just stale. raise IOError("cannot use transparency for this mode") else: if im.mode == "P" and im.im.getpalettemode() == "RGBA": From 14c2f86873777f0a74ab5217bac75f5bbd10409b Mon Sep 17 00:00:00 2001 From: hugovk Date: Wed, 21 May 2014 21:33:49 +0300 Subject: [PATCH 44/46] Rename bytes variable as read_bytes to avoid the built-in function name. --- PIL/PngImagePlugin.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/PIL/PngImagePlugin.py b/PIL/PngImagePlugin.py index 23e77f2fc..e794ef702 100644 --- a/PIL/PngImagePlugin.py +++ b/PIL/PngImagePlugin.py @@ -413,7 +413,7 @@ class PngImageFile(ImageFile.ImageFile): ImageFile.ImageFile.load_prepare(self) - def load_read(self, bytes): + def load_read(self, read_bytes): "internal: read more image data" while self.__idat == 0: @@ -430,14 +430,14 @@ class PngImageFile(ImageFile.ImageFile): self.__idat = length # empty chunks are allowed # read more data from this chunk - if bytes <= 0: - bytes = self.__idat + if read_bytes <= 0: + read_bytes = self.__idat else: - bytes = min(bytes, self.__idat) + read_bytes = min(read_bytes, self.__idat) - self.__idat = self.__idat - bytes + self.__idat = self.__idat - read_bytes - return self.fp.read(bytes) + return self.fp.read(read_bytes) def load_end(self): From de28007585eca582a1648ed59af93fffe611ef88 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Fri, 23 May 2014 00:07:58 +0100 Subject: [PATCH 45/46] Update CHANGES.rst [ci-skip] --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 62d292f72..5c268b804 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,9 @@ Changelog (Pillow) 2.5.0 (unreleased) ------------------ +- Ignore junk JPEG markers + [hugovk] + - Change default interpolation for Image.thumbnail to Image.ANTIALIAS [hugovk] From b3dcf849b8b9b828510f0e2236dbeb04487d4d3f Mon Sep 17 00:00:00 2001 From: wiredfool Date: Sat, 24 May 2014 12:46:55 +0100 Subject: [PATCH 46/46] Update --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 5c268b804..3964b798d 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,9 @@ Changelog (Pillow) 2.5.0 (unreleased) ------------------ +- Rename variables not to use built-in function names + [hugovk] + - Ignore junk JPEG markers [hugovk]