diff --git a/.codecov.yml b/.codecov.yml index d348345dc..060b2685e 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -3,7 +3,7 @@ codecov: # Avoid "Missing base report" due to committing CHANGES.rst with "[CI skip]" # https://github.com/codecov/support/issues/363 - # https://docs.codecov.io/v4.3.6/docs/comparing-commits + # https://docs.codecov.io/docs/comparing-commits allow_coverage_offsets: true token: 6dafc396-e7f5-4221-a38a-8b07a49fbdae diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 195ea3865..576b88414 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -20,6 +20,9 @@ jobs: with: python-version: ${{ matrix.python-version }} + - name: Build system information + run: python .github/workflows/system-info.py + - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/.github/workflows/system-info.py b/.github/workflows/system-info.py new file mode 100644 index 000000000..8e840319a --- /dev/null +++ b/.github/workflows/system-info.py @@ -0,0 +1,25 @@ +""" +Print out some handy system info like Travis CI does. + +This sort of info is missing from GitHub Actions. + +Requested here: +https://github.com/actions/virtual-environments/issues/79 +""" +import os +import platform +import sys + +print("Build system information") +print() + +print("sys.version\t\t", sys.version.split("\n")) +print("os.name\t\t\t", os.name) +print("sys.platform\t\t", sys.platform) +print("platform.system()\t", platform.system()) +print("platform.machine()\t", platform.machine()) +print("platform.platform()\t", platform.platform()) +print("platform.version()\t", platform.version()) +print("platform.uname()\t", platform.uname()) +if sys.platform == "darwin": + print("platform.mac_ver()\t", platform.mac_ver()) diff --git a/.github/workflows/test-docker.yml b/.github/workflows/test-docker.yml index 4121eb5e9..3e8a416a5 100644 --- a/.github/workflows/test-docker.yml +++ b/.github/workflows/test-docker.yml @@ -29,6 +29,9 @@ jobs: steps: - uses: actions/checkout@v1 + - name: Build system information + run: python .github/workflows/system-info.py + - name: Docker pull run: | docker pull pythonpillow/${{ matrix.docker }}:${{ matrix.dockerTag }} diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index 00cae9bc2..e0c55bc1a 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -70,6 +70,9 @@ jobs: python-version: ${{ matrix.python-version }} architecture: ${{ matrix.architecture }} + - name: Build system information + run: python .github/workflows/system-info.py + - name: pip install wheel pytest pytest-cov run: | "%pythonLocation%\python.exe" -m pip install wheel pytest pytest-cov diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 69ed445a6..78307b7a1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -55,6 +55,9 @@ jobs: with: python-version: ${{ matrix.python-version }} + - name: Build system information + run: python .github/workflows/system-info.py + - name: Install Linux dependencies if: startsWith(matrix.os, 'ubuntu') run: | diff --git a/CHANGES.rst b/CHANGES.rst index 5af03f281..c1eab0c2e 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,15 @@ Changelog (Pillow) 7.0.0 (unreleased) ------------------ +- Better thumbnail aspect ratio preservation #4256 + [homm] + +- Add La mode packing and unpacking #4248 + [homm] + +- Include tests in coverage reports #4173 + [hugovk] + - Handle broken Photoshop data #4239 [radarhere] diff --git a/Tests/test_image_thumbnail.py b/Tests/test_image_thumbnail.py index d1224f075..5806e2a08 100644 --- a/Tests/test_image_thumbnail.py +++ b/Tests/test_image_thumbnail.py @@ -5,37 +5,48 @@ from .helper import PillowTestCase, hopper class TestImageThumbnail(PillowTestCase): def test_sanity(self): - im = hopper() - im.thumbnail((100, 100)) + self.assertIsNone(im.thumbnail((100, 100))) - self.assert_image(im, im.mode, (100, 100)) + self.assertEqual(im.size, (100, 100)) def test_aspect(self): - - im = hopper() + im = Image.new("L", (128, 128)) im.thumbnail((100, 100)) - self.assert_image(im, im.mode, (100, 100)) + self.assertEqual(im.size, (100, 100)) - im = hopper().resize((128, 256)) + im = Image.new("L", (128, 256)) im.thumbnail((100, 100)) - self.assert_image(im, im.mode, (50, 100)) + self.assertEqual(im.size, (50, 100)) - im = hopper().resize((128, 256)) + im = Image.new("L", (128, 256)) im.thumbnail((50, 100)) - self.assert_image(im, im.mode, (50, 100)) + self.assertEqual(im.size, (50, 100)) - im = hopper().resize((256, 128)) + im = Image.new("L", (256, 128)) im.thumbnail((100, 100)) - self.assert_image(im, im.mode, (100, 50)) + self.assertEqual(im.size, (100, 50)) - im = hopper().resize((256, 128)) + im = Image.new("L", (256, 128)) im.thumbnail((100, 50)) - self.assert_image(im, im.mode, (100, 50)) + self.assertEqual(im.size, (100, 50)) - im = hopper().resize((128, 128)) + im = Image.new("L", (128, 128)) im.thumbnail((100, 100)) - self.assert_image(im, im.mode, (100, 100)) + self.assertEqual(im.size, (100, 100)) + + im = Image.new("L", (256, 162)) # ratio is 1.5802469136 + im.thumbnail((33, 33)) + self.assertEqual(im.size, (33, 21)) # ratio is 1.5714285714 + + im = Image.new("L", (162, 256)) # ratio is 0.6328125 + im.thumbnail((33, 33)) + self.assertEqual(im.size, (21, 33)) # ratio is 0.6363636364 + + def test_float(self): + im = Image.new("L", (128, 128)) + im.thumbnail((99.9, 99.9)) + self.assertEqual(im.size, (100, 100)) def test_no_resize(self): # Check that draft() can resize the image to the destination size @@ -46,4 +57,4 @@ class TestImageThumbnail(PillowTestCase): # Test thumbnail(), where only draft() is necessary to resize the image with Image.open("Tests/images/hopper.jpg") as im: im.thumbnail((64, 64)) - self.assert_image(im, im.mode, (64, 64)) + self.assertEqual(im.size, (64, 64)) diff --git a/depends/termux.sh b/depends/termux.sh index f117790c5..1acc09c44 100755 --- a/depends/termux.sh +++ b/depends/termux.sh @@ -1,5 +1,5 @@ #!/bin/sh -pkg -y install python python-dev ndk-sysroot clang make \ - libjpeg-turbo-dev +pkg install -y python ndk-sysroot clang make \ + libjpeg-turbo diff --git a/docs/handbook/concepts.rst b/docs/handbook/concepts.rst index 7e782e743..e4a720a08 100644 --- a/docs/handbook/concepts.rst +++ b/docs/handbook/concepts.rst @@ -169,15 +169,15 @@ Filters comparison table | Filter | Downscaling | Upscaling | Performance | | | quality | quality | | +============+=============+===========+=============+ -|``NEAREST`` | | | ⭐⭐⭐⭐⭐ | +|``NEAREST`` | | | ⭐⭐⭐⭐⭐ | +------------+-------------+-----------+-------------+ -|``BOX`` | ⭐ | | ⭐⭐⭐⭐ | +|``BOX`` | ⭐ | | ⭐⭐⭐⭐ | +------------+-------------+-----------+-------------+ -|``BILINEAR``| ⭐ | ⭐ | ⭐⭐⭐ | +|``BILINEAR``| ⭐ | ⭐ | ⭐⭐⭐ | +------------+-------------+-----------+-------------+ -|``HAMMING`` | ⭐⭐ | | ⭐⭐⭐ | +|``HAMMING`` | ⭐⭐ | | ⭐⭐⭐ | +------------+-------------+-----------+-------------+ -|``BICUBIC`` | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ | +|``BICUBIC`` | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ | +------------+-------------+-----------+-------------+ -|``LANCZOS`` | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐ | +|``LANCZOS`` | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐ | +------------+-------------+-----------+-------------+ diff --git a/docs/installation.rst b/docs/installation.rst index 56ab8f0a3..3ec0b7b58 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -15,24 +15,25 @@ Notes .. note:: Pillow is supported on the following Python versions + +-------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+ -|**Python** |**2.4**|**2.5**|**2.6**|**2.7**|**3.2**|**3.3**|**3.4**|**3.5**|**3.6**|**3.7**|**3.8**| +|**Python** |**3.8**|**3.7**|**3.6**|**3.5**|**3.4**|**3.3**|**3.2**|**2.7**|**2.6**|**2.5**|**2.4**| +-------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+ -|Pillow < 2 | Yes | Yes | Yes | Yes | | | | | | | | +|Pillow >= 7 | Yes | Yes | Yes | Yes | | | | | | | | +-------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+ -|Pillow 2 - 3 | | | Yes | Yes | Yes | Yes | Yes | Yes | | | | +|Pillow 6.2.1 | Yes | Yes | Yes | Yes | | | | Yes | | | | +-------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+ -|Pillow 4 | | | | Yes | | Yes | Yes | Yes | Yes | | | +|Pillow 6.0 - 6.2.0 | | Yes | Yes | Yes | | | | Yes | | | | +-------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+ -|Pillow 5.0 - 5.1 | | | | Yes | | | Yes | Yes | Yes | | | +|Pillow 5.2 - 5.4 | | Yes | Yes | Yes | Yes | | | Yes | | | | +-------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+ -|Pillow 5.2 - 5.4 | | | | Yes | | | Yes | Yes | Yes | Yes | | +|Pillow 5.0 - 5.1 | | | Yes | Yes | Yes | | | Yes | | | | +-------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+ -|Pillow 6.0 - 6.2.0 | | | | Yes | | | | Yes | Yes | Yes | | +|Pillow 4 | | | Yes | Yes | Yes | Yes | | Yes | | | | +-------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+ -|Pillow 6.2.1 | | | | Yes | | | | Yes | Yes | Yes | Yes | +|Pillow 2 - 3 | | | | Yes | Yes | Yes | Yes | Yes | Yes | | | +-------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+ -|Pillow >= 7 | | | | | | | | Yes | Yes | Yes | Yes | +|Pillow < 2 | | | | | | | | Yes | Yes | Yes | Yes | +-------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+ Basic Installation @@ -190,7 +191,7 @@ Many of Pillow's features require external libraries: libraqm. * libraqm is dynamically loaded in Pillow 5.0.0 and above, so support is available if all the libraries are installed. - * Windows support: Raqm support is currently unsupported on Windows. + * Windows support: Raqm is not included in prebuilt wheels Once you have installed the prerequisites, run:: @@ -364,8 +365,8 @@ Building on Android Basic Android support has been added for compilation within the Termux environment. The dependencies can be installed by:: - pkg -y install python python-dev ndk-sysroot clang make \ - libjpeg-turbo-dev + pkg install -y python ndk-sysroot clang make \ + libjpeg-turbo This has been tested within the Termux app on ChromeOS, on x86. @@ -413,10 +414,14 @@ These platforms are built and tested for every change. +----------------------------------+--------------------------+-----------------------+ | Ubuntu Linux 16.04 LTS | 3.5, 3.6, 3.7, 3.8, PyPy3|x86-64 | +----------------------------------+--------------------------+-----------------------+ -| Windows Server 2012 R2 | 3.5, 3.6, 3.7, 3.8 |x86, x86-64 | +| Windows Server 2012 R2 | 3.5, 3.8 |x86, x86-64 | | +--------------------------+-----------------------+ | | PyPy3, 3.7/MinGW |x86 | +----------------------------------+--------------------------+-----------------------+ +| Windows Server 2019 | 3.5, 3.6, 3.7, 3.8 |x86, x86-64 | +| +--------------------------+-----------------------+ +| | PyPy3 |x86 | ++----------------------------------+--------------------------+-----------------------+ Other Platforms diff --git a/src/PIL/Image.py b/src/PIL/Image.py index 96ec314bc..981c8c818 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -2137,11 +2137,11 @@ class Image: # preserve aspect ratio x, y = self.size if x > size[0]: - y = int(max(y * size[0] / x, 1)) - x = int(size[0]) + y = max(round(y * size[0] / x), 1) + x = round(size[0]) if y > size[1]: - x = int(max(x * size[1] / y, 1)) - y = int(size[1]) + x = max(round(x * size[1] / y), 1) + y = round(size[1]) size = x, y if size == self.size: