Merge branch 'main' into tiff
|
@ -21,9 +21,11 @@ environment:
|
|||
install:
|
||||
- '%PYTHON%\%EXECUTABLE% --version'
|
||||
- curl -fsSL -o pillow-depends.zip https://github.com/python-pillow/pillow-depends/archive/main.zip
|
||||
- curl -fsSL -o pillow-test-images.zip https://github.com/python-pillow/test-images/archive/main.zip
|
||||
- 7z x pillow-depends.zip -oc:\
|
||||
- 7z x pillow-test-images.zip -oc:\
|
||||
- mv c:\pillow-depends-main c:\pillow-depends
|
||||
- xcopy /S /Y c:\pillow-depends\test_images\* c:\pillow\tests\images
|
||||
- xcopy /S /Y c:\test-images-main\* c:\pillow\tests\images
|
||||
- 7z x ..\pillow-depends\nasm-2.15.05-win64.zip -oc:\
|
||||
- ..\pillow-depends\gs1000w32.exe /S
|
||||
- path c:\nasm-2.15.05;C:\Program Files (x86)\gs\gs10.0.0\bin;%PATH%
|
||||
|
|
|
@ -37,7 +37,8 @@ python3 -m pip install -U pytest-timeout
|
|||
python3 -m pip install pyroma
|
||||
|
||||
if [[ $(uname) != CYGWIN* ]]; then
|
||||
python3 -m pip install numpy
|
||||
# TODO Remove condition when NumPy supports 3.12
|
||||
if ! [ "$GHA_PYTHON_VERSION" == "3.12-dev" ]; then python3 -m pip install numpy ; fi
|
||||
|
||||
# PyQt6 doesn't support PyPy3
|
||||
if [[ $GHA_PYTHON_VERSION == 3.* ]]; then
|
||||
|
|
4
.github/workflows/cifuzz.yml
vendored
|
@ -3,10 +3,12 @@ name: CIFuzz
|
|||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".github/workflows/cifuzz.yml"
|
||||
- "**.c"
|
||||
- "**.h"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/cifuzz.yml"
|
||||
- "**.c"
|
||||
- "**.h"
|
||||
workflow_dispatch:
|
||||
|
@ -14,7 +16,7 @@ on:
|
|||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
|
|
52
.github/workflows/docs.yml
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
name: Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".github/workflows/docs.yml"
|
||||
- "docs/**"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/docs.yml"
|
||||
- "docs/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
name: Docs
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.x"
|
||||
cache: pip
|
||||
cache-dependency-path: ".ci/*.sh"
|
||||
|
||||
- name: Build system information
|
||||
run: python3 .github/workflows/system-info.py
|
||||
|
||||
- name: Install Linux dependencies
|
||||
run: |
|
||||
.ci/install.sh
|
||||
env:
|
||||
GHA_PYTHON_VERSION: "3.x"
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
.ci/build.sh
|
||||
|
||||
- name: Docs
|
||||
run: |
|
||||
make doccheck
|
3
.github/workflows/macos-install.sh
vendored
|
@ -13,7 +13,8 @@ python3 -m pip install -U pytest-cov
|
|||
python3 -m pip install -U pytest-timeout
|
||||
python3 -m pip install pyroma
|
||||
|
||||
python3 -m pip install numpy
|
||||
# TODO Remove condition when NumPy supports 3.12
|
||||
if ! [ "$GHA_PYTHON_VERSION" == "3.12-dev" ]; then python3 -m pip install numpy ; fi
|
||||
|
||||
# extra test images
|
||||
pushd depends && ./install_extra_test_images.sh && popd
|
||||
|
|
39
.github/workflows/test-cygwin.yml
vendored
|
@ -1,6 +1,15 @@
|
|||
name: Test Cygwin
|
||||
|
||||
on: [push, pull_request, workflow_dispatch]
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- "docs/**"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- "docs/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
@ -34,18 +43,34 @@ jobs:
|
|||
with:
|
||||
platform: x86_64
|
||||
packages: >
|
||||
ImageMagick gcc-g++ ghostscript jpeg libfreetype-devel
|
||||
libimagequant-devel libjpeg-devel liblapack-devel
|
||||
liblcms2-devel libopenjp2-devel libraqm-devel
|
||||
libtiff-devel libwebp-devel libxcb-devel libxcb-xinerama0
|
||||
make netpbm perl
|
||||
gcc-g++
|
||||
ghostscript
|
||||
ImageMagick
|
||||
jpeg
|
||||
libfreetype-devel
|
||||
libimagequant-devel
|
||||
libjpeg-devel
|
||||
liblapack-devel
|
||||
liblcms2-devel
|
||||
libopenjp2-devel
|
||||
libraqm-devel
|
||||
libtiff-devel
|
||||
libwebp-devel
|
||||
libxcb-devel
|
||||
libxcb-xinerama0
|
||||
make
|
||||
netpbm
|
||||
perl
|
||||
python3${{ matrix.python-minor-version }}-cffi
|
||||
python3${{ matrix.python-minor-version }}-cython
|
||||
python3${{ matrix.python-minor-version }}-devel
|
||||
python3${{ matrix.python-minor-version }}-numpy
|
||||
python3${{ matrix.python-minor-version }}-sip
|
||||
python3${{ matrix.python-minor-version }}-tkinter
|
||||
qt5-devel-tools subversion xorg-server-extra zlib-devel
|
||||
qt5-devel-tools
|
||||
wget
|
||||
xorg-server-extra
|
||||
zlib-devel
|
||||
|
||||
- name: Add Lapack to PATH
|
||||
uses: egor-tensin/cleanup-path@v3
|
||||
|
|
12
.github/workflows/test-docker.yml
vendored
|
@ -1,6 +1,15 @@
|
|||
name: Test Docker
|
||||
|
||||
on: [push, pull_request, workflow_dispatch]
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- "docs/**"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- "docs/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
@ -87,6 +96,7 @@ jobs:
|
|||
with:
|
||||
flags: GHA_Docker
|
||||
name: ${{ matrix.docker }}
|
||||
gcov: true
|
||||
|
||||
success:
|
||||
permissions:
|
||||
|
|
22
.github/workflows/test-mingw.yml
vendored
|
@ -1,6 +1,15 @@
|
|||
name: Test MinGW
|
||||
|
||||
on: [push, pull_request, workflow_dispatch]
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- "docs/**"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- "docs/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
@ -45,11 +54,6 @@ jobs:
|
|||
- name: Install dependencies
|
||||
run: |
|
||||
pacman -S --noconfirm \
|
||||
${{ matrix.package }}-python3-cffi \
|
||||
${{ matrix.package }}-python3-numpy \
|
||||
${{ matrix.package }}-python3-olefile \
|
||||
${{ matrix.package }}-python3-pip \
|
||||
${{ matrix.package }}-python3-setuptools \
|
||||
${{ matrix.package }}-freetype \
|
||||
${{ matrix.package }}-gcc \
|
||||
${{ matrix.package }}-ghostscript \
|
||||
|
@ -60,7 +64,11 @@ jobs:
|
|||
${{ matrix.package }}-libtiff \
|
||||
${{ matrix.package }}-libwebp \
|
||||
${{ matrix.package }}-openjpeg2 \
|
||||
subversion
|
||||
${{ matrix.package }}-python3-cffi \
|
||||
${{ matrix.package }}-python3-numpy \
|
||||
${{ matrix.package }}-python3-olefile \
|
||||
${{ matrix.package }}-python3-pip \
|
||||
${{ matrix.package }}-python3-setuptools
|
||||
|
||||
if [ ${{ matrix.package }} == "mingw-w64-x86_64" ]; then
|
||||
pacman -S --noconfirm \
|
||||
|
|
4
.github/workflows/test-valgrind.yml
vendored
|
@ -5,10 +5,12 @@ name: Test Valgrind
|
|||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".github/workflows/test-valgrind.yml"
|
||||
- "**.c"
|
||||
- "**.h"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/test-valgrind.yml"
|
||||
- "**.c"
|
||||
- "**.h"
|
||||
workflow_dispatch:
|
||||
|
@ -16,7 +18,7 @@ on:
|
|||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
|
|
22
.github/workflows/test-windows.yml
vendored
|
@ -1,6 +1,15 @@
|
|||
name: Test Windows
|
||||
|
||||
on: [push, pull_request, workflow_dispatch]
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- "docs/**"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- "docs/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
@ -15,7 +24,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
|
||||
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12-dev"]
|
||||
architecture: ["x86", "x64"]
|
||||
include:
|
||||
# PyPy 7.3.4+ only ships 64-bit binaries for Windows
|
||||
|
@ -38,6 +47,12 @@ jobs:
|
|||
repository: python-pillow/pillow-depends
|
||||
path: winbuild\depends
|
||||
|
||||
- name: Checkout extra test images
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: python-pillow/test-images
|
||||
path: Tests\test-images
|
||||
|
||||
# sets env: pythonLocation
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
|
@ -62,7 +77,8 @@ jobs:
|
|||
winbuild\depends\gs1000w32.exe /S
|
||||
echo "C:\Program Files (x86)\gs\gs10.0.0\bin" >> $env:GITHUB_PATH
|
||||
|
||||
xcopy /S /Y winbuild\depends\test_images\* Tests\images\
|
||||
# Install extra test images
|
||||
xcopy /S /Y Tests\test-images\* Tests\images
|
||||
|
||||
# make cache key depend on VS version
|
||||
& "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" `
|
||||
|
|
19
.github/workflows/test.yml
vendored
|
@ -1,6 +1,15 @@
|
|||
name: Test
|
||||
|
||||
on: [push, pull_request, workflow_dispatch]
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- "docs/**"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- "docs/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
@ -22,6 +31,7 @@ jobs:
|
|||
python-version: [
|
||||
"pypy3.9",
|
||||
"pypy3.8",
|
||||
"3.12-dev",
|
||||
"3.11",
|
||||
"3.10",
|
||||
"3.9",
|
||||
|
@ -95,11 +105,6 @@ jobs:
|
|||
name: errors
|
||||
path: Tests/errors
|
||||
|
||||
- name: Docs
|
||||
if: startsWith(matrix.os, 'ubuntu') && matrix.python-version == 3.11
|
||||
run: |
|
||||
make doccheck
|
||||
|
||||
- name: After success
|
||||
run: |
|
||||
.ci/after_success.sh
|
||||
|
@ -107,9 +112,9 @@ jobs:
|
|||
- name: Upload coverage
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
file: ./coverage.xml
|
||||
flags: ${{ matrix.os == 'macos-latest' && 'GHA_macOS' || 'GHA_Ubuntu' }}
|
||||
name: ${{ matrix.os }} Python ${{ matrix.python-version }}
|
||||
gcov: true
|
||||
|
||||
success:
|
||||
permissions:
|
||||
|
|
2
.gitignore
vendored
|
@ -79,7 +79,7 @@ docs/_build/
|
|||
# JetBrains
|
||||
.idea
|
||||
|
||||
# Extra test images installed from pillow-depends/test_images
|
||||
# Extra test images installed from python-pillow/test-images
|
||||
Tests/images/README.md
|
||||
Tests/images/crash_1.tif
|
||||
Tests/images/crash_2.tif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
repos:
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 22.12.0
|
||||
rev: 23.1.0
|
||||
hooks:
|
||||
- id: black
|
||||
args: [--target-version=py37]
|
||||
|
@ -9,7 +9,7 @@ repos:
|
|||
types: []
|
||||
|
||||
- repo: https://github.com/PyCQA/isort
|
||||
rev: 5.11.4
|
||||
rev: 5.12.0
|
||||
hooks:
|
||||
- id: isort
|
||||
|
||||
|
@ -26,7 +26,7 @@ repos:
|
|||
- id: yesqa
|
||||
|
||||
- repo: https://github.com/Lucas-C/pre-commit-hooks
|
||||
rev: v1.3.1
|
||||
rev: v1.4.2
|
||||
hooks:
|
||||
- id: remove-tabs
|
||||
exclude: (Makefile$|\.bat$|\.cmake$|\.eps$|\.fits$|\.opt$)
|
||||
|
@ -39,7 +39,7 @@ repos:
|
|||
[flake8-2020, flake8-errmsg, flake8-implicit-str-concat]
|
||||
|
||||
- repo: https://github.com/pre-commit/pygrep-hooks
|
||||
rev: v1.9.0
|
||||
rev: v1.10.0
|
||||
hooks:
|
||||
- id: python-check-blanket-noqa
|
||||
- id: rst-backticks
|
||||
|
@ -57,7 +57,7 @@ repos:
|
|||
- id: sphinx-lint
|
||||
|
||||
- repo: https://github.com/tox-dev/tox-ini-fmt
|
||||
rev: 0.5.2
|
||||
rev: 0.6.1
|
||||
hooks:
|
||||
- id: tox-ini-fmt
|
||||
|
||||
|
|
24
CHANGES.rst
|
@ -5,6 +5,30 @@ Changelog (Pillow)
|
|||
9.5.0 (unreleased)
|
||||
------------------
|
||||
|
||||
- Raise an error if ImageDraw co-ordinates are incorrectly ordered #6978
|
||||
[radarhere]
|
||||
|
||||
- Added "corners" argument to ImageDraw rounded_rectangle() #6954
|
||||
[radarhere]
|
||||
|
||||
- Added memoryview support to frombytes() #6974
|
||||
[radarhere]
|
||||
|
||||
- Allow comments in FITS images #6973
|
||||
[radarhere]
|
||||
|
||||
- Support saving PDF with different X and Y resolutions #6961
|
||||
[jvanderneutstulen, radarhere, hugovk]
|
||||
|
||||
- Fixed writing int as UNDEFINED tag #6950
|
||||
[radarhere]
|
||||
|
||||
- Raise an error if EXIF data is too long when saving JPEG #6939
|
||||
[radarhere]
|
||||
|
||||
- Handle more than one directory returned by pkg-config #6896
|
||||
[sebastic, radarhere]
|
||||
|
||||
- Do not retry past formats when loading all formats for the first time #6902
|
||||
[radarhere]
|
||||
|
||||
|
|
4
LICENSE
|
@ -13,8 +13,8 @@ By obtaining, using, and/or copying this software and/or its associated
|
|||
documentation, you agree that you have read, understood, and will comply
|
||||
with the following terms and conditions:
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
associated documentation for any purpose and without fee is hereby granted,
|
||||
Permission to use, copy, modify and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted,
|
||||
provided that the above copyright notice appears in all copies, and that
|
||||
both that copyright notice and this permission notice appear in supporting
|
||||
documentation, and that the name of Secret Labs AB or the author not be
|
||||
|
|
|
@ -4,7 +4,6 @@ TEST_FILE = "Tests/images/fli_overflow.fli"
|
|||
|
||||
|
||||
def test_fli_overflow():
|
||||
|
||||
# this should not crash with a malloc error or access violation
|
||||
with Image.open(TEST_FILE) as im:
|
||||
im.load()
|
||||
|
|
|
@ -23,7 +23,6 @@ def test_ignore_dos_text():
|
|||
|
||||
|
||||
def test_dos_text():
|
||||
|
||||
try:
|
||||
im = Image.open(TEST_FILE)
|
||||
im.load()
|
||||
|
|
|
@ -20,7 +20,7 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
HAS_UPLOADER = False
|
||||
|
||||
if os.environ.get("SHOW_ERRORS", None):
|
||||
if os.environ.get("SHOW_ERRORS"):
|
||||
# local img.show for errors.
|
||||
HAS_UPLOADER = True
|
||||
|
||||
|
@ -271,7 +271,7 @@ def netpbm_available():
|
|||
|
||||
def magick_command():
|
||||
if sys.platform == "win32":
|
||||
magickhome = os.environ.get("MAGICK_HOME", "")
|
||||
magickhome = os.environ.get("MAGICK_HOME")
|
||||
if magickhome:
|
||||
imagemagick = [os.path.join(magickhome, "convert.exe")]
|
||||
graphicsmagick = [os.path.join(magickhome, "gm.exe"), "convert"]
|
||||
|
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
BIN
Tests/images/imagedraw_rounded_rectangle_corners_nnnn.png
Normal file
After Width: | Height: | Size: 544 B |
BIN
Tests/images/imagedraw_rounded_rectangle_corners_nnny.png
Normal file
After Width: | Height: | Size: 685 B |
BIN
Tests/images/imagedraw_rounded_rectangle_corners_nnyn.png
Normal file
After Width: | Height: | Size: 649 B |
BIN
Tests/images/imagedraw_rounded_rectangle_corners_nnyy.png
Normal file
After Width: | Height: | Size: 755 B |
BIN
Tests/images/imagedraw_rounded_rectangle_corners_nynn.png
Normal file
After Width: | Height: | Size: 643 B |
BIN
Tests/images/imagedraw_rounded_rectangle_corners_nyny.png
Normal file
After Width: | Height: | Size: 775 B |
BIN
Tests/images/imagedraw_rounded_rectangle_corners_nyyn.png
Normal file
After Width: | Height: | Size: 741 B |
BIN
Tests/images/imagedraw_rounded_rectangle_corners_nyyy.png
Normal file
After Width: | Height: | Size: 844 B |
BIN
Tests/images/imagedraw_rounded_rectangle_corners_ynnn.png
Normal file
After Width: | Height: | Size: 656 B |
BIN
Tests/images/imagedraw_rounded_rectangle_corners_ynny.png
Normal file
After Width: | Height: | Size: 785 B |
BIN
Tests/images/imagedraw_rounded_rectangle_corners_ynyn.png
Normal file
After Width: | Height: | Size: 752 B |
BIN
Tests/images/imagedraw_rounded_rectangle_corners_ynyy.png
Normal file
After Width: | Height: | Size: 856 B |
BIN
Tests/images/imagedraw_rounded_rectangle_corners_yynn.png
Normal file
After Width: | Height: | Size: 737 B |
BIN
Tests/images/imagedraw_rounded_rectangle_corners_yyny.png
Normal file
After Width: | Height: | Size: 870 B |
BIN
Tests/images/imagedraw_rounded_rectangle_corners_yyyn.png
Normal file
After Width: | Height: | Size: 835 B |
BIN
Tests/images/imagedraw_rounded_rectangle_corners_yyyy.png
Normal file
After Width: | Height: | Size: 934 B |
|
@ -18,7 +18,6 @@ def test_bad():
|
|||
"""These shouldn't crash/dos, but they shouldn't return anything
|
||||
either"""
|
||||
for f in get_files("b"):
|
||||
|
||||
# Assert that there is no unclosed file warning
|
||||
with warnings.catch_warnings():
|
||||
try:
|
||||
|
|
|
@ -177,13 +177,14 @@ class TestEnvVars:
|
|||
Image._apply_env_variables({"PILLOW_BLOCK_SIZE": "2m"})
|
||||
assert Image.core.get_block_size() == 2 * 1024 * 1024
|
||||
|
||||
def test_warnings(self):
|
||||
pytest.warns(
|
||||
UserWarning, Image._apply_env_variables, {"PILLOW_ALIGNMENT": "15"}
|
||||
)
|
||||
pytest.warns(
|
||||
UserWarning, Image._apply_env_variables, {"PILLOW_BLOCK_SIZE": "1024"}
|
||||
)
|
||||
pytest.warns(
|
||||
UserWarning, Image._apply_env_variables, {"PILLOW_BLOCKS_MAX": "wat"}
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"var",
|
||||
(
|
||||
{"PILLOW_ALIGNMENT": "15"},
|
||||
{"PILLOW_BLOCK_SIZE": "1024"},
|
||||
{"PILLOW_BLOCKS_MAX": "wat"},
|
||||
),
|
||||
)
|
||||
def test_warnings(self, var):
|
||||
with pytest.warns(UserWarning):
|
||||
Image._apply_env_variables(var)
|
||||
|
|
|
@ -36,12 +36,10 @@ class TestDecompressionBomb:
|
|||
Image.MAX_IMAGE_PIXELS = 128 * 128 - 1
|
||||
assert Image.MAX_IMAGE_PIXELS == 128 * 128 - 1
|
||||
|
||||
def open():
|
||||
with pytest.warns(Image.DecompressionBombWarning):
|
||||
with Image.open(TEST_FILE):
|
||||
pass
|
||||
|
||||
pytest.warns(Image.DecompressionBombWarning, open)
|
||||
|
||||
def test_exception(self):
|
||||
# Set limit to trigger exception on the test file
|
||||
Image.MAX_IMAGE_PIXELS = 64 * 128 - 1
|
||||
|
@ -87,7 +85,8 @@ class TestDecompressionCrop:
|
|||
# same decompression bomb warnings on them.
|
||||
with hopper() as src:
|
||||
box = (0, 0, src.width * 2, src.height * 2)
|
||||
pytest.warns(Image.DecompressionBombWarning, src.crop, box)
|
||||
with pytest.warns(Image.DecompressionBombWarning):
|
||||
src.crop(box)
|
||||
|
||||
def test_crop_decompression_checks(self):
|
||||
im = Image.new("RGB", (100, 100))
|
||||
|
@ -95,7 +94,8 @@ class TestDecompressionCrop:
|
|||
for value in ((-9999, -9999, -9990, -9990), (-999, -999, -990, -990)):
|
||||
assert im.crop(value).size == (9, 9)
|
||||
|
||||
pytest.warns(Image.DecompressionBombWarning, im.crop, (-160, -160, 99, 99))
|
||||
with pytest.warns(Image.DecompressionBombWarning):
|
||||
im.crop((-160, -160, 99, 99))
|
||||
|
||||
with pytest.raises(Image.DecompressionBombError):
|
||||
im.crop((-99909, -99990, 99999, 99999))
|
||||
|
|
|
@ -263,13 +263,11 @@ def test_apng_chunk_errors():
|
|||
with Image.open("Tests/images/apng/chunk_no_actl.png") as im:
|
||||
assert not im.is_animated
|
||||
|
||||
def open():
|
||||
with pytest.warns(UserWarning):
|
||||
with Image.open("Tests/images/apng/chunk_multi_actl.png") as im:
|
||||
im.load()
|
||||
assert not im.is_animated
|
||||
|
||||
pytest.warns(UserWarning, open)
|
||||
|
||||
with Image.open("Tests/images/apng/chunk_actl_after_idat.png") as im:
|
||||
assert not im.is_animated
|
||||
|
||||
|
@ -287,21 +285,17 @@ def test_apng_chunk_errors():
|
|||
|
||||
|
||||
def test_apng_syntax_errors():
|
||||
def open_frames_zero():
|
||||
with pytest.warns(UserWarning):
|
||||
with Image.open("Tests/images/apng/syntax_num_frames_zero.png") as im:
|
||||
assert not im.is_animated
|
||||
with pytest.raises(OSError):
|
||||
im.load()
|
||||
|
||||
pytest.warns(UserWarning, open_frames_zero)
|
||||
|
||||
def open_frames_zero_default():
|
||||
with pytest.warns(UserWarning):
|
||||
with Image.open("Tests/images/apng/syntax_num_frames_zero_default.png") as im:
|
||||
assert not im.is_animated
|
||||
im.load()
|
||||
|
||||
pytest.warns(UserWarning, open_frames_zero_default)
|
||||
|
||||
# we can handle this case gracefully
|
||||
exception = None
|
||||
with Image.open("Tests/images/apng/syntax_num_frames_low.png") as im:
|
||||
|
@ -316,13 +310,11 @@ def test_apng_syntax_errors():
|
|||
im.seek(im.n_frames - 1)
|
||||
im.load()
|
||||
|
||||
def open():
|
||||
with pytest.warns(UserWarning):
|
||||
with Image.open("Tests/images/apng/syntax_num_frames_invalid.png") as im:
|
||||
assert not im.is_animated
|
||||
im.load()
|
||||
|
||||
pytest.warns(UserWarning, open)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"test_file",
|
||||
|
|
|
@ -141,7 +141,6 @@ def test_rgba_bitfields():
|
|||
# This test image has been manually hexedited
|
||||
# to change the bitfield compression in the header from XBGR to RGBA
|
||||
with Image.open("Tests/images/rgb32bf-rgba.bmp") as im:
|
||||
|
||||
# So before the comparing the image, swap the channels
|
||||
b, g, r = im.split()[1:]
|
||||
im = Image.merge("RGB", (r, g, b))
|
||||
|
|
|
@ -10,7 +10,6 @@ TEST_FILE = "Tests/images/gfs.t06z.rassda.tm00.bufr_d"
|
|||
def test_open():
|
||||
# Act
|
||||
with Image.open(TEST_FILE) as im:
|
||||
|
||||
# Assert
|
||||
assert im.format == "BUFR"
|
||||
|
||||
|
@ -31,7 +30,6 @@ def test_invalid_file():
|
|||
def test_load():
|
||||
# Arrange
|
||||
with Image.open(TEST_FILE) as im:
|
||||
|
||||
# Act / Assert: stub cannot load without an implemented handler
|
||||
with pytest.raises(OSError):
|
||||
im.load()
|
||||
|
@ -58,6 +56,7 @@ def test_handler(tmp_path):
|
|||
|
||||
def load(self, im):
|
||||
self.loaded = True
|
||||
im.fp.close()
|
||||
return Image.new("RGB", (1, 1))
|
||||
|
||||
def save(self, im, fp, filename):
|
||||
|
|
|
@ -15,7 +15,6 @@ def test_sanity():
|
|||
|
||||
# Act
|
||||
with Image.open(TEST_FILE) as im:
|
||||
|
||||
# Assert
|
||||
assert im.size == (128, 128)
|
||||
assert isinstance(im, DcxImagePlugin.DcxImageFile)
|
||||
|
@ -29,7 +28,8 @@ def test_unclosed_file():
|
|||
im = Image.open(TEST_FILE)
|
||||
im.load()
|
||||
|
||||
pytest.warns(ResourceWarning, open)
|
||||
with pytest.warns(ResourceWarning):
|
||||
open()
|
||||
|
||||
|
||||
def test_closed_file():
|
||||
|
@ -54,7 +54,6 @@ def test_invalid_file():
|
|||
def test_tell():
|
||||
# Arrange
|
||||
with Image.open(TEST_FILE) as im:
|
||||
|
||||
# Act
|
||||
frame = im.tell()
|
||||
|
||||
|
|
|
@ -80,7 +80,6 @@ def test_invalid_file():
|
|||
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
|
||||
def test_cmyk():
|
||||
with Image.open("Tests/images/pil_sample_cmyk.eps") as cmyk_image:
|
||||
|
||||
assert cmyk_image.mode == "CMYK"
|
||||
assert cmyk_image.size == (100, 100)
|
||||
assert cmyk_image.format == "EPS"
|
||||
|
|
|
@ -12,7 +12,6 @@ TEST_FILE = "Tests/images/hopper.fits"
|
|||
def test_open():
|
||||
# Act
|
||||
with Image.open(TEST_FILE) as im:
|
||||
|
||||
# Assert
|
||||
assert im.format == "FITS"
|
||||
assert im.size == (128, 128)
|
||||
|
@ -45,6 +44,12 @@ def test_naxis_zero():
|
|||
pass
|
||||
|
||||
|
||||
def test_comment():
|
||||
image_data = b"SIMPLE = T / comment string"
|
||||
with pytest.raises(OSError):
|
||||
FitsImagePlugin.FitsImageFile(BytesIO(image_data))
|
||||
|
||||
|
||||
def test_stub_deprecated():
|
||||
class Handler:
|
||||
opened = False
|
||||
|
@ -55,6 +60,7 @@ def test_stub_deprecated():
|
|||
|
||||
def load(self, im):
|
||||
self.loaded = True
|
||||
im.fp.close()
|
||||
return Image.new("RGB", (1, 1))
|
||||
|
||||
handler = Handler()
|
||||
|
|
|
@ -36,7 +36,8 @@ def test_unclosed_file():
|
|||
im = Image.open(static_test_file)
|
||||
im.load()
|
||||
|
||||
pytest.warns(ResourceWarning, open)
|
||||
with pytest.warns(ResourceWarning):
|
||||
open()
|
||||
|
||||
|
||||
def test_closed_file():
|
||||
|
@ -64,7 +65,6 @@ def test_context_manager():
|
|||
def test_tell():
|
||||
# Arrange
|
||||
with Image.open(static_test_file) as im:
|
||||
|
||||
# Act
|
||||
frame = im.tell()
|
||||
|
||||
|
@ -110,7 +110,6 @@ def test_eoferror():
|
|||
|
||||
def test_seek_tell():
|
||||
with Image.open(animated_test_file) as im:
|
||||
|
||||
layer_number = im.tell()
|
||||
assert layer_number == 0
|
||||
|
||||
|
|
|
@ -18,6 +18,16 @@ def test_sanity():
|
|||
assert_image_equal_tofile(im, "Tests/images/input_bw_one_band.png")
|
||||
|
||||
|
||||
def test_close():
|
||||
with Image.open("Tests/images/input_bw_one_band.fpx") as im:
|
||||
pass
|
||||
assert im.ole.fp.closed
|
||||
|
||||
im = Image.open("Tests/images/input_bw_one_band.fpx")
|
||||
im.close()
|
||||
assert im.ole.fp.closed
|
||||
|
||||
|
||||
def test_invalid_file():
|
||||
# Test an invalid OLE file
|
||||
invalid_file = "Tests/images/flower.jpg"
|
||||
|
|
|
@ -36,7 +36,8 @@ def test_unclosed_file():
|
|||
im = Image.open(TEST_GIF)
|
||||
im.load()
|
||||
|
||||
pytest.warns(ResourceWarning, open)
|
||||
with pytest.warns(ResourceWarning):
|
||||
open()
|
||||
|
||||
|
||||
def test_closed_file():
|
||||
|
@ -209,7 +210,7 @@ def test_optimize_if_palette_can_be_reduced_by_half():
|
|||
im = im.resize((591, 443))
|
||||
im_rgb = im.convert("RGB")
|
||||
|
||||
for (optimize, colors) in ((False, 256), (True, 8)):
|
||||
for optimize, colors in ((False, 256), (True, 8)):
|
||||
out = BytesIO()
|
||||
im_rgb.save(out, "GIF", optimize=optimize)
|
||||
with Image.open(out) as reloaded:
|
||||
|
@ -221,7 +222,6 @@ def test_roundtrip(tmp_path):
|
|||
im = hopper()
|
||||
im.save(out)
|
||||
with Image.open(out) as reread:
|
||||
|
||||
assert_image_similar(reread.convert("RGB"), im, 50)
|
||||
|
||||
|
||||
|
@ -232,7 +232,6 @@ def test_roundtrip2(tmp_path):
|
|||
im2 = im.copy()
|
||||
im2.save(out)
|
||||
with Image.open(out) as reread:
|
||||
|
||||
assert_image_similar(reread.convert("RGB"), hopper(), 50)
|
||||
|
||||
|
||||
|
@ -242,7 +241,6 @@ def test_roundtrip_save_all(tmp_path):
|
|||
im = hopper()
|
||||
im.save(out, save_all=True)
|
||||
with Image.open(out) as reread:
|
||||
|
||||
assert_image_similar(reread.convert("RGB"), im, 50)
|
||||
|
||||
# Multiframe image
|
||||
|
@ -284,13 +282,11 @@ def test_headers_saving_for_animated_gifs(tmp_path):
|
|||
important_headers = ["background", "version", "duration", "loop"]
|
||||
# Multiframe image
|
||||
with Image.open("Tests/images/dispose_bgnd.gif") as im:
|
||||
|
||||
info = im.info.copy()
|
||||
|
||||
out = str(tmp_path / "temp.gif")
|
||||
im.save(out, save_all=True)
|
||||
with Image.open(out) as reread:
|
||||
|
||||
for header in important_headers:
|
||||
assert info[header] == reread.info[header]
|
||||
|
||||
|
@ -308,7 +304,6 @@ def test_palette_handling(tmp_path):
|
|||
im2.save(f, optimize=True)
|
||||
|
||||
with Image.open(f) as reloaded:
|
||||
|
||||
assert_image_similar(im, reloaded.convert("RGB"), 10)
|
||||
|
||||
|
||||
|
@ -324,7 +319,6 @@ def test_palette_434(tmp_path):
|
|||
|
||||
orig = "Tests/images/test.colors.gif"
|
||||
with Image.open(orig) as im:
|
||||
|
||||
with roundtrip(im) as reloaded:
|
||||
assert_image_similar(im, reloaded, 1)
|
||||
with roundtrip(im, optimize=True) as reloaded:
|
||||
|
@ -575,7 +569,6 @@ def test_save_dispose(tmp_path):
|
|||
)
|
||||
|
||||
with Image.open(out) as img:
|
||||
|
||||
for i in range(2):
|
||||
img.seek(img.tell() + 1)
|
||||
assert img.disposal_method == i + 1
|
||||
|
@ -773,7 +766,6 @@ def test_multiple_duration(tmp_path):
|
|||
out, save_all=True, append_images=im_list[1:], duration=duration_list
|
||||
)
|
||||
with Image.open(out) as reread:
|
||||
|
||||
for duration in duration_list:
|
||||
assert reread.info["duration"] == duration
|
||||
try:
|
||||
|
@ -786,7 +778,6 @@ def test_multiple_duration(tmp_path):
|
|||
out, save_all=True, append_images=im_list[1:], duration=tuple(duration_list)
|
||||
)
|
||||
with Image.open(out) as reread:
|
||||
|
||||
for duration in duration_list:
|
||||
assert reread.info["duration"] == duration
|
||||
try:
|
||||
|
@ -844,7 +835,6 @@ def test_identical_frames(tmp_path):
|
|||
out, save_all=True, append_images=im_list[1:], duration=duration_list
|
||||
)
|
||||
with Image.open(out) as reread:
|
||||
|
||||
# Assert that the first three frames were combined
|
||||
assert reread.n_frames == 2
|
||||
|
||||
|
@ -1098,7 +1088,8 @@ def test_rgb_transparency(tmp_path):
|
|||
im = Image.new("RGB", (1, 1))
|
||||
im.info["transparency"] = b""
|
||||
ims = [Image.new("RGB", (1, 1))]
|
||||
pytest.warns(UserWarning, im.save, out, save_all=True, append_images=ims)
|
||||
with pytest.warns(UserWarning):
|
||||
im.save(out, save_all=True, append_images=ims)
|
||||
|
||||
with Image.open(out) as reloaded:
|
||||
assert "transparency" not in reloaded.info
|
||||
|
|
|
@ -10,7 +10,6 @@ TEST_FILE = "Tests/images/WAlaska.wind.7days.grb"
|
|||
def test_open():
|
||||
# Act
|
||||
with Image.open(TEST_FILE) as im:
|
||||
|
||||
# Assert
|
||||
assert im.format == "GRIB"
|
||||
|
||||
|
@ -31,7 +30,6 @@ def test_invalid_file():
|
|||
def test_load():
|
||||
# Arrange
|
||||
with Image.open(TEST_FILE) as im:
|
||||
|
||||
# Act / Assert: stub cannot load without an implemented handler
|
||||
with pytest.raises(OSError):
|
||||
im.load()
|
||||
|
@ -58,6 +56,7 @@ def test_handler(tmp_path):
|
|||
|
||||
def load(self, im):
|
||||
self.loaded = True
|
||||
im.fp.close()
|
||||
return Image.new("RGB", (1, 1))
|
||||
|
||||
def save(self, im, fp, filename):
|
||||
|
|
|
@ -8,7 +8,6 @@ TEST_FILE = "Tests/images/hdf5.h5"
|
|||
def test_open():
|
||||
# Act
|
||||
with Image.open(TEST_FILE) as im:
|
||||
|
||||
# Assert
|
||||
assert im.format == "HDF5"
|
||||
|
||||
|
@ -29,7 +28,6 @@ def test_invalid_file():
|
|||
def test_load():
|
||||
# Arrange
|
||||
with Image.open(TEST_FILE) as im:
|
||||
|
||||
# Act / Assert: stub cannot load without an implemented handler
|
||||
with pytest.raises(OSError):
|
||||
im.load()
|
||||
|
@ -59,6 +57,7 @@ def test_handler(tmp_path):
|
|||
|
||||
def load(self, im):
|
||||
self.loaded = True
|
||||
im.fp.close()
|
||||
return Image.new("RGB", (1, 1))
|
||||
|
||||
def save(self, im, fp, filename):
|
||||
|
|
|
@ -16,7 +16,6 @@ def test_sanity():
|
|||
# Loading this icon by default should result in the largest size
|
||||
# (512x512@2x) being loaded
|
||||
with Image.open(TEST_FILE) as im:
|
||||
|
||||
# Assert that there is no unclosed file warning
|
||||
with warnings.catch_warnings():
|
||||
im.load()
|
||||
|
|
|
@ -175,7 +175,6 @@ def test_save_256x256(tmp_path):
|
|||
# Act
|
||||
im.save(outfile)
|
||||
with Image.open(outfile) as im_saved:
|
||||
|
||||
# Assert
|
||||
assert im_saved.size == (256, 256)
|
||||
|
||||
|
@ -213,12 +212,10 @@ def test_save_append_images(tmp_path):
|
|||
def test_unexpected_size():
|
||||
# This image has been manually hexedited to state that it is 16x32
|
||||
# while the image within is still 16x16
|
||||
def open():
|
||||
with pytest.warns(UserWarning):
|
||||
with Image.open("Tests/images/hopper_unexpected.ico") as im:
|
||||
assert im.size == (16, 16)
|
||||
|
||||
pytest.warns(UserWarning, open)
|
||||
|
||||
|
||||
def test_draw_reloaded(tmp_path):
|
||||
with Image.open(TEST_ICO_FILE) as im:
|
||||
|
|
|
@ -32,7 +32,8 @@ def test_unclosed_file():
|
|||
im = Image.open(TEST_IM)
|
||||
im.load()
|
||||
|
||||
pytest.warns(ResourceWarning, open)
|
||||
with pytest.warns(ResourceWarning):
|
||||
open()
|
||||
|
||||
|
||||
def test_closed_file():
|
||||
|
@ -51,7 +52,6 @@ def test_context_manager():
|
|||
def test_tell():
|
||||
# Arrange
|
||||
with Image.open(TEST_IM) as im:
|
||||
|
||||
# Act
|
||||
frame = im.tell()
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ TEST_FILE = "Tests/images/iptc.jpg"
|
|||
def test_getiptcinfo_jpg_none():
|
||||
# Arrange
|
||||
with hopper() as im:
|
||||
|
||||
# Act
|
||||
iptc = IptcImagePlugin.getiptcinfo(im)
|
||||
|
||||
|
@ -22,7 +21,6 @@ def test_getiptcinfo_jpg_none():
|
|||
def test_getiptcinfo_jpg_found():
|
||||
# Arrange
|
||||
with Image.open(TEST_FILE) as im:
|
||||
|
||||
# Act
|
||||
iptc = IptcImagePlugin.getiptcinfo(im)
|
||||
|
||||
|
@ -35,7 +33,6 @@ def test_getiptcinfo_jpg_found():
|
|||
def test_getiptcinfo_tiff_none():
|
||||
# Arrange
|
||||
with Image.open("Tests/images/hopper.tif") as im:
|
||||
|
||||
# Act
|
||||
iptc = IptcImagePlugin.getiptcinfo(im)
|
||||
|
||||
|
|
|
@ -57,7 +57,6 @@ class TestFileJpeg:
|
|||
return Image.frombytes(mode, size, os.urandom(size[0] * size[1] * len(mode)))
|
||||
|
||||
def test_sanity(self):
|
||||
|
||||
# internal version number
|
||||
assert re.search(r"\d+\.\d+$", features.version_codec("jpg"))
|
||||
|
||||
|
@ -271,7 +270,10 @@ class TestFileJpeg:
|
|||
# https://github.com/python-pillow/Pillow/issues/148
|
||||
f = str(tmp_path / "temp.jpg")
|
||||
im = hopper()
|
||||
im.save(f, "JPEG", quality=90, exif=b"1" * 65532)
|
||||
im.save(f, "JPEG", quality=90, exif=b"1" * 65533)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
im.save(f, "JPEG", quality=90, exif=b"1" * 65534)
|
||||
|
||||
def test_exif_typeerror(self):
|
||||
with Image.open("Tests/images/exif_typeerror.jpg") as im:
|
||||
|
@ -368,7 +370,6 @@ class TestFileJpeg:
|
|||
|
||||
def test_exif_gps_typeerror(self):
|
||||
with Image.open("Tests/images/exif_gps_typeerror.jpg") as im:
|
||||
|
||||
# Should not raise a TypeError
|
||||
im._getexif()
|
||||
|
||||
|
@ -447,7 +448,7 @@ class TestFileJpeg:
|
|||
ims = im.get_child_images()
|
||||
|
||||
assert len(ims) == 1
|
||||
assert_image_equal_tofile(ims[0], "Tests/images/flower_thumbnail.png")
|
||||
assert_image_similar_tofile(ims[0], "Tests/images/flower_thumbnail.png", 2.1)
|
||||
|
||||
def test_mp(self):
|
||||
with Image.open("Tests/images/pil_sample_rgb.jpg") as im:
|
||||
|
@ -682,7 +683,6 @@ class TestFileJpeg:
|
|||
# Shouldn't raise error
|
||||
fn = "Tests/images/sugarshack_bad_mpo_header.jpg"
|
||||
with pytest.warns(UserWarning, Image.open, fn) as im:
|
||||
|
||||
# Assert
|
||||
assert im.format == "JPEG"
|
||||
|
||||
|
@ -704,7 +704,6 @@ class TestFileJpeg:
|
|||
# Arrange
|
||||
outfile = str(tmp_path / "temp.tif")
|
||||
with Image.open("Tests/images/hopper.tif") as im:
|
||||
|
||||
# Act
|
||||
im.save(outfile, "JPEG", dpi=im.info["dpi"])
|
||||
|
||||
|
@ -731,7 +730,6 @@ class TestFileJpeg:
|
|||
# This Photoshop CC 2017 image has DPI in EXIF not metadata
|
||||
# EXIF XResolution is (2000000, 10000)
|
||||
with Image.open("Tests/images/photoshop-200dpi.jpg") as im:
|
||||
|
||||
# Act / Assert
|
||||
assert im.info.get("dpi") == (200, 200)
|
||||
|
||||
|
@ -740,7 +738,6 @@ class TestFileJpeg:
|
|||
# This image has DPI in EXIF not metadata
|
||||
# EXIF XResolution is 72
|
||||
with Image.open("Tests/images/exif-72dpi-int.jpg") as im:
|
||||
|
||||
# Act / Assert
|
||||
assert im.info.get("dpi") == (72, 72)
|
||||
|
||||
|
@ -749,7 +746,6 @@ class TestFileJpeg:
|
|||
# This is photoshop-200dpi.jpg with EXIF resolution unit set to cm:
|
||||
# exiftool -exif:ResolutionUnit=cm photoshop-200dpi.jpg
|
||||
with Image.open("Tests/images/exif-200dpcm.jpg") as im:
|
||||
|
||||
# Act / Assert
|
||||
assert im.info.get("dpi") == (508, 508)
|
||||
|
||||
|
@ -758,7 +754,6 @@ class TestFileJpeg:
|
|||
# This is photoshop-200dpi.jpg with EXIF resolution set to 0/0:
|
||||
# exiftool -XResolution=0/0 -YResolution=0/0 photoshop-200dpi.jpg
|
||||
with Image.open("Tests/images/exif-dpi-zerodivision.jpg") as im:
|
||||
|
||||
# Act / Assert
|
||||
# This should return the default, and not raise a ZeroDivisionError
|
||||
assert im.info.get("dpi") == (72, 72)
|
||||
|
@ -767,7 +762,6 @@ class TestFileJpeg:
|
|||
# Arrange
|
||||
# 0x011A tag in this exif contains string '300300\x02'
|
||||
with Image.open("Tests/images/broken_exif_dpi.jpg") as im:
|
||||
|
||||
# Act / Assert
|
||||
# This should return the default
|
||||
assert im.info.get("dpi") == (72, 72)
|
||||
|
@ -777,7 +771,6 @@ class TestFileJpeg:
|
|||
# This is photoshop-200dpi.jpg with resolution removed from EXIF:
|
||||
# exiftool "-*resolution*"= photoshop-200dpi.jpg
|
||||
with Image.open("Tests/images/no-dpi-in-exif.jpg") as im:
|
||||
|
||||
# Act / Assert
|
||||
# "When the image resolution is unknown, 72 [dpi] is designated."
|
||||
# https://exiv2.org/tags.html
|
||||
|
@ -787,7 +780,6 @@ class TestFileJpeg:
|
|||
# This is no-dpi-in-exif with the tiff header of the exif block
|
||||
# hexedited from MM * to FF FF FF FF
|
||||
with Image.open("Tests/images/invalid-exif.jpg") as im:
|
||||
|
||||
# This should return the default, and not a SyntaxError or
|
||||
# OSError for unidentified image.
|
||||
assert im.info.get("dpi") == (72, 72)
|
||||
|
@ -810,7 +802,6 @@ class TestFileJpeg:
|
|||
def test_invalid_exif_x_resolution(self):
|
||||
# When no x or y resolution is defined in EXIF
|
||||
with Image.open("Tests/images/invalid-exif-without-x-resolution.jpg") as im:
|
||||
|
||||
# This should return the default, and not a ValueError or
|
||||
# OSError for an unidentified image.
|
||||
assert im.info.get("dpi") == (72, 72)
|
||||
|
@ -820,7 +811,6 @@ class TestFileJpeg:
|
|||
# This image has been manually hexedited to have an IFD offset of 10,
|
||||
# in contrast to normal 8
|
||||
with Image.open("Tests/images/exif-ifd-offset.jpg") as im:
|
||||
|
||||
# Act / Assert
|
||||
assert im._getexif()[306] == "2017:03:13 23:03:09"
|
||||
|
||||
|
|
|
@ -270,7 +270,6 @@ def test_rgba():
|
|||
# Arrange
|
||||
with Image.open("Tests/images/rgb_trns_ycbc.j2k") as j2k:
|
||||
with Image.open("Tests/images/rgb_trns_ycbc.jp2") as jp2:
|
||||
|
||||
# Act
|
||||
j2k.load()
|
||||
jp2.load()
|
||||
|
|
|
@ -645,7 +645,6 @@ class TestFileLibTiff(LibTiffTestCase):
|
|||
pilim = hopper()
|
||||
|
||||
def save_bytesio(compression=None):
|
||||
|
||||
buffer_io = io.BytesIO()
|
||||
pilim.save(buffer_io, format="tiff", compression=compression)
|
||||
buffer_io.seek(0)
|
||||
|
@ -740,7 +739,6 @@ class TestFileLibTiff(LibTiffTestCase):
|
|||
|
||||
def test_multipage_compression(self):
|
||||
with Image.open("Tests/images/compression.tif") as im:
|
||||
|
||||
im.seek(0)
|
||||
assert im._compression == "tiff_ccitt"
|
||||
assert im.size == (10, 10)
|
||||
|
@ -1098,6 +1096,12 @@ class TestFileLibTiff(LibTiffTestCase):
|
|||
with pytest.raises(SystemError):
|
||||
im.save(out, compression=compression)
|
||||
|
||||
def test_save_many_compressed(self, tmp_path):
|
||||
im = hopper()
|
||||
out = str(tmp_path / "temp.tif")
|
||||
for _ in range(10000):
|
||||
im.save(out, compression="jpeg")
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"path, sizes",
|
||||
(
|
||||
|
|
|
@ -51,6 +51,16 @@ def test_seek():
|
|||
assert im.tell() == 0
|
||||
|
||||
|
||||
def test_close():
|
||||
with Image.open(TEST_FILE) as im:
|
||||
pass
|
||||
assert im.ole.fp.closed
|
||||
|
||||
im = Image.open(TEST_FILE)
|
||||
im.close()
|
||||
assert im.ole.fp.closed
|
||||
|
||||
|
||||
def test_invalid_file():
|
||||
# Test an invalid OLE file
|
||||
invalid_file = "Tests/images/flower.jpg"
|
||||
|
|
|
@ -42,7 +42,8 @@ def test_unclosed_file():
|
|||
im = Image.open(test_files[0])
|
||||
im.load()
|
||||
|
||||
pytest.warns(ResourceWarning, open)
|
||||
with pytest.warns(ResourceWarning):
|
||||
open()
|
||||
|
||||
|
||||
def test_closed_file():
|
||||
|
|
|
@ -44,7 +44,6 @@ def test_open_windows_v1():
|
|||
# Arrange
|
||||
# Act
|
||||
with Image.open(TEST_FILE) as im:
|
||||
|
||||
# Assert
|
||||
assert_image_equal(im, hopper("1"))
|
||||
assert isinstance(im, MspImagePlugin.MspImageFile)
|
||||
|
@ -59,7 +58,6 @@ def _assert_file_image_equal(source_path, target_path):
|
|||
not os.path.exists(EXTRA_DIR), reason="Extra image files not installed"
|
||||
)
|
||||
def test_open_windows_v2():
|
||||
|
||||
files = (
|
||||
os.path.join(EXTRA_DIR, f)
|
||||
for f in os.listdir(EXTRA_DIR)
|
||||
|
|
|
@ -80,6 +80,34 @@ def test_resolution(tmp_path):
|
|||
assert size == (61.44, 61.44)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
(
|
||||
{"dpi": (75, 150)},
|
||||
{"dpi": (75, 150), "resolution": 200},
|
||||
),
|
||||
)
|
||||
def test_dpi(params, tmp_path):
|
||||
im = hopper()
|
||||
|
||||
outfile = str(tmp_path / "temp.pdf")
|
||||
im.save(outfile, **params)
|
||||
|
||||
with open(outfile, "rb") as fp:
|
||||
contents = fp.read()
|
||||
|
||||
size = tuple(
|
||||
float(d)
|
||||
for d in contents.split(b"stream\nq ")[1].split(b" 0 0 cm")[0].split(b" 0 0 ")
|
||||
)
|
||||
assert size == (122.88, 61.44)
|
||||
|
||||
size = tuple(
|
||||
float(d) for d in contents.split(b"/MediaBox [ 0 0 ")[1].split(b"]")[0].split()
|
||||
)
|
||||
assert size == (122.88, 61.44)
|
||||
|
||||
|
||||
@mark_if_feature_version(
|
||||
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
|
||||
)
|
||||
|
@ -89,7 +117,6 @@ def test_save_all(tmp_path):
|
|||
|
||||
# Multiframe image
|
||||
with Image.open("Tests/images/dispose_bgnd.gif") as im:
|
||||
|
||||
outfile = str(tmp_path / "temp.pdf")
|
||||
im.save(outfile, save_all=True)
|
||||
|
||||
|
@ -123,7 +150,6 @@ def test_save_all(tmp_path):
|
|||
def test_multiframe_normal_save(tmp_path):
|
||||
# Test saving a multiframe image without save_all
|
||||
with Image.open("Tests/images/dispose_bgnd.gif") as im:
|
||||
|
||||
outfile = str(tmp_path / "temp.pdf")
|
||||
im.save(outfile)
|
||||
|
||||
|
|
|
@ -78,7 +78,6 @@ class TestFilePng:
|
|||
return chunks
|
||||
|
||||
def test_sanity(self, tmp_path):
|
||||
|
||||
# internal version number
|
||||
assert re.search(r"\d+\.\d+\.\d+(\.\d+)?$", features.version_codec("zlib"))
|
||||
|
||||
|
@ -156,7 +155,6 @@ class TestFilePng:
|
|||
assert im.info == {"spam": "egg"}
|
||||
|
||||
def test_bad_itxt(self):
|
||||
|
||||
im = load(HEAD + chunk(b"iTXt") + TAIL)
|
||||
assert im.info == {}
|
||||
|
||||
|
@ -201,7 +199,6 @@ class TestFilePng:
|
|||
assert im.info["spam"].tkey == "Spam"
|
||||
|
||||
def test_interlace(self):
|
||||
|
||||
test_file = "Tests/images/pil123p.png"
|
||||
with Image.open(test_file) as im:
|
||||
assert_image(im, "P", (162, 150))
|
||||
|
@ -495,7 +492,6 @@ class TestFilePng:
|
|||
# Check reading images with null tRNS value, issue #1239
|
||||
test_file = "Tests/images/tRNS_null_1x1.png"
|
||||
with Image.open(test_file) as im:
|
||||
|
||||
assert im.info["transparency"] == 0
|
||||
|
||||
def test_save_icc_profile(self):
|
||||
|
|
|
@ -27,7 +27,8 @@ def test_unclosed_file():
|
|||
im = Image.open(test_file)
|
||||
im.load()
|
||||
|
||||
pytest.warns(ResourceWarning, open)
|
||||
with pytest.warns(ResourceWarning):
|
||||
open()
|
||||
|
||||
|
||||
def test_closed_file():
|
||||
|
@ -77,7 +78,6 @@ def test_eoferror():
|
|||
|
||||
def test_seek_tell():
|
||||
with Image.open(test_file) as im:
|
||||
|
||||
layer_number = im.tell()
|
||||
assert layer_number == 1
|
||||
|
||||
|
@ -95,7 +95,6 @@ def test_seek_tell():
|
|||
|
||||
def test_seek_eoferror():
|
||||
with Image.open(test_file) as im:
|
||||
|
||||
with pytest.raises(EOFError):
|
||||
im.seek(-1)
|
||||
|
||||
|
|
|
@ -25,7 +25,8 @@ def test_unclosed_file():
|
|||
im = Image.open(TEST_FILE)
|
||||
im.load()
|
||||
|
||||
pytest.warns(ResourceWarning, open)
|
||||
with pytest.warns(ResourceWarning):
|
||||
open()
|
||||
|
||||
|
||||
def test_closed_file():
|
||||
|
@ -79,7 +80,6 @@ def test_is_spider_image():
|
|||
def test_tell():
|
||||
# Arrange
|
||||
with Image.open(TEST_FILE) as im:
|
||||
|
||||
# Act
|
||||
index = im.tell()
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ def test_sanity():
|
|||
|
||||
# Act
|
||||
with Image.open(test_file) as im:
|
||||
|
||||
# Assert
|
||||
assert im.size == (128, 128)
|
||||
|
||||
|
|
|
@ -29,11 +29,9 @@ def test_sanity(codec, test_path, format):
|
|||
|
||||
@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
|
||||
def test_unclosed_file():
|
||||
def open():
|
||||
with pytest.warns(ResourceWarning):
|
||||
TarIO.TarIO(TEST_TAR_FILE, "hopper.jpg")
|
||||
|
||||
pytest.warns(ResourceWarning, open)
|
||||
|
||||
|
||||
def test_close():
|
||||
with warnings.catch_warnings():
|
||||
|
|
|
@ -78,7 +78,6 @@ def test_id_field():
|
|||
|
||||
# Act
|
||||
with Image.open(test_file) as im:
|
||||
|
||||
# Assert
|
||||
assert im.size == (100, 100)
|
||||
|
||||
|
@ -89,7 +88,6 @@ def test_id_field_rle():
|
|||
|
||||
# Act
|
||||
with Image.open(test_file) as im:
|
||||
|
||||
# Assert
|
||||
assert im.size == (199, 199)
|
||||
|
||||
|
@ -165,13 +163,14 @@ def test_save_id_section(tmp_path):
|
|||
|
||||
# Save with custom id section greater than 255 characters
|
||||
id_section = b"Test content" * 25
|
||||
pytest.warns(UserWarning, lambda: im.save(out, id_section=id_section))
|
||||
with pytest.warns(UserWarning):
|
||||
im.save(out, id_section=id_section)
|
||||
|
||||
with Image.open(out) as test_im:
|
||||
assert test_im.info["id_section"] == id_section[:255]
|
||||
|
||||
test_file = "Tests/images/tga_id_field.tga"
|
||||
with Image.open(test_file) as im:
|
||||
|
||||
# Save with no id section
|
||||
im.save(out, id_section="")
|
||||
with Image.open(out) as test_im:
|
||||
|
|
|
@ -25,7 +25,6 @@ except ImportError:
|
|||
|
||||
class TestFileTiff:
|
||||
def test_sanity(self, tmp_path):
|
||||
|
||||
filename = str(tmp_path / "temp.tif")
|
||||
|
||||
hopper("RGB").save(filename)
|
||||
|
@ -62,7 +61,8 @@ class TestFileTiff:
|
|||
im = Image.open("Tests/images/multipage.tiff")
|
||||
im.load()
|
||||
|
||||
pytest.warns(ResourceWarning, open)
|
||||
with pytest.warns(ResourceWarning):
|
||||
open()
|
||||
|
||||
def test_closed_file(self):
|
||||
with warnings.catch_warnings():
|
||||
|
@ -109,7 +109,6 @@ class TestFileTiff:
|
|||
def test_xyres_tiff(self):
|
||||
filename = "Tests/images/pil168.tif"
|
||||
with Image.open(filename) as im:
|
||||
|
||||
# legacy api
|
||||
assert isinstance(im.tag[X_RESOLUTION][0], tuple)
|
||||
assert isinstance(im.tag[Y_RESOLUTION][0], tuple)
|
||||
|
@ -123,7 +122,6 @@ class TestFileTiff:
|
|||
def test_xyres_fallback_tiff(self):
|
||||
filename = "Tests/images/compression.tif"
|
||||
with Image.open(filename) as im:
|
||||
|
||||
# v2 api
|
||||
assert isinstance(im.tag_v2[X_RESOLUTION], TiffImagePlugin.IFDRational)
|
||||
assert isinstance(im.tag_v2[Y_RESOLUTION], TiffImagePlugin.IFDRational)
|
||||
|
@ -138,7 +136,6 @@ class TestFileTiff:
|
|||
def test_int_resolution(self):
|
||||
filename = "Tests/images/pil168.tif"
|
||||
with Image.open(filename) as im:
|
||||
|
||||
# Try to read a file where X,Y_RESOLUTION are ints
|
||||
im.tag_v2[X_RESOLUTION] = 71
|
||||
im.tag_v2[Y_RESOLUTION] = 71
|
||||
|
@ -187,7 +184,8 @@ class TestFileTiff:
|
|||
def test_bad_exif(self):
|
||||
with Image.open("Tests/images/hopper_bad_exif.jpg") as i:
|
||||
# Should not raise struct.error.
|
||||
pytest.warns(UserWarning, i._getexif)
|
||||
with pytest.warns(UserWarning):
|
||||
i._getexif()
|
||||
|
||||
def test_save_rgba(self, tmp_path):
|
||||
im = hopper("RGBA")
|
||||
|
@ -333,7 +331,6 @@ class TestFileTiff:
|
|||
def test___str__(self):
|
||||
filename = "Tests/images/pil136.tiff"
|
||||
with Image.open(filename) as im:
|
||||
|
||||
# Act
|
||||
ret = str(im.ifd)
|
||||
|
||||
|
@ -344,7 +341,6 @@ class TestFileTiff:
|
|||
# Arrange
|
||||
filename = "Tests/images/pil136.tiff"
|
||||
with Image.open(filename) as im:
|
||||
|
||||
# v2 interface
|
||||
v2_tags = {
|
||||
256: 55,
|
||||
|
@ -582,7 +578,6 @@ class TestFileTiff:
|
|||
filename = str(tmp_path / "temp.tif")
|
||||
hopper("RGB").save(filename, **kwargs)
|
||||
with Image.open(filename) as im:
|
||||
|
||||
# legacy interface
|
||||
assert im.tag[X_RESOLUTION][0][0] == 72
|
||||
assert im.tag[Y_RESOLUTION][0][0] == 36
|
||||
|
|
|
@ -54,7 +54,6 @@ def test_rt_metadata(tmp_path):
|
|||
img.save(f, tiffinfo=info)
|
||||
|
||||
with Image.open(f) as loaded:
|
||||
|
||||
assert loaded.tag[ImageJMetaDataByteCounts] == (len(bin_data),)
|
||||
assert loaded.tag_v2[ImageJMetaDataByteCounts] == (len(bin_data),)
|
||||
|
||||
|
@ -74,14 +73,12 @@ def test_rt_metadata(tmp_path):
|
|||
info[ImageJMetaDataByteCounts] = (8, len(bin_data) - 8)
|
||||
img.save(f, tiffinfo=info)
|
||||
with Image.open(f) as loaded:
|
||||
|
||||
assert loaded.tag[ImageJMetaDataByteCounts] == (8, len(bin_data) - 8)
|
||||
assert loaded.tag_v2[ImageJMetaDataByteCounts] == (8, len(bin_data) - 8)
|
||||
|
||||
|
||||
def test_read_metadata():
|
||||
with Image.open("Tests/images/hopper_g4.tif") as img:
|
||||
|
||||
assert {
|
||||
"YResolution": IFDRational(4294967295, 113653537),
|
||||
"PlanarConfiguration": 1,
|
||||
|
@ -219,6 +216,22 @@ def test_writing_other_types_to_bytes(value, tmp_path):
|
|||
assert reloaded.tag_v2[700] == b"\x01"
|
||||
|
||||
|
||||
def test_writing_other_types_to_undefined(tmp_path):
|
||||
im = hopper()
|
||||
info = TiffImagePlugin.ImageFileDirectory_v2()
|
||||
|
||||
tag = TiffTags.TAGS_V2[33723]
|
||||
assert tag.type == TiffTags.UNDEFINED
|
||||
|
||||
info[33723] = 1
|
||||
|
||||
out = str(tmp_path / "temp.tiff")
|
||||
im.save(out, tiffinfo=info)
|
||||
|
||||
with Image.open(out) as reloaded:
|
||||
assert reloaded.tag_v2[33723] == b"1"
|
||||
|
||||
|
||||
def test_undefined_zero(tmp_path):
|
||||
# Check that the tag has not been changed since this test was created
|
||||
tag = TiffTags.TAGS_V2[45059]
|
||||
|
@ -239,7 +252,8 @@ def test_empty_metadata():
|
|||
head = f.read(8)
|
||||
info = TiffImagePlugin.ImageFileDirectory(head)
|
||||
# Should not raise struct.error.
|
||||
pytest.warns(UserWarning, info.load, f)
|
||||
with pytest.warns(UserWarning):
|
||||
info.load(f)
|
||||
|
||||
|
||||
def test_iccprofile(tmp_path):
|
||||
|
@ -405,11 +419,12 @@ def test_too_many_entries():
|
|||
ifd = TiffImagePlugin.ImageFileDirectory_v2()
|
||||
|
||||
# 277: ("SamplesPerPixel", SHORT, 1),
|
||||
ifd._tagdata[277] = struct.pack("hh", 4, 4)
|
||||
ifd._tagdata[277] = struct.pack("<hh", 4, 4)
|
||||
ifd.tagtype[277] = TiffTags.SHORT
|
||||
|
||||
# Should not raise ValueError.
|
||||
pytest.warns(UserWarning, lambda: ifd[277])
|
||||
with pytest.warns(UserWarning):
|
||||
assert ifd[277] == 4
|
||||
|
||||
|
||||
def test_tag_group_data():
|
||||
|
|
|
@ -29,7 +29,10 @@ class TestUnsupportedWebp:
|
|||
WebPImagePlugin.SUPPORTED = False
|
||||
|
||||
file_path = "Tests/images/hopper.webp"
|
||||
pytest.warns(UserWarning, lambda: pytest.raises(OSError, Image.open, file_path))
|
||||
with pytest.warns(UserWarning):
|
||||
with pytest.raises(OSError):
|
||||
with Image.open(file_path):
|
||||
pass
|
||||
|
||||
if HAVE_WEBP:
|
||||
WebPImagePlugin.SUPPORTED = True
|
||||
|
|
|
@ -18,10 +18,8 @@ except ImportError:
|
|||
|
||||
|
||||
def test_read_exif_metadata():
|
||||
|
||||
file_path = "Tests/images/flower.webp"
|
||||
with Image.open(file_path) as image:
|
||||
|
||||
assert image.format == "WEBP"
|
||||
exif_data = image.info.get("exif", None)
|
||||
assert exif_data
|
||||
|
@ -64,10 +62,8 @@ def test_write_exif_metadata():
|
|||
|
||||
|
||||
def test_read_icc_profile():
|
||||
|
||||
file_path = "Tests/images/flower2.webp"
|
||||
with Image.open(file_path) as image:
|
||||
|
||||
assert image.format == "WEBP"
|
||||
assert image.info.get("icc_profile", None)
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ from .helper import assert_image_similar_tofile, hopper
|
|||
|
||||
|
||||
def test_load_raw():
|
||||
|
||||
# Test basic EMF open and rendering
|
||||
with Image.open("Tests/images/drawing.emf") as im:
|
||||
if hasattr(Image.core, "drawwmf"):
|
||||
|
|
|
@ -44,7 +44,6 @@ def test_open():
|
|||
|
||||
# Act
|
||||
with Image.open(filename) as im:
|
||||
|
||||
# Assert
|
||||
assert im.mode == "1"
|
||||
assert im.size == (128, 128)
|
||||
|
@ -57,7 +56,6 @@ def test_open_filename_with_underscore():
|
|||
|
||||
# Act
|
||||
with Image.open(filename) as im:
|
||||
|
||||
# Assert
|
||||
assert im.mode == "1"
|
||||
assert im.size == (128, 128)
|
||||
|
|
|
@ -10,7 +10,6 @@ TEST_FILE = "Tests/images/hopper.p7"
|
|||
def test_open():
|
||||
# Act
|
||||
with Image.open(TEST_FILE) as im:
|
||||
|
||||
# Assert
|
||||
assert im.format == "XVThumb"
|
||||
|
||||
|
|
|
@ -69,7 +69,6 @@ class TestImage:
|
|||
assert issubclass(UnidentifiedImageError, OSError)
|
||||
|
||||
def test_sanity(self):
|
||||
|
||||
im = Image.new("L", (100, 100))
|
||||
assert repr(im)[:45] == "<PIL.Image.Image image mode=L size=100x100 at"
|
||||
assert im.mode == "L"
|
||||
|
@ -1007,7 +1006,6 @@ def mock_encode(*args):
|
|||
|
||||
class TestRegistry:
|
||||
def test_encode_registry(self):
|
||||
|
||||
Image.register_encoder("MOCK", mock_encode)
|
||||
assert "MOCK" in Image.ENCODERS
|
||||
|
||||
|
|
|
@ -132,22 +132,26 @@ class TestImageGetPixel(AccessTest):
|
|||
return 1
|
||||
return tuple(range(1, bands + 1))
|
||||
|
||||
def check(self, mode, c=None):
|
||||
if not c:
|
||||
c = self.color(mode)
|
||||
def check(self, mode, expected_color=None):
|
||||
if not expected_color:
|
||||
expected_color = self.color(mode)
|
||||
|
||||
# check putpixel
|
||||
im = Image.new(mode, (1, 1), None)
|
||||
im.putpixel((0, 0), c)
|
||||
assert (
|
||||
im.getpixel((0, 0)) == c
|
||||
), f"put/getpixel roundtrip failed for mode {mode}, color {c}"
|
||||
im.putpixel((0, 0), expected_color)
|
||||
actual_color = im.getpixel((0, 0))
|
||||
assert actual_color == expected_color, (
|
||||
f"put/getpixel roundtrip failed for mode {mode}, "
|
||||
f"expected {expected_color} got {actual_color}"
|
||||
)
|
||||
|
||||
# check putpixel negative index
|
||||
im.putpixel((-1, -1), c)
|
||||
assert (
|
||||
im.getpixel((-1, -1)) == c
|
||||
), f"put/getpixel roundtrip negative index failed for mode {mode}, color {c}"
|
||||
im.putpixel((-1, -1), expected_color)
|
||||
actual_color = im.getpixel((-1, -1))
|
||||
assert actual_color == expected_color, (
|
||||
f"put/getpixel roundtrip negative index failed for mode {mode}, "
|
||||
f"expected {expected_color} got {actual_color}"
|
||||
)
|
||||
|
||||
# Check 0
|
||||
im = Image.new(mode, (0, 0), None)
|
||||
|
@ -155,27 +159,32 @@ class TestImageGetPixel(AccessTest):
|
|||
|
||||
error = ValueError if self._need_cffi_access else IndexError
|
||||
with pytest.raises(error):
|
||||
im.putpixel((0, 0), c)
|
||||
im.putpixel((0, 0), expected_color)
|
||||
with pytest.raises(error):
|
||||
im.getpixel((0, 0))
|
||||
# Check 0 negative index
|
||||
with pytest.raises(error):
|
||||
im.putpixel((-1, -1), c)
|
||||
im.putpixel((-1, -1), expected_color)
|
||||
with pytest.raises(error):
|
||||
im.getpixel((-1, -1))
|
||||
|
||||
# check initial color
|
||||
im = Image.new(mode, (1, 1), c)
|
||||
assert (
|
||||
im.getpixel((0, 0)) == c
|
||||
), f"initial color failed for mode {mode}, color {c} "
|
||||
im = Image.new(mode, (1, 1), expected_color)
|
||||
actual_color = im.getpixel((0, 0))
|
||||
assert actual_color == expected_color, (
|
||||
f"initial color failed for mode {mode}, "
|
||||
f"expected {expected_color} got {actual_color}"
|
||||
)
|
||||
|
||||
# check initial color negative index
|
||||
assert (
|
||||
im.getpixel((-1, -1)) == c
|
||||
), f"initial color failed with negative index for mode {mode}, color {c} "
|
||||
actual_color = im.getpixel((-1, -1))
|
||||
assert actual_color == expected_color, (
|
||||
f"initial color failed with negative index for mode {mode}, "
|
||||
f"expected {expected_color} got {actual_color}"
|
||||
)
|
||||
|
||||
# Check 0
|
||||
im = Image.new(mode, (0, 0), c)
|
||||
im = Image.new(mode, (0, 0), expected_color)
|
||||
with pytest.raises(error):
|
||||
im.getpixel((0, 0))
|
||||
# Check 0 negative index
|
||||
|
@ -205,13 +214,13 @@ class TestImageGetPixel(AccessTest):
|
|||
self.check(mode)
|
||||
|
||||
@pytest.mark.parametrize("mode", ("I;16", "I;16B"))
|
||||
def test_signedness(self, mode):
|
||||
@pytest.mark.parametrize(
|
||||
"expected_color", (2**15 - 1, 2**15, 2**15 + 1, 2**16 - 1)
|
||||
)
|
||||
def test_signedness(self, mode, expected_color):
|
||||
# see https://github.com/python-pillow/Pillow/issues/452
|
||||
# pixelaccess is using signed int* instead of uint*
|
||||
self.check(mode, 2**15 - 1)
|
||||
self.check(mode, 2**15)
|
||||
self.check(mode, 2**15 + 1)
|
||||
self.check(mode, 2**16 - 1)
|
||||
self.check(mode, expected_color)
|
||||
|
||||
@pytest.mark.parametrize("mode", ("P", "PA"))
|
||||
@pytest.mark.parametrize("color", ((255, 0, 0), (255, 0, 0, 255)))
|
||||
|
|
|
@ -45,7 +45,6 @@ def test_unsupported_conversion():
|
|||
|
||||
|
||||
def test_default():
|
||||
|
||||
im = hopper("P")
|
||||
assert im.mode == "P"
|
||||
converted_im = im.convert()
|
||||
|
@ -255,17 +254,6 @@ def test_p2pa_palette():
|
|||
assert im_pa.getpalette() == im.getpalette()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mode", ("RGB", "RGBA", "RGBX"))
|
||||
def test_rgb_lab(mode):
|
||||
im = Image.new(mode, (1, 1))
|
||||
converted_im = im.convert("LAB")
|
||||
assert converted_im.getpixel((0, 0)) == (0, 128, 128)
|
||||
|
||||
im = Image.new("LAB", (1, 1), (255, 0, 0))
|
||||
converted_im = im.convert(mode)
|
||||
assert converted_im.getpixel((0, 0))[:3] == (0, 255, 255)
|
||||
|
||||
|
||||
def test_matrix_illegal_conversion():
|
||||
# Arrange
|
||||
im = hopper("CMYK")
|
||||
|
|
|
@ -86,7 +86,6 @@ def test_crop_crash():
|
|||
|
||||
|
||||
def test_crop_zero():
|
||||
|
||||
im = Image.new("RGB", (0, 0), "white")
|
||||
|
||||
cropped = im.crop((0, 0, 0, 0))
|
||||
|
|
|
@ -1,10 +1,17 @@
|
|||
import pytest
|
||||
|
||||
from PIL import Image
|
||||
|
||||
from .helper import assert_image_equal, hopper
|
||||
|
||||
|
||||
def test_sanity():
|
||||
@pytest.mark.parametrize("data_type", ("bytes", "memoryview"))
|
||||
def test_sanity(data_type):
|
||||
im1 = hopper()
|
||||
im2 = Image.frombytes(im1.mode, im1.size, im1.tobytes())
|
||||
|
||||
data = im1.tobytes()
|
||||
if data_type == "memoryview":
|
||||
data = memoryview(data)
|
||||
im2 = Image.frombytes(im1.mode, im1.size, data)
|
||||
|
||||
assert_image_equal(im1, im2)
|
||||
|
|
|
@ -4,7 +4,6 @@ from .helper import hopper
|
|||
|
||||
|
||||
def test_sanity():
|
||||
|
||||
bbox = hopper().getbbox()
|
||||
assert isinstance(bbox, tuple)
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ from .helper import hopper
|
|||
|
||||
|
||||
def test_sanity():
|
||||
|
||||
with hopper() as im:
|
||||
im.mode
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ def test_resample():
|
|||
# >>> im.save('Tests/images/hopper_45.png')
|
||||
|
||||
with Image.open("Tests/images/hopper_45.png") as target:
|
||||
for (resample, epsilon) in (
|
||||
for resample, epsilon in (
|
||||
(Image.Resampling.NEAREST, 10),
|
||||
(Image.Resampling.BILINEAR, 5),
|
||||
(Image.Resampling.BICUBIC, 0),
|
||||
|
|
|
@ -4,7 +4,6 @@ from .helper import assert_image_equal, fromstring, hopper
|
|||
|
||||
|
||||
def test_sanity():
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
hopper().tobitmap()
|
||||
|
||||
|
|
|
@ -50,7 +50,6 @@ def test_add():
|
|||
# Arrange
|
||||
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
|
||||
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
|
||||
|
||||
# Act
|
||||
new = ImageChops.add(im1, im2)
|
||||
|
||||
|
@ -63,7 +62,6 @@ def test_add_scale_offset():
|
|||
# Arrange
|
||||
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
|
||||
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
|
||||
|
||||
# Act
|
||||
new = ImageChops.add(im1, im2, scale=2.5, offset=100)
|
||||
|
||||
|
@ -87,7 +85,6 @@ def test_add_modulo():
|
|||
# Arrange
|
||||
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
|
||||
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
|
||||
|
||||
# Act
|
||||
new = ImageChops.add_modulo(im1, im2)
|
||||
|
||||
|
@ -111,7 +108,6 @@ def test_blend():
|
|||
# Arrange
|
||||
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
|
||||
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
|
||||
|
||||
# Act
|
||||
new = ImageChops.blend(im1, im2, 0.5)
|
||||
|
||||
|
@ -137,7 +133,6 @@ def test_darker_image():
|
|||
# Arrange
|
||||
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
|
||||
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
|
||||
|
||||
# Act
|
||||
new = ImageChops.darker(im1, im2)
|
||||
|
||||
|
@ -149,7 +144,6 @@ def test_darker_pixel():
|
|||
# Arrange
|
||||
im1 = hopper()
|
||||
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
|
||||
|
||||
# Act
|
||||
new = ImageChops.darker(im1, im2)
|
||||
|
||||
|
@ -161,7 +155,6 @@ def test_difference():
|
|||
# Arrange
|
||||
with Image.open("Tests/images/imagedraw_arc_end_le_start.png") as im1:
|
||||
with Image.open("Tests/images/imagedraw_arc_no_loops.png") as im2:
|
||||
|
||||
# Act
|
||||
new = ImageChops.difference(im1, im2)
|
||||
|
||||
|
@ -173,7 +166,6 @@ def test_difference_pixel():
|
|||
# Arrange
|
||||
im1 = hopper()
|
||||
with Image.open("Tests/images/imagedraw_polygon_kite_RGB.png") as im2:
|
||||
|
||||
# Act
|
||||
new = ImageChops.difference(im1, im2)
|
||||
|
||||
|
@ -195,7 +187,6 @@ def test_duplicate():
|
|||
def test_invert():
|
||||
# Arrange
|
||||
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im:
|
||||
|
||||
# Act
|
||||
new = ImageChops.invert(im)
|
||||
|
||||
|
@ -209,7 +200,6 @@ def test_lighter_image():
|
|||
# Arrange
|
||||
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
|
||||
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
|
||||
|
||||
# Act
|
||||
new = ImageChops.lighter(im1, im2)
|
||||
|
||||
|
@ -221,7 +211,6 @@ def test_lighter_pixel():
|
|||
# Arrange
|
||||
im1 = hopper()
|
||||
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
|
||||
|
||||
# Act
|
||||
new = ImageChops.lighter(im1, im2)
|
||||
|
||||
|
@ -275,7 +264,6 @@ def test_offset():
|
|||
xoffset = 45
|
||||
yoffset = 20
|
||||
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im:
|
||||
|
||||
# Act
|
||||
new = ImageChops.offset(im, xoffset, yoffset)
|
||||
|
||||
|
@ -292,7 +280,6 @@ def test_screen():
|
|||
# Arrange
|
||||
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
|
||||
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
|
||||
|
||||
# Act
|
||||
new = ImageChops.screen(im1, im2)
|
||||
|
||||
|
@ -305,7 +292,6 @@ def test_subtract():
|
|||
# Arrange
|
||||
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
|
||||
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
|
||||
|
||||
# Act
|
||||
new = ImageChops.subtract(im1, im2)
|
||||
|
||||
|
@ -319,7 +305,6 @@ def test_subtract_scale_offset():
|
|||
# Arrange
|
||||
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
|
||||
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
|
||||
|
||||
# Act
|
||||
new = ImageChops.subtract(im1, im2, scale=2.5, offset=100)
|
||||
|
||||
|
@ -332,7 +317,6 @@ def test_subtract_clip():
|
|||
# Arrange
|
||||
im1 = hopper()
|
||||
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
|
||||
|
||||
# Act
|
||||
new = ImageChops.subtract(im1, im2)
|
||||
|
||||
|
@ -344,7 +328,6 @@ def test_subtract_modulo():
|
|||
# Arrange
|
||||
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
|
||||
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
|
||||
|
||||
# Act
|
||||
new = ImageChops.subtract_modulo(im1, im2)
|
||||
|
||||
|
@ -358,7 +341,6 @@ def test_subtract_modulo_no_clip():
|
|||
# Arrange
|
||||
im1 = hopper()
|
||||
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
|
||||
|
||||
# Act
|
||||
new = ImageChops.subtract_modulo(im1, im2)
|
||||
|
||||
|
@ -370,7 +352,6 @@ def test_soft_light():
|
|||
# Arrange
|
||||
with Image.open("Tests/images/hopper.png") as im1:
|
||||
with Image.open("Tests/images/hopper-XYZ.png") as im2:
|
||||
|
||||
# Act
|
||||
new = ImageChops.soft_light(im1, im2)
|
||||
|
||||
|
@ -383,7 +364,6 @@ def test_hard_light():
|
|||
# Arrange
|
||||
with Image.open("Tests/images/hopper.png") as im1:
|
||||
with Image.open("Tests/images/hopper-XYZ.png") as im2:
|
||||
|
||||
# Act
|
||||
new = ImageChops.hard_light(im1, im2)
|
||||
|
||||
|
@ -396,7 +376,6 @@ def test_overlay():
|
|||
# Arrange
|
||||
with Image.open("Tests/images/hopper.png") as im1:
|
||||
with Image.open("Tests/images/hopper-XYZ.png") as im2:
|
||||
|
||||
# Act
|
||||
new = ImageChops.overlay(im1, im2)
|
||||
|
||||
|
|
|
@ -625,3 +625,14 @@ def test_constants_deprecation():
|
|||
for name in enum.__members__:
|
||||
with pytest.warns(DeprecationWarning):
|
||||
assert getattr(ImageCms, prefix + name) == enum[name]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mode", ("RGB", "RGBA", "RGBX"))
|
||||
def test_rgb_lab(mode):
|
||||
im = Image.new(mode, (1, 1))
|
||||
converted_im = im.convert("LAB")
|
||||
assert converted_im.getpixel((0, 0)) == (0, 128, 128)
|
||||
|
||||
im = Image.new("LAB", (1, 1), (255, 0, 0))
|
||||
converted_im = im.convert(mode)
|
||||
assert converted_im.getpixel((0, 0))[:3] == (0, 255, 255)
|
||||
|
|
|
@ -52,7 +52,6 @@ def test_sanity():
|
|||
|
||||
def test_valueerror():
|
||||
with Image.open("Tests/images/chi.gif") as im:
|
||||
|
||||
draw = ImageDraw.Draw(im)
|
||||
draw.line((0, 0), fill=(0, 0, 0))
|
||||
|
||||
|
@ -356,7 +355,13 @@ def ellipse_various_sizes_helper(filled):
|
|||
for w in ellipse_sizes:
|
||||
y = 1
|
||||
for h in ellipse_sizes:
|
||||
border = [x, y, x + w - 1, y + h - 1]
|
||||
x1 = x + w
|
||||
if w:
|
||||
x1 -= 1
|
||||
y1 = y + h
|
||||
if h:
|
||||
y1 -= 1
|
||||
border = [x, y, x1, y1]
|
||||
if filled:
|
||||
draw.ellipse(border, fill="white")
|
||||
else:
|
||||
|
@ -736,6 +741,36 @@ def test_rounded_rectangle(xy):
|
|||
assert_image_equal_tofile(im, "Tests/images/imagedraw_rounded_rectangle.png")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("top_left", (True, False))
|
||||
@pytest.mark.parametrize("top_right", (True, False))
|
||||
@pytest.mark.parametrize("bottom_right", (True, False))
|
||||
@pytest.mark.parametrize("bottom_left", (True, False))
|
||||
def test_rounded_rectangle_corners(top_left, top_right, bottom_right, bottom_left):
|
||||
corners = (top_left, top_right, bottom_right, bottom_left)
|
||||
|
||||
# Arrange
|
||||
im = Image.new("RGB", (200, 200))
|
||||
draw = ImageDraw.Draw(im)
|
||||
|
||||
# Act
|
||||
draw.rounded_rectangle(
|
||||
(10, 20, 190, 180), 30, fill="red", outline="green", width=5, corners=corners
|
||||
)
|
||||
|
||||
# Assert
|
||||
suffix = "".join(
|
||||
(
|
||||
("y" if top_left else "n"),
|
||||
("y" if top_right else "n"),
|
||||
("y" if bottom_right else "n"),
|
||||
("y" if bottom_left else "n"),
|
||||
)
|
||||
)
|
||||
assert_image_equal_tofile(
|
||||
im, "Tests/images/imagedraw_rounded_rectangle_corners_" + suffix + ".png"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"xy, radius, type",
|
||||
[
|
||||
|
@ -903,9 +938,6 @@ def test_square():
|
|||
img, draw = create_base_image_draw((10, 10))
|
||||
draw.rectangle((2, 2, 7, 7), BLACK)
|
||||
assert_image_equal_tofile(img, expected, "square as normal rectangle failed")
|
||||
img, draw = create_base_image_draw((10, 10))
|
||||
draw.rectangle((7, 7, 2, 2), BLACK)
|
||||
assert_image_equal_tofile(img, expected, "square as inverted rectangle failed")
|
||||
|
||||
|
||||
def test_triangle_right():
|
||||
|
@ -1470,3 +1502,21 @@ def test_polygon2():
|
|||
draw.polygon([(18, 30), (19, 31), (18, 30), (85, 30), (60, 72)], "red")
|
||||
expected = "Tests/images/imagedraw_outline_polygon_RGB.png"
|
||||
assert_image_similar_tofile(im, expected, 1)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("xy", ((1, 1, 0, 1), (1, 1, 1, 0)))
|
||||
def test_incorrectly_ordered_coordinates(xy):
|
||||
im = Image.new("RGB", (W, H))
|
||||
draw = ImageDraw.Draw(im)
|
||||
with pytest.raises(ValueError):
|
||||
draw.arc(xy, 10, 260)
|
||||
with pytest.raises(ValueError):
|
||||
draw.chord(xy, 10, 260)
|
||||
with pytest.raises(ValueError):
|
||||
draw.ellipse(xy)
|
||||
with pytest.raises(ValueError):
|
||||
draw.pieslice(xy, 10, 260)
|
||||
with pytest.raises(ValueError):
|
||||
draw.rectangle(xy)
|
||||
with pytest.raises(ValueError):
|
||||
draw.rounded_rectangle(xy)
|
||||
|
|
|
@ -30,7 +30,6 @@ SAFEBLOCK = ImageFile.SAFEBLOCK
|
|||
class TestImageFile:
|
||||
def test_parser(self):
|
||||
def roundtrip(format):
|
||||
|
||||
im = hopper("L").resize((1000, 1000), Image.Resampling.NEAREST)
|
||||
if format in ("MSP", "XBM"):
|
||||
im = im.convert("1")
|
||||
|
|
|
@ -351,7 +351,8 @@ def test_rotated_transposed_font(font, orientation):
|
|||
assert bbox_b[3] == 20 + bbox_a[2] - bbox_a[0]
|
||||
|
||||
# text length is undefined for vertical text
|
||||
pytest.raises(ValueError, draw.textlength, word)
|
||||
with pytest.raises(ValueError):
|
||||
draw.textlength(word)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
@ -872,25 +873,23 @@ def test_anchor_invalid(font):
|
|||
d.font = font
|
||||
|
||||
for anchor in ["", "l", "a", "lax", "sa", "xa", "lx"]:
|
||||
pytest.raises(ValueError, lambda: font.getmask2("hello", anchor=anchor))
|
||||
pytest.raises(ValueError, lambda: font.getbbox("hello", anchor=anchor))
|
||||
pytest.raises(ValueError, lambda: d.text((0, 0), "hello", anchor=anchor))
|
||||
pytest.raises(ValueError, lambda: d.textbbox((0, 0), "hello", anchor=anchor))
|
||||
pytest.raises(
|
||||
ValueError, lambda: d.multiline_text((0, 0), "foo\nbar", anchor=anchor)
|
||||
)
|
||||
pytest.raises(
|
||||
ValueError,
|
||||
lambda: d.multiline_textbbox((0, 0), "foo\nbar", anchor=anchor),
|
||||
)
|
||||
with pytest.raises(ValueError):
|
||||
font.getmask2("hello", anchor=anchor)
|
||||
with pytest.raises(ValueError):
|
||||
font.getbbox("hello", anchor=anchor)
|
||||
with pytest.raises(ValueError):
|
||||
d.text((0, 0), "hello", anchor=anchor)
|
||||
with pytest.raises(ValueError):
|
||||
d.textbbox((0, 0), "hello", anchor=anchor)
|
||||
with pytest.raises(ValueError):
|
||||
d.multiline_text((0, 0), "foo\nbar", anchor=anchor)
|
||||
with pytest.raises(ValueError):
|
||||
d.multiline_textbbox((0, 0), "foo\nbar", anchor=anchor)
|
||||
for anchor in ["lt", "lb"]:
|
||||
pytest.raises(
|
||||
ValueError, lambda: d.multiline_text((0, 0), "foo\nbar", anchor=anchor)
|
||||
)
|
||||
pytest.raises(
|
||||
ValueError,
|
||||
lambda: d.multiline_textbbox((0, 0), "foo\nbar", anchor=anchor),
|
||||
)
|
||||
with pytest.raises(ValueError):
|
||||
d.multiline_text((0, 0), "foo\nbar", anchor=anchor)
|
||||
with pytest.raises(ValueError):
|
||||
d.multiline_textbbox((0, 0), "foo\nbar", anchor=anchor)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("bpp", (1, 2, 4, 8))
|
||||
|
|
|
@ -360,37 +360,20 @@ def test_anchor_invalid_ttb():
|
|||
d.font = font
|
||||
|
||||
for anchor in ["", "l", "a", "lax", "xa", "la", "ls", "ld", "lx"]:
|
||||
pytest.raises(
|
||||
ValueError, lambda: font.getmask2("hello", anchor=anchor, direction="ttb")
|
||||
)
|
||||
pytest.raises(
|
||||
ValueError, lambda: font.getbbox("hello", anchor=anchor, direction="ttb")
|
||||
)
|
||||
pytest.raises(
|
||||
ValueError, lambda: d.text((0, 0), "hello", anchor=anchor, direction="ttb")
|
||||
)
|
||||
pytest.raises(
|
||||
ValueError,
|
||||
lambda: d.textbbox((0, 0), "hello", anchor=anchor, direction="ttb"),
|
||||
)
|
||||
pytest.raises(
|
||||
ValueError,
|
||||
lambda: d.multiline_text(
|
||||
(0, 0), "foo\nbar", anchor=anchor, direction="ttb"
|
||||
),
|
||||
)
|
||||
pytest.raises(
|
||||
ValueError,
|
||||
lambda: d.multiline_textbbox(
|
||||
(0, 0), "foo\nbar", anchor=anchor, direction="ttb"
|
||||
),
|
||||
)
|
||||
with pytest.raises(ValueError):
|
||||
font.getmask2("hello", anchor=anchor, direction="ttb")
|
||||
with pytest.raises(ValueError):
|
||||
font.getbbox("hello", anchor=anchor, direction="ttb")
|
||||
with pytest.raises(ValueError):
|
||||
d.text((0, 0), "hello", anchor=anchor, direction="ttb")
|
||||
with pytest.raises(ValueError):
|
||||
d.textbbox((0, 0), "hello", anchor=anchor, direction="ttb")
|
||||
with pytest.raises(ValueError):
|
||||
d.multiline_text((0, 0), "foo\nbar", anchor=anchor, direction="ttb")
|
||||
with pytest.raises(ValueError):
|
||||
d.multiline_textbbox((0, 0), "foo\nbar", anchor=anchor, direction="ttb")
|
||||
# ttb multiline text does not support anchors at all
|
||||
pytest.raises(
|
||||
ValueError,
|
||||
lambda: d.multiline_text((0, 0), "foo\nbar", anchor="mm", direction="ttb"),
|
||||
)
|
||||
pytest.raises(
|
||||
ValueError,
|
||||
lambda: d.multiline_textbbox((0, 0), "foo\nbar", anchor="mm", direction="ttb"),
|
||||
)
|
||||
with pytest.raises(ValueError):
|
||||
d.multiline_text((0, 0), "foo\nbar", anchor="mm", direction="ttb")
|
||||
with pytest.raises(ValueError):
|
||||
d.multiline_textbbox((0, 0), "foo\nbar", anchor="mm", direction="ttb")
|
||||
|
|
|
@ -21,7 +21,6 @@ deformer = Deformer()
|
|||
|
||||
|
||||
def test_sanity():
|
||||
|
||||
ImageOps.autocontrast(hopper("L"))
|
||||
ImageOps.autocontrast(hopper("RGB"))
|
||||
|
||||
|
@ -419,7 +418,6 @@ def test_autocontrast_cutoff():
|
|||
def test_autocontrast_mask_toy_input():
|
||||
# Test the mask argument of autocontrast
|
||||
with Image.open("Tests/images/bw_gradient.png") as img:
|
||||
|
||||
rect_mask = Image.new("L", img.size, 0)
|
||||
draw = ImageDraw.Draw(rect_mask)
|
||||
x0 = img.size[0] // 4
|
||||
|
@ -439,7 +437,6 @@ def test_autocontrast_mask_toy_input():
|
|||
def test_autocontrast_mask_real_input():
|
||||
# Test the autocontrast with a rectangular mask
|
||||
with Image.open("Tests/images/iptc.jpg") as img:
|
||||
|
||||
rect_mask = Image.new("L", img.size, 0)
|
||||
draw = ImageDraw.Draw(rect_mask)
|
||||
x0, y0 = img.size[0] // 2, img.size[1] // 2
|
||||
|
|
|
@ -6,7 +6,6 @@ from .helper import assert_image_equal, assert_image_equal_tofile
|
|||
|
||||
|
||||
def test_sanity():
|
||||
|
||||
palette = ImagePalette.ImagePalette("RGB", list(range(256)) * 3)
|
||||
assert len(palette.colors) == 256
|
||||
|
||||
|
@ -23,7 +22,6 @@ def test_reload():
|
|||
|
||||
|
||||
def test_getcolor():
|
||||
|
||||
palette = ImagePalette.ImagePalette()
|
||||
assert len(palette.palette) == 0
|
||||
assert len(palette.colors) == 0
|
||||
|
@ -84,7 +82,6 @@ def test_getcolor_not_special(index, palette):
|
|||
|
||||
|
||||
def test_file(tmp_path):
|
||||
|
||||
palette = ImagePalette.ImagePalette("RGB", list(range(256)) * 3)
|
||||
|
||||
f = str(tmp_path / "temp.lut")
|
||||
|
|
|
@ -8,7 +8,6 @@ from PIL import Image, ImagePath
|
|||
|
||||
|
||||
def test_path():
|
||||
|
||||
p = ImagePath.Path(list(range(10)))
|
||||
|
||||
# sequence interface
|
||||
|
|
|
@ -6,7 +6,6 @@ from .helper import assert_image_equal, hopper, skip_unless_feature
|
|||
|
||||
|
||||
def test_sanity(tmp_path):
|
||||
|
||||
test_file = str(tmp_path / "temp.im")
|
||||
|
||||
im = hopper("RGB")
|
||||
|
|
|
@ -55,8 +55,8 @@ def test_show_without_viewers():
|
|||
viewers = ImageShow._viewers
|
||||
ImageShow._viewers = []
|
||||
|
||||
im = hopper()
|
||||
assert not ImageShow.show(im)
|
||||
with hopper() as im:
|
||||
assert not ImageShow.show(im)
|
||||
|
||||
ImageShow._viewers = viewers
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ from .helper import hopper
|
|||
|
||||
|
||||
def test_sanity():
|
||||
|
||||
im = hopper()
|
||||
|
||||
st = ImageStat.Stat(im)
|
||||
|
@ -31,7 +30,6 @@ def test_sanity():
|
|||
|
||||
|
||||
def test_hopper():
|
||||
|
||||
im = hopper()
|
||||
|
||||
st = ImageStat.Stat(im)
|
||||
|
@ -45,7 +43,6 @@ def test_hopper():
|
|||
|
||||
|
||||
def test_constant():
|
||||
|
||||
im = Image.new("L", (128, 128), 128)
|
||||
|
||||
st = ImageStat.Stat(im)
|
||||
|
|
|
@ -100,8 +100,11 @@ class TestImageWinDib:
|
|||
# Act
|
||||
# Make one the same as the using tobytes()/frombytes()
|
||||
test_buffer = dib1.tobytes()
|
||||
dib2.frombytes(test_buffer)
|
||||
for datatype in ("bytes", "memoryview"):
|
||||
if datatype == "memoryview":
|
||||
test_buffer = memoryview(test_buffer)
|
||||
dib2.frombytes(test_buffer)
|
||||
|
||||
# Assert
|
||||
# Confirm they're the same
|
||||
assert dib1.tobytes() == dib2.tobytes()
|
||||
# Assert
|
||||
# Confirm they're the same
|
||||
assert dib1.tobytes() == dib2.tobytes()
|
||||
|
|
|
@ -4,7 +4,6 @@ from PIL import Image
|
|||
|
||||
|
||||
def test_setmode():
|
||||
|
||||
im = Image.new("L", (1, 1), 255)
|
||||
im.im.setmode("1")
|
||||
assert im.im.getpixel((0, 0)) == 255
|
||||
|
|
|
@ -42,7 +42,6 @@ def test_basic(tmp_path, mode):
|
|||
im_in.save(filename)
|
||||
|
||||
with Image.open(filename) as im_out:
|
||||
|
||||
verify(im_in)
|
||||
verify(im_out)
|
||||
|
||||
|
@ -87,7 +86,6 @@ def test_tobytes():
|
|||
|
||||
|
||||
def test_convert():
|
||||
|
||||
im = original.copy()
|
||||
|
||||
verify(im.convert("I;16"))
|
||||
|
|
|
@ -235,7 +235,6 @@ def test_no_resource_warning_for_numpy_array():
|
|||
|
||||
test_file = "Tests/images/hopper.png"
|
||||
with Image.open(test_file) as im:
|
||||
|
||||
# Act/Assert
|
||||
with warnings.catch_warnings():
|
||||
array(im)
|
||||
|
|
|
@ -89,7 +89,6 @@ def test_pickle_la_mode_with_palette(tmp_path):
|
|||
def test_pickle_tell():
|
||||
# Arrange
|
||||
with Image.open("Tests/images/hopper.webp") as image:
|
||||
|
||||
# Act: roundtrip
|
||||
unpickled_image = pickle.loads(pickle.dumps(image))
|
||||
|
||||
|
|