diff --git a/.travis.yml b/.travis.yml index 1ae6e415c..36dae5b7a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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" diff --git a/CHANGES.rst b/CHANGES.rst index c774a6ddf..8121a9519 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,15 @@ Changelog (Pillow) 2.5.0 (unreleased) ------------------ +- Remove transparency resource after P->RGBA conversion + [hugovk] + +- Clean up preprocessor cruft for Windows + [CounterPillow] + +- Adjust Homebrew freetype detection logic + [jacknagel] + - Added Image.close, context manager support. [wiredfool] diff --git a/PIL/Image.py b/PIL/Image.py index 80b7258c6..c6ab76b6d 100644 --- a/PIL/Image.py +++ b/PIL/Image.py @@ -818,7 +818,10 @@ class Image: # can't just retrieve the palette number, got to do it # after quantization. trns_im = trns_im.convert('RGB') - trns = trns_im.getpixel((0, 0)) + trns = trns_im.getpixel((0,0)) + + elif self.mode == 'P' and mode == 'RGBA': + delete_trns = True if mode == "P" and palette == ADAPTIVE: im = self.im.quantize(colors) diff --git a/Tests/test_image_convert.py b/Tests/test_image_convert.py index 4d40e43b2..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')) @@ -54,30 +59,45 @@ 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 + 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') + 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_equal(rgb.info['transparency'], (128, 128, 128)) # undone assert_no_exception(lambda: rgb.save(f)) p = im.convert('P') @@ -85,28 +105,26 @@ 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') assert_true('transparency' in p.info) 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)) - - 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/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/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 7fc5cbdca..92c126a10 100644 --- a/libImaging/ImPlatform.h +++ b/libImaging/ImPlatform.h @@ -17,26 +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' */ +#if defined(_MSC_VER) && !defined(__GNUC__) +#define inline __inline #endif -#if defined(_MSC_VER) -#define inline __inline -#elif !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 @@ -61,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/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; 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) 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])