Merge branch 'main' into main
							
								
								
									
										6
									
								
								.git-blame-ignore-revs
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,6 @@ | ||||||
|  | # Flake8 | ||||||
|  | 8de95676e0fd89f2326b3953488ab66ff29cd2d0 | ||||||
|  | # Format with Black | ||||||
|  | 53a7e3500437a9fd5826bc04758f7116bd7e52dc | ||||||
|  | # Format the C code with ClangFormat | ||||||
|  | 46b7e86bab79450ec0a2866c6c0c679afb659d17 | ||||||
							
								
								
									
										4
									
								
								.github/workflows/cifuzz.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -42,13 +42,13 @@ jobs: | ||||||
|         language: python |         language: python | ||||||
|         dry-run: false |         dry-run: false | ||||||
|     - name: Upload New Crash |     - name: Upload New Crash | ||||||
|       uses: actions/upload-artifact@v3 |       uses: actions/upload-artifact@v4 | ||||||
|       if: failure() && steps.build.outcome == 'success' |       if: failure() && steps.build.outcome == 'success' | ||||||
|       with: |       with: | ||||||
|         name: artifacts |         name: artifacts | ||||||
|         path: ./out/artifacts |         path: ./out/artifacts | ||||||
|     - name: Upload Legacy Crash |     - name: Upload Legacy Crash | ||||||
|       uses: actions/upload-artifact@v3 |       uses: actions/upload-artifact@v4 | ||||||
|       if: steps.run.outcome == 'success' |       if: steps.run.outcome == 'success' | ||||||
|       with: |       with: | ||||||
|         name: crash |         name: crash | ||||||
|  |  | ||||||
							
								
								
									
										6
									
								
								.github/workflows/lint.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -2,6 +2,9 @@ name: Lint | ||||||
| 
 | 
 | ||||||
| on: [push, pull_request, workflow_dispatch] | on: [push, pull_request, workflow_dispatch] | ||||||
| 
 | 
 | ||||||
|  | env: | ||||||
|  |   FORCE_COLOR: 1 | ||||||
|  | 
 | ||||||
| permissions: | permissions: | ||||||
|   contents: read |   contents: read | ||||||
| 
 | 
 | ||||||
|  | @ -46,3 +49,6 @@ jobs: | ||||||
|       run: tox -e lint |       run: tox -e lint | ||||||
|       env: |       env: | ||||||
|         PRE_COMMIT_COLOR: always |         PRE_COMMIT_COLOR: always | ||||||
|  | 
 | ||||||
|  |     - name: Mypy | ||||||
|  |       run: tox -e mypy | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								.github/workflows/system-info.py
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -6,6 +6,8 @@ This sort of info is missing from GitHub Actions. | ||||||
| Requested here: | Requested here: | ||||||
| https://github.com/actions/virtual-environments/issues/79 | https://github.com/actions/virtual-environments/issues/79 | ||||||
| """ | """ | ||||||
|  | from __future__ import annotations | ||||||
|  | 
 | ||||||
| import os | import os | ||||||
| import platform | import platform | ||||||
| import sys | import sys | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								.github/workflows/test-cygwin.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -132,7 +132,7 @@ jobs: | ||||||
|           dash.exe -c "mkdir -p Tests/errors" |           dash.exe -c "mkdir -p Tests/errors" | ||||||
| 
 | 
 | ||||||
|       - name: Upload errors |       - name: Upload errors | ||||||
|         uses: actions/upload-artifact@v3 |         uses: actions/upload-artifact@v4 | ||||||
|         if: failure() |         if: failure() | ||||||
|         with: |         with: | ||||||
|           name: errors |           name: errors | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								.github/workflows/test-windows.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -190,7 +190,7 @@ jobs: | ||||||
|       shell: bash |       shell: bash | ||||||
| 
 | 
 | ||||||
|     - name: Upload errors |     - name: Upload errors | ||||||
|       uses: actions/upload-artifact@v3 |       uses: actions/upload-artifact@v4 | ||||||
|       if: failure() |       if: failure() | ||||||
|       with: |       with: | ||||||
|         name: errors |         name: errors | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -112,7 +112,7 @@ jobs: | ||||||
|         mkdir -p Tests/errors |         mkdir -p Tests/errors | ||||||
| 
 | 
 | ||||||
|     - name: Upload errors |     - name: Upload errors | ||||||
|       uses: actions/upload-artifact@v3 |       uses: actions/upload-artifact@v4 | ||||||
|       if: failure() |       if: failure() | ||||||
|       with: |       with: | ||||||
|         name: errors |         name: errors | ||||||
|  |  | ||||||
|  | @ -1,17 +1,17 @@ | ||||||
| repos: | repos: | ||||||
|   - repo: https://github.com/astral-sh/ruff-pre-commit |   - repo: https://github.com/astral-sh/ruff-pre-commit | ||||||
|     rev: v0.1.6 |     rev: v0.1.7 | ||||||
|     hooks: |     hooks: | ||||||
|       - id: ruff |       - id: ruff | ||||||
|         args: [--fix, --exit-non-zero-on-fix] |         args: [--fix, --exit-non-zero-on-fix] | ||||||
| 
 | 
 | ||||||
|   - repo: https://github.com/psf/black-pre-commit-mirror |   - repo: https://github.com/psf/black-pre-commit-mirror | ||||||
|     rev: 23.11.0 |     rev: 23.12.0 | ||||||
|     hooks: |     hooks: | ||||||
|       - id: black |       - id: black | ||||||
| 
 | 
 | ||||||
|   - repo: https://github.com/PyCQA/bandit |   - repo: https://github.com/PyCQA/bandit | ||||||
|     rev: 1.7.5 |     rev: 1.7.6 | ||||||
|     hooks: |     hooks: | ||||||
|     - id: bandit |     - id: bandit | ||||||
|       args: [--severity-level=high] |       args: [--severity-level=high] | ||||||
|  | @ -42,7 +42,7 @@ repos: | ||||||
|         exclude: ^.github/.*TEMPLATE|^Tests/(fonts|images)/ |         exclude: ^.github/.*TEMPLATE|^Tests/(fonts|images)/ | ||||||
| 
 | 
 | ||||||
|   - repo: https://github.com/sphinx-contrib/sphinx-lint |   - repo: https://github.com/sphinx-contrib/sphinx-lint | ||||||
|     rev: v0.9.0 |     rev: v0.9.1 | ||||||
|     hooks: |     hooks: | ||||||
|       - id: sphinx-lint |       - id: sphinx-lint | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -5,7 +5,7 @@ formats: [pdf] | ||||||
| build: | build: | ||||||
|   os: ubuntu-22.04 |   os: ubuntu-22.04 | ||||||
|   tools: |   tools: | ||||||
|     python: "3.11" |     python: "3" | ||||||
| 
 | 
 | ||||||
| python: | python: | ||||||
|   install: |   install: | ||||||
|  |  | ||||||
							
								
								
									
										24
									
								
								CHANGES.rst
									
									
									
									
									
								
							
							
						
						|  | @ -5,6 +5,30 @@ Changelog (Pillow) | ||||||
| 10.2.0 (unreleased) | 10.2.0 (unreleased) | ||||||
| ------------------- | ------------------- | ||||||
| 
 | 
 | ||||||
|  | - Fix incorrect color blending for overlapping glyphs #7497 | ||||||
|  |   [ZachNagengast, nulano, radarhere] | ||||||
|  | 
 | ||||||
|  | - Attempt memory mapping when tile args is a string #7565 | ||||||
|  |   [radarhere] | ||||||
|  | 
 | ||||||
|  | - Fill identical pixels with transparency in subsequent frames when saving GIF #7568 | ||||||
|  |   [radarhere] | ||||||
|  | 
 | ||||||
|  | - Corrected duration when combining multiple GIF frames into single frame #7521 | ||||||
|  |   [radarhere] | ||||||
|  | 
 | ||||||
|  | - Handle disposing GIF background from outside palette #7515 | ||||||
|  |   [radarhere] | ||||||
|  | 
 | ||||||
|  | - Seek past the data when skipping a PSD layer #7483 | ||||||
|  |   [radarhere] | ||||||
|  | 
 | ||||||
|  | - Import plugins relative to the module #7576 | ||||||
|  |   [deliangyang, jaxx0n] | ||||||
|  | 
 | ||||||
|  | - Translate encoder error codes to strings; deprecate ``ImageFile.raise_oserror()`` #7609 | ||||||
|  |   [bgilbert, radarhere] | ||||||
|  | 
 | ||||||
| - Support reading BC4U and DX10 BC1 images #6486 | - Support reading BC4U and DX10 BC1 images #6486 | ||||||
|   [REDxEYE, radarhere, hugovk] |   [REDxEYE, radarhere, hugovk] | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| #!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||||
|  | from __future__ import annotations | ||||||
| 
 | 
 | ||||||
| import sys | import sys | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import time | import time | ||||||
| 
 | 
 | ||||||
| from PIL import PyAccess | from PIL import PyAccess | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| #!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||||
|  | from __future__ import annotations | ||||||
| 
 | 
 | ||||||
| from PIL import Image | from PIL import Image | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| from PIL import Image | from PIL import Image | ||||||
| 
 | 
 | ||||||
| TEST_FILE = "Tests/images/fli_overflow.fli" | TEST_FILE = "Tests/images/fli_overflow.fli" | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| # Tests potential DOS of IcnsImagePlugin with 0 length block. | # Tests potential DOS of IcnsImagePlugin with 0 length block. | ||||||
| # Run from anywhere that PIL is importable. | # Run from anywhere that PIL is importable. | ||||||
|  | from __future__ import annotations | ||||||
| 
 | 
 | ||||||
| from io import BytesIO | from io import BytesIO | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| #!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||||
|  | from __future__ import annotations | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
| from PIL import Image | from PIL import Image | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| # Tests potential DOS of Jpeg2kImagePlugin with 0 length block. | # Tests potential DOS of Jpeg2kImagePlugin with 0 length block. | ||||||
| # Run from anywhere that PIL is importable. | # Run from anywhere that PIL is importable. | ||||||
|  | from __future__ import annotations | ||||||
| 
 | 
 | ||||||
| from io import BytesIO | from io import BytesIO | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| from io import BytesIO | from io import BytesIO | ||||||
| 
 | 
 | ||||||
| import pytest | import pytest | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
| from PIL import Image | from PIL import Image | ||||||
|  |  | ||||||
|  | @ -12,6 +12,7 @@ | ||||||
| # the output should be empty. There may be python issues | # the output should be empty. There may be python issues | ||||||
| # in the valgrind especially if run in a debug python | # in the valgrind especially if run in a debug python | ||||||
| # version. | # version. | ||||||
|  | from __future__ import annotations | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| from PIL import Image | from PIL import Image | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| from io import BytesIO | from io import BytesIO | ||||||
| 
 | 
 | ||||||
| import pytest | import pytest | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import sys | import sys | ||||||
| 
 | 
 | ||||||
| import pytest | import pytest | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import sys | import sys | ||||||
| 
 | 
 | ||||||
| import pytest | import pytest | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
| from PIL import Image | from PIL import Image | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import zlib | import zlib | ||||||
| from io import BytesIO | from io import BytesIO | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import sys | import sys | ||||||
| from pathlib import Path | from pathlib import Path | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import sys | import sys | ||||||
| 
 | 
 | ||||||
| from PIL import features | from PIL import features | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import io | import io | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| #!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||||
|  | from __future__ import annotations | ||||||
| import base64 | import base64 | ||||||
| import os | import os | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										
											BIN
										
									
								
								Tests/fonts/CBDTTestFont.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Tests/fonts/EBDTTestFont.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -2,7 +2,6 @@ | ||||||
| NotoNastaliqUrdu-Regular.ttf and NotoSansSymbols-Regular.ttf, from https://github.com/googlei18n/noto-fonts | NotoNastaliqUrdu-Regular.ttf and NotoSansSymbols-Regular.ttf, from https://github.com/googlei18n/noto-fonts | ||||||
| NotoSans-Regular.ttf, from https://www.google.com/get/noto/ | NotoSans-Regular.ttf, from https://www.google.com/get/noto/ | ||||||
| NotoSansJP-Thin.otf, from https://www.google.com/get/noto/help/cjk/ | NotoSansJP-Thin.otf, from https://www.google.com/get/noto/help/cjk/ | ||||||
| NotoColorEmoji.ttf, from https://github.com/googlefonts/noto-emoji |  | ||||||
| AdobeVFPrototype.ttf, from https://github.com/adobe-fonts/adobe-variable-font-prototype | AdobeVFPrototype.ttf, from https://github.com/adobe-fonts/adobe-variable-font-prototype | ||||||
| TINY5x3GX.ttf, from http://velvetyne.fr/fonts/tiny | TINY5x3GX.ttf, from http://velvetyne.fr/fonts/tiny | ||||||
| ArefRuqaa-Regular.ttf, from https://github.com/google/fonts/tree/master/ofl/arefruqaa | ArefRuqaa-Regular.ttf, from https://github.com/google/fonts/tree/master/ofl/arefruqaa | ||||||
|  | @ -25,3 +24,5 @@ FreeMono.ttf is licensed under GPLv3. | ||||||
| 10x20-ISO8859-1.pcf, from https://packages.ubuntu.com/xenial/xfonts-base | 10x20-ISO8859-1.pcf, from https://packages.ubuntu.com/xenial/xfonts-base | ||||||
| 
 | 
 | ||||||
| "Public domain font.  Share and enjoy." | "Public domain font.  Share and enjoy." | ||||||
|  | 
 | ||||||
|  | CBDTTestFont.ttf and EBDTTestFont.ttf from https://github.com/nulano/font-tests are public domain. | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| """ | """ | ||||||
| Helper functions. | Helper functions. | ||||||
| """ | """ | ||||||
|  | from __future__ import annotations | ||||||
| 
 | 
 | ||||||
| import logging | import logging | ||||||
| import os | import os | ||||||
|  |  | ||||||
							
								
								
									
										
											BIN
										
									
								
								Tests/images/background_outside_palette.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 82 B | 
							
								
								
									
										
											BIN
										
									
								
								Tests/images/bitmap_font_blend.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 387 B | 
| Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.7 KiB | 
| Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.7 KiB | 
							
								
								
									
										
											BIN
										
									
								
								Tests/images/cbdt.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 348 B | 
							
								
								
									
										
											BIN
										
									
								
								Tests/images/cbdt_mask.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 367 B | 
| Before Width: | Height: | Size: 3.6 KiB | 
| Before Width: | Height: | Size: 3.5 KiB | 
| Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB | 
							
								
								
									
										
											BIN
										
									
								
								Tests/images/five_channels.psd
									
									
									
									
									
										Normal file
									
								
							
							
						
						| Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.2 KiB | 
| Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.2 KiB | 
| Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB | 
| Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB | 
|  | @ -13,6 +13,7 @@ | ||||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
| # See the License for the specific language governing permissions and | # See the License for the specific language governing permissions and | ||||||
| # limitations under the License. | # limitations under the License. | ||||||
|  | from __future__ import annotations | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| import atheris | import atheris | ||||||
|  |  | ||||||
|  | @ -13,6 +13,7 @@ | ||||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
| # See the License for the specific language governing permissions and | # See the License for the specific language governing permissions and | ||||||
| # limitations under the License. | # limitations under the License. | ||||||
|  | from __future__ import annotations | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| import atheris | import atheris | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import io | import io | ||||||
| import warnings | import warnings | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import subprocess | import subprocess | ||||||
| import sys | import sys | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| from PIL import Image | from PIL import Image | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| from PIL import _binary | from PIL import _binary | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import os | import os | ||||||
| import warnings | import warnings | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
| from PIL import Image, ImageFilter | from PIL import Image, ImageFilter | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| from array import array | from array import array | ||||||
| 
 | 
 | ||||||
| import pytest | import pytest | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import sys | import sys | ||||||
| 
 | 
 | ||||||
| import pytest | import pytest | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
| from PIL import Image | from PIL import Image | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
| from PIL import _deprecate | from PIL import _deprecate | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import io | import io | ||||||
| import re | import re | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
| from PIL import Image, ImageSequence, PngImagePlugin | from PIL import Image, ImageSequence, PngImagePlugin | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
| from PIL import Image | from PIL import Image | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import io | import io | ||||||
| 
 | 
 | ||||||
| import pytest | import pytest | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
| from PIL import BufrStubImagePlugin, Image | from PIL import BufrStubImagePlugin, Image | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
| from PIL import ContainerIO, Image | from PIL import ContainerIO, Image | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| from io import BytesIO | from io import BytesIO | ||||||
| 
 | 
 | ||||||
| import pytest | import pytest | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import warnings | import warnings | ||||||
| 
 | 
 | ||||||
| import pytest | import pytest | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| """Test DdsImagePlugin""" | """Test DdsImagePlugin""" | ||||||
|  | from __future__ import annotations | ||||||
| from io import BytesIO | from io import BytesIO | ||||||
| 
 | 
 | ||||||
| import pytest | import pytest | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import io | import io | ||||||
| 
 | 
 | ||||||
| import pytest | import pytest | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| from io import BytesIO | from io import BytesIO | ||||||
| 
 | 
 | ||||||
| import pytest | import pytest | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import warnings | import warnings | ||||||
| 
 | 
 | ||||||
| import pytest | import pytest | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
| from PIL import Image | from PIL import Image | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
| from PIL import FtexImagePlugin, Image | from PIL import FtexImagePlugin, Image | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
| from PIL import GbrImagePlugin, Image | from PIL import GbrImagePlugin, Image | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
| from PIL import GdImageFile, UnidentifiedImageError | from PIL import GdImageFile, UnidentifiedImageError | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import warnings | import warnings | ||||||
| from io import BytesIO | from io import BytesIO | ||||||
| 
 | 
 | ||||||
|  | @ -217,6 +218,27 @@ def test_optimize_if_palette_can_be_reduced_by_half(): | ||||||
|             assert len(reloaded.palette.palette) // 3 == colors |             assert len(reloaded.palette.palette) // 3 == colors | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | def test_full_palette_second_frame(tmp_path): | ||||||
|  |     out = str(tmp_path / "temp.gif") | ||||||
|  |     im = Image.new("P", (1, 256)) | ||||||
|  | 
 | ||||||
|  |     full_palette_im = Image.new("P", (1, 256)) | ||||||
|  |     for i in range(256): | ||||||
|  |         full_palette_im.putpixel((0, i), i) | ||||||
|  |     full_palette_im.palette = ImagePalette.ImagePalette( | ||||||
|  |         "RGB", bytearray(i // 3 for i in range(768)) | ||||||
|  |     ) | ||||||
|  |     full_palette_im.palette.dirty = 1 | ||||||
|  | 
 | ||||||
|  |     im.save(out, save_all=True, append_images=[full_palette_im]) | ||||||
|  | 
 | ||||||
|  |     with Image.open(out) as reloaded: | ||||||
|  |         reloaded.seek(1) | ||||||
|  | 
 | ||||||
|  |         for i in range(256): | ||||||
|  |             reloaded.getpixel((0, i)) == i | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| def test_roundtrip(tmp_path): | def test_roundtrip(tmp_path): | ||||||
|     out = str(tmp_path / "temp.gif") |     out = str(tmp_path / "temp.gif") | ||||||
|     im = hopper() |     im = hopper() | ||||||
|  | @ -856,7 +878,14 @@ def test_identical_frames(tmp_path): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @pytest.mark.parametrize( | @pytest.mark.parametrize( | ||||||
|     "duration", ([1000, 1500, 2000, 4000], (1000, 1500, 2000, 4000), 8500) |     "duration", | ||||||
|  |     ( | ||||||
|  |         [1000, 1500, 2000], | ||||||
|  |         (1000, 1500, 2000), | ||||||
|  |         # One more duration than the number of frames | ||||||
|  |         [1000, 1500, 2000, 4000], | ||||||
|  |         1500, | ||||||
|  |     ), | ||||||
| ) | ) | ||||||
| def test_identical_frames_to_single_frame(duration, tmp_path): | def test_identical_frames_to_single_frame(duration, tmp_path): | ||||||
|     out = str(tmp_path / "temp.gif") |     out = str(tmp_path / "temp.gif") | ||||||
|  | @ -872,7 +901,7 @@ def test_identical_frames_to_single_frame(duration, tmp_path): | ||||||
|         assert reread.n_frames == 1 |         assert reread.n_frames == 1 | ||||||
| 
 | 
 | ||||||
|         # Assert that the new duration is the total of the identical frames |         # Assert that the new duration is the total of the identical frames | ||||||
|         assert reread.info["duration"] == 8500 |         assert reread.info["duration"] == 4500 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def test_loop_none(tmp_path): | def test_loop_none(tmp_path): | ||||||
|  | @ -1142,6 +1171,12 @@ def test_rgba_transparency(tmp_path): | ||||||
|         assert_image_equal(hopper("P").convert("RGB"), reloaded) |         assert_image_equal(hopper("P").convert("RGB"), reloaded) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | def test_background_outside_palettte(tmp_path): | ||||||
|  |     with Image.open("Tests/images/background_outside_palette.gif") as im: | ||||||
|  |         im.seek(1) | ||||||
|  |         assert im.info["background"] == 255 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| def test_bbox(tmp_path): | def test_bbox(tmp_path): | ||||||
|     out = str(tmp_path / "temp.gif") |     out = str(tmp_path / "temp.gif") | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| from PIL import GimpGradientFile, ImagePalette | from PIL import GimpGradientFile, ImagePalette | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
| from PIL.GimpPaletteFile import GimpPaletteFile | from PIL.GimpPaletteFile import GimpPaletteFile | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
| from PIL import GribStubImagePlugin, Image | from PIL import GribStubImagePlugin, Image | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
| from PIL import Hdf5StubImagePlugin, Image | from PIL import Hdf5StubImagePlugin, Image | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import io | import io | ||||||
| import os | import os | ||||||
| import warnings | import warnings | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import io | import io | ||||||
| import os | import os | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import filecmp | import filecmp | ||||||
| import warnings | import warnings | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import io | import io | ||||||
| 
 | 
 | ||||||
| import pytest | import pytest | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import sys | import sys | ||||||
| from io import BytesIO, StringIO | from io import BytesIO, StringIO | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import os | import os | ||||||
| import re | import re | ||||||
| import warnings | import warnings | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import os | import os | ||||||
| import re | import re | ||||||
| from io import BytesIO | from io import BytesIO | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import base64 | import base64 | ||||||
| import io | import io | ||||||
| import itertools | import itertools | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| from io import BytesIO | from io import BytesIO | ||||||
| 
 | 
 | ||||||
| from PIL import Image | from PIL import Image | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
| from PIL import Image, McIdasImagePlugin | from PIL import Image, McIdasImagePlugin | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
| from PIL import Image, ImagePalette | from PIL import Image, ImagePalette | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import warnings | import warnings | ||||||
| from io import BytesIO | from io import BytesIO | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import os | import os | ||||||
| 
 | 
 | ||||||
| import pytest | import pytest | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import os.path | import os.path | ||||||
| import subprocess | import subprocess | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| from PIL import Image | from PIL import Image | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
| from PIL import Image, ImageFile, PcxImagePlugin | from PIL import Image, ImageFile, PcxImagePlugin | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import io | import io | ||||||
| import os | import os | ||||||
| import os.path | import os.path | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
| from PIL import Image, PixarImagePlugin | from PIL import Image, PixarImagePlugin | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | from __future__ import annotations | ||||||
| import re | import re | ||||||
| import sys | import sys | ||||||
| import warnings | import warnings | ||||||
|  |  | ||||||