Merge branch 'main' into bgr32

This commit is contained in:
Andrew Murray 2023-03-25 23:45:48 +11:00
commit d5d830dd00
55 changed files with 319 additions and 167 deletions

View File

@ -27,8 +27,8 @@ install:
- mv c:\pillow-depends-main c:\pillow-depends - mv c:\pillow-depends-main c:\pillow-depends
- xcopy /S /Y c:\test-images-main\* 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:\ - 7z x ..\pillow-depends\nasm-2.15.05-win64.zip -oc:\
- ..\pillow-depends\gs1000w32.exe /S - choco install ghostscript --version=10.0.0.20230317
- path c:\nasm-2.15.05;C:\Program Files (x86)\gs\gs10.0.0\bin;%PATH% - path c:\nasm-2.15.05;C:\Program Files\gs\gs10.00.0\bin;%PATH%
- cd c:\pillow\winbuild\ - cd c:\pillow\winbuild\
- ps: | - ps: |
c:\python37\python.exe c:\pillow\winbuild\build_prepare.py -v --depends=C:\pillow-depends\ c:\python37\python.exe c:\pillow\winbuild\build_prepare.py -v --depends=C:\pillow-depends\

View File

@ -18,6 +18,9 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true
env:
FORCE_COLOR: 1
jobs: jobs:
build: build:

View File

@ -20,7 +20,7 @@ jobs:
steps: steps:
- name: "Check issues" - name: "Check issues"
uses: actions/stale@v7 uses: actions/stale@v8
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
only-labels: "Awaiting OP Action" only-labels: "Awaiting OP Action"

View File

@ -33,11 +33,11 @@ jobs:
# Then run the remainder # Then run the remainder
alpine, alpine,
amazon-2-amd64, amazon-2-amd64,
amazon-2023-amd64,
arch, arch,
centos-7-amd64, centos-7-amd64,
centos-stream-8-amd64, centos-stream-8-amd64,
centos-stream-9-amd64, centos-stream-9-amd64,
debian-10-buster-x86,
debian-11-bullseye-x86, debian-11-bullseye-x86,
fedora-36-amd64, fedora-36-amd64,
fedora-37-amd64, fedora-37-amd64,

View File

@ -74,8 +74,8 @@ jobs:
7z x winbuild\depends\nasm-2.15.05-win64.zip "-o$env:RUNNER_WORKSPACE\" 7z x winbuild\depends\nasm-2.15.05-win64.zip "-o$env:RUNNER_WORKSPACE\"
echo "$env:RUNNER_WORKSPACE\nasm-2.15.05" >> $env:GITHUB_PATH echo "$env:RUNNER_WORKSPACE\nasm-2.15.05" >> $env:GITHUB_PATH
winbuild\depends\gs1000w32.exe /S choco install ghostscript --version=10.0.0.20230317
echo "C:\Program Files (x86)\gs\gs10.0.0\bin" >> $env:GITHUB_PATH echo "C:\Program Files\gs\gs10.00.0\bin" >> $env:GITHUB_PATH
# Install extra test images # Install extra test images
xcopy /S /Y Tests\test-images\* Tests\images xcopy /S /Y Tests\test-images\* Tests\images

View File

@ -5,6 +5,24 @@ Changelog (Pillow)
9.5.0 (unreleased) 9.5.0 (unreleased)
------------------ ------------------
- Consider transparency when applying APNG blend mask #7018
[radarhere]
- Round duration when saving animated WebP images #6996
[radarhere]
- Added reading of JPEG2000 comments #6909
[radarhere]
- Decrement reference count #7003
[radarhere, nulano]
- Allow libtiff_support_custom_tags to be missing #7020
[radarhere]
- Improved I;16N support #6834
[radarhere]
- Added QOI reading #6852 - Added QOI reading #6852
[radarhere, hugovk] [radarhere, hugovk]

View File

@ -16,10 +16,16 @@ coverage:
python3 -m coverage report python3 -m coverage report
.PHONY: doc .PHONY: doc
doc: .PHONY: html
doc html:
python3 -c "import PIL" > /dev/null 2>&1 || python3 -m pip install . python3 -c "import PIL" > /dev/null 2>&1 || python3 -m pip install .
$(MAKE) -C docs html $(MAKE) -C docs html
.PHONY: htmlview
htmlview:
python3 -c "import PIL" > /dev/null 2>&1 || python3 -m pip install .
$(MAKE) -C docs htmlview
.PHONY: doccheck .PHONY: doccheck
doccheck: doccheck:
$(MAKE) doc $(MAKE) doc
@ -38,7 +44,8 @@ help:
@echo " coverage run coverage test (in progress)" @echo " coverage run coverage test (in progress)"
@echo " doc make HTML docs" @echo " doc make HTML docs"
@echo " docserve run an HTTP server on the docs directory" @echo " docserve run an HTTP server on the docs directory"
@echo " html to make standalone HTML files" @echo " html make HTML docs"
@echo " htmlview open the index page built by the html target in your browser"
@echo " inplace make inplace extension" @echo " inplace make inplace extension"
@echo " install make and install" @echo " install make and install"
@echo " install-coverage make and install with C coverage" @echo " install-coverage make and install with C coverage"

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 B

BIN
Tests/images/comment.jp2 Normal file

Binary file not shown.

View File

@ -163,6 +163,12 @@ def test_apng_blend():
assert im.getpixel((64, 32)) == (0, 255, 0, 255) assert im.getpixel((64, 32)) == (0, 255, 0, 255)
def test_apng_blend_transparency():
with Image.open("Tests/images/blend_transparency.png") as im:
im.seek(1)
assert im.getpixel((0, 0)) == (255, 0, 0)
def test_apng_chunk_order(): def test_apng_chunk_order():
with Image.open("Tests/images/apng/fctl_actl.png") as im: with Image.open("Tests/images/apng/fctl_actl.png") as im:
im.seek(im.n_frames - 1) im.seek(im.n_frames - 1)

View File

@ -353,6 +353,17 @@ def test_subsampling_decode(name):
assert_image_similar(im, expected, epsilon) assert_image_similar(im, expected, epsilon)
def test_comment():
with Image.open("Tests/images/comment.jp2") as im:
assert im.info["comment"] == b"Created by OpenJPEG version 2.5.0"
# Test an image that is truncated partway through a codestream
with open("Tests/images/comment.jp2", "rb") as fp:
b = BytesIO(fp.read(130))
with Image.open(b) as im:
pass
@pytest.mark.parametrize( @pytest.mark.parametrize(
"test_file", "test_file",
[ [

View File

@ -134,6 +134,18 @@ def test_timestamp_and_duration(tmp_path):
ts += durations[frame] ts += durations[frame]
def test_float_duration(tmp_path):
temp_file = str(tmp_path / "temp.webp")
with Image.open("Tests/images/iss634.apng") as im:
assert im.info["duration"] == 70.0
im.save(temp_file, save_all=True)
with Image.open(temp_file) as reloaded:
reloaded.load()
assert reloaded.info["duration"] == 70
def test_seeking(tmp_path): def test_seeking(tmp_path):
""" """
Create an animated WebP file, and then try seeking through frames in reverse-order, Create an animated WebP file, and then try seeking through frames in reverse-order,

View File

@ -275,15 +275,10 @@ class TestCffi(AccessTest):
# self._test_get_access(hopper('PA')) # PA -- how do I make a PA image? # self._test_get_access(hopper('PA')) # PA -- how do I make a PA image?
self._test_get_access(hopper("F")) self._test_get_access(hopper("F"))
im = Image.new("I;16", (10, 10), 40000) for mode in ("I;16", "I;16L", "I;16B", "I;16N", "I"):
self._test_get_access(im) im = Image.new(mode, (10, 10), 40000)
im = Image.new("I;16L", (10, 10), 40000) self._test_get_access(im)
self._test_get_access(im)
im = Image.new("I;16B", (10, 10), 40000)
self._test_get_access(im)
im = Image.new("I", (10, 10), 40000)
self._test_get_access(im)
# These don't actually appear to be modes that I can actually make, # These don't actually appear to be modes that I can actually make,
# as unpack sets them directly into the I mode. # as unpack sets them directly into the I mode.
# im = Image.new('I;32L', (10, 10), -2**10) # im = Image.new('I;32L', (10, 10), -2**10)
@ -322,15 +317,10 @@ class TestCffi(AccessTest):
# self._test_set_access(i, (128, 128)) #PA -- undone how to make # self._test_set_access(i, (128, 128)) #PA -- undone how to make
self._test_set_access(hopper("F"), 1024.0) self._test_set_access(hopper("F"), 1024.0)
im = Image.new("I;16", (10, 10), 40000) for mode in ("I;16", "I;16L", "I;16B", "I;16N", "I"):
self._test_set_access(im, 45000) im = Image.new(mode, (10, 10), 40000)
im = Image.new("I;16L", (10, 10), 40000) self._test_set_access(im, 45000)
self._test_set_access(im, 45000)
im = Image.new("I;16B", (10, 10), 40000)
self._test_set_access(im, 45000)
im = Image.new("I", (10, 10), 40000)
self._test_set_access(im, 45000)
# im = Image.new('I;32L', (10, 10), -(2**10)) # im = Image.new('I;32L', (10, 10), -(2**10))
# self._test_set_access(im, -(2**13)+1) # self._test_set_access(im, -(2**13)+1)
# im = Image.new('I;32B', (10, 10), 2**10) # im = Image.new('I;32B', (10, 10), 2**10)

View File

@ -207,6 +207,9 @@ class TestLibPack:
0x01000083, 0x01000083,
) )
def test_I16(self):
self.assert_pack("I;16N", "I;16N", 2, 0x0201, 0x0403, 0x0605)
def test_F_float(self): def test_F_float(self):
self.assert_pack("F", "F;32F", 4, 1.539989614439558e-36, 4.063216068939723e-34) self.assert_pack("F", "F;32F", 4, 1.539989614439558e-36, 4.063216068939723e-34)
@ -761,10 +764,12 @@ class TestLibUnpack:
self.assert_unpack("I;16", "I;16N", 2, 0x0201, 0x0403, 0x0605) self.assert_unpack("I;16", "I;16N", 2, 0x0201, 0x0403, 0x0605)
self.assert_unpack("I;16B", "I;16N", 2, 0x0201, 0x0403, 0x0605) self.assert_unpack("I;16B", "I;16N", 2, 0x0201, 0x0403, 0x0605)
self.assert_unpack("I;16L", "I;16N", 2, 0x0201, 0x0403, 0x0605) self.assert_unpack("I;16L", "I;16N", 2, 0x0201, 0x0403, 0x0605)
self.assert_unpack("I;16N", "I;16N", 2, 0x0201, 0x0403, 0x0605)
else: else:
self.assert_unpack("I;16", "I;16N", 2, 0x0102, 0x0304, 0x0506) self.assert_unpack("I;16", "I;16N", 2, 0x0102, 0x0304, 0x0506)
self.assert_unpack("I;16B", "I;16N", 2, 0x0102, 0x0304, 0x0506) self.assert_unpack("I;16B", "I;16N", 2, 0x0102, 0x0304, 0x0506)
self.assert_unpack("I;16L", "I;16N", 2, 0x0102, 0x0304, 0x0506) self.assert_unpack("I;16L", "I;16N", 2, 0x0102, 0x0304, 0x0506)
self.assert_unpack("I;16N", "I;16N", 2, 0x0102, 0x0304, 0x0506)
def test_CMYK16(self): def test_CMYK16(self):
self.assert_unpack("CMYK", "CMYK;16L", 8, (2, 4, 6, 8), (10, 12, 14, 16)) self.assert_unpack("CMYK", "CMYK;16L", 8, (2, 4, 6, 8), (10, 12, 14, 16))

View File

@ -88,10 +88,7 @@ def test_tobytes():
def test_convert(): def test_convert():
im = original.copy() im = original.copy()
verify(im.convert("I;16")) for mode in ("I;16", "I;16B", "I;16N"):
verify(im.convert("I;16").convert("L")) verify(im.convert(mode))
verify(im.convert("I;16").convert("I")) verify(im.convert(mode).convert("L"))
verify(im.convert(mode).convert("I"))
verify(im.convert("I;16B"))
verify(im.convert("I;16B").convert("L"))
verify(im.convert("I;16B").convert("I"))

View File

@ -19,6 +19,7 @@ I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
help: help:
@echo "Please use \`make <target>' where <target> is one of" @echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files" @echo " html to make standalone HTML files"
@echo " htmlview to open the index page built by the html target in your browser"
@echo " serve to start a local server for viewing docs" @echo " serve to start a local server for viewing docs"
@echo " livehtml to start a local server for viewing docs and auto-reload on change" @echo " livehtml to start a local server for viewing docs and auto-reload on change"
@echo " dirhtml to make HTML files named index.html in directories" @echo " dirhtml to make HTML files named index.html in directories"
@ -45,7 +46,7 @@ clean:
-rm -rf $(BUILDDIR)/* -rm -rf $(BUILDDIR)/*
install-sphinx: install-sphinx:
$(PYTHON) -m pip install --quiet furo olefile sphinx sphinx-copybutton sphinx-inline-tabs sphinx-issues sphinx-removed-in sphinxext-opengraph $(PYTHON) -m pip install --quiet furo olefile sphinx sphinx-copybutton sphinx-inline-tabs sphinx-removed-in sphinxext-opengraph
.PHONY: html .PHONY: html
html: html:
@ -196,6 +197,10 @@ doctest:
@echo "Testing of doctests in the sources finished, look at the " \ @echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt." "results in $(BUILDDIR)/doctest/output.txt."
.PHONY: htmlview
htmlview: html
$(PYTHON) -c "import os, webbrowser; webbrowser.open('file://' + os.path.realpath('$(BUILDDIR)/html/index.html'))"
.PHONY: livehtml .PHONY: livehtml
livehtml: html livehtml: html
livereload $(BUILDDIR)/html -p 33233 livereload $(BUILDDIR)/html -p 33233

View File

@ -28,11 +28,11 @@ needs_sphinx = "2.4"
# ones. # ones.
extensions = [ extensions = [
"sphinx.ext.autodoc", "sphinx.ext.autodoc",
"sphinx.ext.extlinks",
"sphinx.ext.intersphinx", "sphinx.ext.intersphinx",
"sphinx.ext.viewcode", "sphinx.ext.viewcode",
"sphinx_copybutton", "sphinx_copybutton",
"sphinx_inline_tabs", "sphinx_inline_tabs",
"sphinx_issues",
"sphinx_removed_in", "sphinx_removed_in",
"sphinxext.opengraph", "sphinxext.opengraph",
] ]
@ -317,8 +317,17 @@ def setup(app):
app.add_css_file("css/dark.css") app.add_css_file("css/dark.css")
# GitHub repo for sphinx-issues # sphinx.ext.extlinks
issues_github_path = "python-pillow/Pillow" # This config is a dictionary of external sites,
# mapping unique short aliases to a base URL and a prefix.
# https://www.sphinx-doc.org/en/master/usage/extensions/extlinks.html
_repo = "https://github.com/python-pillow/Pillow/"
extlinks = {
"cve": ("https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-%s", "CVE-%s"),
"cwe": ("https://cwe.mitre.org/data/definitions/%s.html", "CWE-%s"),
"issue": (_repo + "issues/%s", "#%s"),
"pr": (_repo + "pull/%s", "#%s"),
}
# sphinxext.opengraph # sphinxext.opengraph
ogp_image = ( ogp_image = (

View File

@ -261,7 +261,7 @@ FreeType 2.7
Support for FreeType 2.7 has been removed. Support for FreeType 2.7 has been removed.
We recommend upgrading to at least `FreeType`_ 2.10.4, which fixed a severe We recommend upgrading to at least `FreeType`_ 2.10.4, which fixed a severe
vulnerability introduced in FreeType 2.6 (:cve:`CVE-2020-15999`). vulnerability introduced in FreeType 2.6 (:cve:`2020-15999`).
.. _FreeType: https://freetype.org/ .. _FreeType: https://freetype.org/

View File

@ -424,6 +424,8 @@ These platforms are built and tested for every change.
+----------------------------------+----------------------------+---------------------+ +----------------------------------+----------------------------+---------------------+
| Amazon Linux 2 | 3.7 | x86-64 | | Amazon Linux 2 | 3.7 | x86-64 |
+----------------------------------+----------------------------+---------------------+ +----------------------------------+----------------------------+---------------------+
| Amazon Linux 2023 | 3.9 | x86-64 |
+----------------------------------+----------------------------+---------------------+
| Arch | 3.9 | x86-64 | | Arch | 3.9 | x86-64 |
+----------------------------------+----------------------------+---------------------+ +----------------------------------+----------------------------+---------------------+
| CentOS 7 | 3.9 | x86-64 | | CentOS 7 | 3.9 | x86-64 |
@ -432,8 +434,6 @@ These platforms are built and tested for every change.
+----------------------------------+----------------------------+---------------------+ +----------------------------------+----------------------------+---------------------+
| CentOS Stream 9 | 3.9 | x86-64 | | CentOS Stream 9 | 3.9 | x86-64 |
+----------------------------------+----------------------------+---------------------+ +----------------------------------+----------------------------+---------------------+
| Debian 10 Buster | 3.7 | x86 |
+----------------------------------+----------------------------+---------------------+
| Debian 11 Bullseye | 3.9 | x86 | | Debian 11 Bullseye | 3.9 | x86 |
+----------------------------------+----------------------------+---------------------+ +----------------------------------+----------------------------+---------------------+
| Fedora 36 | 3.10 | x86-64 | | Fedora 36 | 3.10 | x86-64 |

View File

@ -19,6 +19,7 @@ if "%1" == "help" (
:help :help
echo.Please use `make ^<target^>` where ^<target^> is one of echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files echo. html to make standalone HTML files
echo. htmlview to open the index page built by the html target in your browser
echo. dirhtml to make HTML files named index.html in directories echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files echo. pickle to make pickle files
@ -44,12 +45,23 @@ if "%1" == "clean" (
goto end goto end
) )
if "%1" == "html" ( set html=false
if "%1%" == "html" set html=true
if "%1%" == "htmlview" set html=true
if "%html%" == "true" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1 if errorlevel 1 exit /b 1
echo. echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html. echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
if "%1" == "htmlview" (
if EXIST "%BUILDDIR%\html\index.html" (
echo.Opening "%BUILDDIR%\html\index.html" in the default web browser...
start "" "%BUILDDIR%\html\index.html"
)
)
goto end
) )
if "%1" == "dirhtml" ( if "%1" == "dirhtml" (

View File

@ -320,8 +320,8 @@ Methods
:param xy: Two points to define the bounding box. Sequence of either :param xy: Two points to define the bounding box. Sequence of either
``[(x0, y0), (x1, y1)]`` or ``[x0, y0, x1, y1]``, where ``x1 >= x0`` and ``[(x0, y0), (x1, y1)]`` or ``[x0, y0, x1, y1]``, where ``x1 >= x0`` and
``y1 >= y0``. The bounding box is inclusive of both endpoints. ``y1 >= y0``. The bounding box is inclusive of both endpoints.
:param outline: Color to use for the outline.
:param fill: Color to use for the fill. :param fill: Color to use for the fill.
:param outline: Color to use for the outline.
:param width: The line width, in pixels. :param width: The line width, in pixels.
.. versionadded:: 5.3.0 .. versionadded:: 5.3.0
@ -334,8 +334,8 @@ Methods
``[(x0, y0), (x1, y1)]`` or ``[x0, y0, x1, y1]``, where ``x1 >= x0`` and ``[(x0, y0), (x1, y1)]`` or ``[x0, y0, x1, y1]``, where ``x1 >= x0`` and
``y1 >= y0``. The bounding box is inclusive of both endpoints. ``y1 >= y0``. The bounding box is inclusive of both endpoints.
:param radius: Radius of the corners. :param radius: Radius of the corners.
:param outline: Color to use for the outline.
:param fill: Color to use for the fill. :param fill: Color to use for the fill.
:param outline: Color to use for the outline.
:param width: The line width, in pixels. :param width: The line width, in pixels.
:param corners: A tuple of whether to round each corner, :param corners: A tuple of whether to round each corner,
``(top_left, top_right, bottom_right, bottom_left)``. ``(top_left, top_right, bottom_right, bottom_left)``.

View File

@ -10,19 +10,13 @@ distributions.
- ``python3-dbg`` package for the gdb extensions and python symbols - ``python3-dbg`` package for the gdb extensions and python symbols
- ``gdb`` and ``valgrind`` - ``gdb`` and ``valgrind``
- Potentially debug symbols for libraries. On ubuntu they're shipped - Potentially debug symbols for libraries. On Ubuntu you can follow those
in package-dbgsym packages, from a different repo. instructions to install the corresponding packages: `Debug Symbol Packages <https://wiki.ubuntu.com/Debug%20Symbol%20Packages#Getting_-dbgsym.ddeb_packages>`_
:: Then ``sudo apt-get install libtiff5-dbgsym``
deb http://ddebs.ubuntu.com focal main restricted universe multiverse - There's a bug with the ``python3-dbg`` package for at least Python 3.8 on
deb http://ddebs.ubuntu.com focal-updates main restricted universe multiverse Ubuntu 20.04, and you need to add a new link or two to make it autoload when
deb http://ddebs.ubuntu.com focal-proposed main restricted universe multiverse
Then ``sudo apt-get update && sudo apt-get install libtiff5-dbgsym``
- There's a bug with the dbg package for at least python 3.8 on ubuntu
20.04, and you need to add a new link or two to make it autoload when
running python: running python:
:: ::

View File

@ -6,7 +6,7 @@ CVE-2016-0740 -- Buffer overflow in TiffDecode.c
------------------------------------------------ ------------------------------------------------
Pillow 3.1.0 and earlier when linked against libtiff >= 4.0.0 on x64 Pillow 3.1.0 and earlier when linked against libtiff >= 4.0.0 on x64
may overflow a buffer when reading a specially crafted tiff file (:cve:`CVE-2016-0740`). may overflow a buffer when reading a specially crafted tiff file (:cve:`2016-0740`).
Specifically, libtiff >= 4.0.0 changed the return type of Specifically, libtiff >= 4.0.0 changed the return type of
``TIFFScanlineSize`` from ``int32`` to machine dependent ``TIFFScanlineSize`` from ``int32`` to machine dependent
@ -24,7 +24,7 @@ CVE-2016-0775 -- Buffer overflow in FliDecode.c
----------------------------------------------- -----------------------------------------------
In all versions of Pillow, dating back at least to the last PIL 1.1.7 In all versions of Pillow, dating back at least to the last PIL 1.1.7
release, FliDecode.c has a buffer overflow error (:cve:`CVE-2016-0775`). release, FliDecode.c has a buffer overflow error (:cve:`2016-0775`).
Around line 192: Around line 192:
@ -53,7 +53,7 @@ CVE-2016-2533 -- Buffer overflow in PcdDecode.c
----------------------------------------------- -----------------------------------------------
In all versions of Pillow, dating back at least to the last PIL 1.1.7 In all versions of Pillow, dating back at least to the last PIL 1.1.7
release, ``PcdDecode.c`` has a buffer overflow error (:cve:`CVE-2016-2533`). release, ``PcdDecode.c`` has a buffer overflow error (:cve:`2016-2533`).
The ``state.buffer`` for ``PcdDecode.c`` is allocated based on a 3 The ``state.buffer`` for ``PcdDecode.c`` is allocated based on a 3
bytes per pixel sizing, where ``PcdDecode.c`` wrote into the buffer bytes per pixel sizing, where ``PcdDecode.c`` wrote into the buffer

View File

@ -7,7 +7,7 @@ CVE-2016-3076 -- Buffer overflow in Jpeg2KEncode.c
Pillow between 2.5.0 and 3.1.1 may overflow a buffer when writing Pillow between 2.5.0 and 3.1.1 may overflow a buffer when writing
large Jpeg2000 files, allowing for code execution or other memory large Jpeg2000 files, allowing for code execution or other memory
corruption (:cve:`CVE-2016-3076`). corruption (:cve:`2016-3076`).
This occurs specifically in the function ``j2k_encode_entry``, at the line: This occurs specifically in the function ``j2k_encode_entry``, at the line:

View File

@ -69,7 +69,7 @@ Security
======== ========
This release catches several buffer overruns, as well as addressing This release catches several buffer overruns, as well as addressing
:cve:`CVE-2019-16865`. The CVE is regarding DOS problems, such as consuming large :cve:`2019-16865`. The CVE is regarding DOS problems, such as consuming large
amounts of memory, or taking a large amount of time to process an image. amounts of memory, or taking a large amount of time to process an image.
In RawDecode.c, an error is now thrown if skip is calculated to be less than In RawDecode.c, an error is now thrown if skip is calculated to be less than

View File

@ -6,13 +6,13 @@ Security
This release addresses several security problems. This release addresses several security problems.
:cve:`CVE-2019-19911` is regarding FPX images. If an image reports that it has a large :cve:`2019-19911` is regarding FPX images. If an image reports that it has a large
number of bands, a large amount of resources will be used when trying to process the number of bands, a large amount of resources will be used when trying to process the
image. This is fixed by limiting the number of bands to those usable by Pillow. image. This is fixed by limiting the number of bands to those usable by Pillow.
Buffer overruns were found when processing an SGI (:cve:`CVE-2020-5311`), Buffer overruns were found when processing an SGI (:cve:`2020-5311`),
PCX (:cve:`CVE-2020-5312`) or FLI image (:cve:`CVE-2020-5313`). Checks have been added PCX (:cve:`2020-5312`) or FLI image (:cve:`2020-5313`). Checks have been added
to prevent this. to prevent this.
:cve:`CVE-2020-5310`: Overflow checks have been added when calculating the size of a :cve:`2020-5310`: Overflow checks have been added when calculating the size of a
memory block to be reallocated in the processing of a TIFF image. memory block to be reallocated in the processing of a TIFF image.

View File

@ -72,11 +72,11 @@ Security
This release includes security fixes. This release includes security fixes.
* :cve:`CVE-2020-10177` Fix multiple out-of-bounds reads in FLI decoding * :cve:`2020-10177` Fix multiple out-of-bounds reads in FLI decoding
* :cve:`CVE-2020-10378` Fix bounds overflow in PCX decoding * :cve:`2020-10378` Fix bounds overflow in PCX decoding
* :cve:`CVE-2020-10379` Fix two buffer overflows in TIFF decoding * :cve:`2020-10379` Fix two buffer overflows in TIFF decoding
* :cve:`CVE-2020-10994` Fix bounds overflow in JPEG 2000 decoding * :cve:`2020-10994` Fix bounds overflow in JPEG 2000 decoding
* :cve:`CVE-2020-11538` Fix buffer overflow in SGI-RLE decoding * :cve:`2020-11538` Fix buffer overflow in SGI-RLE decoding
Other Changes Other Changes
============= =============

View File

@ -4,7 +4,7 @@
Security Security
======== ========
Update FreeType used in binary wheels to `2.10.4`_ to fix :cve:`CVE-2020-15999`: Update FreeType used in binary wheels to `2.10.4`_ to fix :cve:`2020-15999`:
- A heap buffer overflow has been found in the handling of embedded PNG bitmaps, - A heap buffer overflow has been found in the handling of embedded PNG bitmaps,
introduced in FreeType version 2.6. introduced in FreeType version 2.6.

View File

@ -11,7 +11,7 @@ Support for FreeType 2.7 is deprecated and will be removed in Pillow 9.0.0 (2022
when FreeType 2.8 will be the minimum supported. when FreeType 2.8 will be the minimum supported.
We recommend upgrading to at least FreeType `2.10.4`_, which fixed a severe We recommend upgrading to at least FreeType `2.10.4`_, which fixed a severe
vulnerability introduced in FreeType 2.6 (:cve:`CVE-2020-15999`). vulnerability introduced in FreeType 2.6 (:cve:`2020-15999`).
.. _2.10.4: https://sourceforge.net/projects/freetype/files/freetype2/2.10.4/ .. _2.10.4: https://sourceforge.net/projects/freetype/files/freetype2/2.10.4/
@ -40,13 +40,13 @@ This release includes security fixes.
* An out-of-bounds read when saving TIFFs with custom metadata through LibTIFF * An out-of-bounds read when saving TIFFs with custom metadata through LibTIFF
* An out-of-bounds read when saving a GIF of 1px width * An out-of-bounds read when saving a GIF of 1px width
* :cve:`CVE-2020-35653` Buffer read overrun in PCX decoding * :cve:`2020-35653` Buffer read overrun in PCX decoding
The PCX image decoder used the reported image stride to calculate the row buffer, The PCX image decoder used the reported image stride to calculate the row buffer,
rather than calculating it from the image size. This issue dates back to the PIL fork. rather than calculating it from the image size. This issue dates back to the PIL fork.
Thanks to Google's `OSS-Fuzz`_ project for finding this. Thanks to Google's `OSS-Fuzz`_ project for finding this.
* :cve:`CVE-2020-35654` Fix TIFF out-of-bounds write error * :cve:`2020-35654` Fix TIFF out-of-bounds write error
Out-of-bounds write in ``TiffDecode.c`` when reading corrupt YCbCr files in some Out-of-bounds write in ``TiffDecode.c`` when reading corrupt YCbCr files in some
LibTIFF versions (4.1.0/Ubuntu 20.04, but not 4.0.9/Ubuntu 18.04). In some cases LibTIFF versions (4.1.0/Ubuntu 20.04, but not 4.0.9/Ubuntu 18.04). In some cases
@ -55,7 +55,7 @@ an out-of-bounds write in ``TiffDecode.c``. This potentially affects Pillow vers
from 6.0.0 to 8.0.1, depending on the version of LibTIFF. This was reported through from 6.0.0 to 8.0.1, depending on the version of LibTIFF. This was reported through
`Tidelift`_. `Tidelift`_.
* :cve:`CVE-2020-35655` Fix for SGI Decode buffer overrun * :cve:`2020-35655` Fix for SGI Decode buffer overrun
4 byte read overflow in ``SgiRleDecode.c``, where the code was not correctly checking the 4 byte read overflow in ``SgiRleDecode.c``, where the code was not correctly checking the
offsets and length tables. Independently reported through `Tidelift`_ and Google's offsets and length tables. Independently reported through `Tidelift`_ and Google's

View File

@ -4,19 +4,19 @@
Security Security
======== ========
:cve:`CVE-2021-25289`: The previous fix for :cve:`CVE-2020-35654` was insufficient :cve:`2021-25289`: The previous fix for :cve:`2020-35654` was insufficient
due to incorrect error checking in ``TiffDecode.c``. due to incorrect error checking in ``TiffDecode.c``.
:cve:`CVE-2021-25290`: In ``TiffDecode.c``, there is a negative-offset ``memcpy`` :cve:`2021-25290`: In ``TiffDecode.c``, there is a negative-offset ``memcpy``
with an invalid size. with an invalid size.
:cve:`CVE-2021-25291`: In ``TiffDecode.c``, invalid tile boundaries could lead to :cve:`2021-25291`: In ``TiffDecode.c``, invalid tile boundaries could lead to
an out-of-bounds read in ``TIFFReadRGBATile``. an out-of-bounds read in ``TIFFReadRGBATile``.
:cve:`CVE-2021-25292`: The PDF parser has a catastrophic backtracking regex :cve:`2021-25292`: The PDF parser has a catastrophic backtracking regex
that could be used as a DOS attack. that could be used as a DOS attack.
:cve:`CVE-2021-25293`: There is an out-of-bounds read in ``SgiRleDecode.c``, :cve:`2021-25293`: There is an out-of-bounds read in ``SgiRleDecode.c``,
since Pillow 4.3.0. since Pillow 4.3.0.

View File

@ -4,8 +4,8 @@
Security Security
======== ========
There is an exhaustion of memory DOS in the BLP (:cve:`CVE-2021-27921`), There is an exhaustion of memory DOS in the BLP (:cve:`2021-27921`),
ICNS (:cve:`CVE-2021-27922`) and ICO (:cve:`CVE-2021-27923`) container formats ICNS (:cve:`2021-27922`) and ICO (:cve:`2021-27923`) container formats
where Pillow did not properly check the reported size of the contained image. where Pillow did not properly check the reported size of the contained image.
These images could cause arbitrarily large memory allocations. This was reported These images could cause arbitrarily large memory allocations. This was reported
by Jiayi Lin, Luke Shaffer, Xinran Xie, and Akshay Ajayan of by Jiayi Lin, Luke Shaffer, Xinran Xie, and Akshay Ajayan of

View File

@ -129,15 +129,15 @@ Security
These were all found with `OSS-Fuzz`_. These were all found with `OSS-Fuzz`_.
:cve:`CVE-2021-25287`, :cve:`CVE-2021-25288`: Fix OOB read in Jpeg2KDecode :cve:`2021-25287`, :cve:`2021-25288`: Fix OOB read in Jpeg2KDecode
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* For J2k images with multiple bands, it's legal to have different widths for each band, * For J2k images with multiple bands, it's legal to have different widths for each band,
e.g. 1 byte for ``L``, 4 bytes for ``A``. e.g. 1 byte for ``L``, 4 bytes for ``A``.
* This dates to Pillow 2.4.0. * This dates to Pillow 2.4.0.
:cve:`CVE-2021-28675`: Fix DOS in PsdImagePlugin :cve:`2021-28675`: Fix DOS in PsdImagePlugin
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* :py:class:`.PsdImagePlugin.PsdImageFile` did not sanity check the number of input * :py:class:`.PsdImagePlugin.PsdImageFile` did not sanity check the number of input
layers with regard to the size of the data block, this could lead to a layers with regard to the size of the data block, this could lead to a
@ -145,15 +145,15 @@ These were all found with `OSS-Fuzz`_.
:py:meth:`~PIL.Image.Image.load`. :py:meth:`~PIL.Image.Image.load`.
* This dates to the PIL fork. * This dates to the PIL fork.
:cve:`CVE-2021-28676`: Fix FLI DOS :cve:`2021-28676`: Fix FLI DOS
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* ``FliDecode.c`` did not properly check that the block advance was non-zero, * ``FliDecode.c`` did not properly check that the block advance was non-zero,
potentially leading to an infinite loop on load. potentially leading to an infinite loop on load.
* This dates to the PIL fork. * This dates to the PIL fork.
:cve:`CVE-2021-28677`: Fix EPS DOS on _open :cve:`2021-28677`: Fix EPS DOS on _open
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* The readline used in EPS has to deal with any combination of ``\r`` and ``\n`` as line * The readline used in EPS has to deal with any combination of ``\r`` and ``\n`` as line
endings. It accidentally used a quadratic method of accumulating lines while looking endings. It accidentally used a quadratic method of accumulating lines while looking
@ -162,8 +162,8 @@ These were all found with `OSS-Fuzz`_.
open phase, before an image was accepted for opening. open phase, before an image was accepted for opening.
* This dates to the PIL fork. * This dates to the PIL fork.
:cve:`CVE-2021-28678`: Fix BLP DOS :cve:`2021-28678`: Fix BLP DOS
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* ``BlpImagePlugin`` did not properly check that reads after jumping to file offsets * ``BlpImagePlugin`` did not properly check that reads after jumping to file offsets
returned data. This could lead to a denial-of-service where the decoder could be run a returned data. This could lead to a denial-of-service where the decoder could be run a

View File

@ -85,7 +85,7 @@ Security
Buffer overflow Buffer overflow
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
This release addresses :cve:`CVE-2021-34552`. PIL since 1.1.4 and Pillow since 1.0 This release addresses :cve:`2021-34552`. PIL since 1.1.4 and Pillow since 1.0
allowed parameters passed into a convert function to trigger buffer overflow in allowed parameters passed into a convert function to trigger buffer overflow in
Convert.c. Convert.c.

View File

@ -4,7 +4,7 @@
Security Security
======== ========
* :cve:`CVE-2021-23437`: Avoid a potential ReDoS (regular expression denial of service) * :cve:`2021-23437`: Avoid a potential ReDoS (regular expression denial of service)
in :py:class:`~PIL.ImageColor`'s :py:meth:`~PIL.ImageColor.getrgb` by raising in :py:class:`~PIL.ImageColor`'s :py:meth:`~PIL.ImageColor.getrgb` by raising
:py:exc:`ValueError` if the color specifier is too long. Present since Pillow 5.2.0. :py:exc:`ValueError` if the color specifier is too long. Present since Pillow 5.2.0.

View File

@ -43,7 +43,7 @@ FreeType 2.7
Support for FreeType 2.7 has been removed; FreeType 2.8 is the minimum supported. Support for FreeType 2.7 has been removed; FreeType 2.8 is the minimum supported.
We recommend upgrading to at least `FreeType`_ 2.10.4, which fixed a severe We recommend upgrading to at least `FreeType`_ 2.10.4, which fixed a severe
vulnerability introduced in FreeType 2.6 (:cve:`CVE-2020-15999`). vulnerability introduced in FreeType 2.6 (:cve:`2020-15999`).
.. _FreeType: https://freetype.org/ .. _FreeType: https://freetype.org/
@ -119,7 +119,7 @@ Google's `OSS-Fuzz`_ project for finding this issue.
Restrict builtins available to ImageMath.eval Restrict builtins available to ImageMath.eval
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:cve:`CVE-2022-22817`: To limit :py:class:`PIL.ImageMath` to working with images, Pillow :cve:`2022-22817`: To limit :py:class:`PIL.ImageMath` to working with images, Pillow
will now restrict the builtins available to :py:meth:`PIL.ImageMath.eval`. This will will now restrict the builtins available to :py:meth:`PIL.ImageMath.eval`. This will
help prevent problems arising if users evaluate arbitrary expressions, such as help prevent problems arising if users evaluate arbitrary expressions, such as
``ImageMath.eval("exec(exit())")``. ``ImageMath.eval("exec(exit())")``.
@ -127,7 +127,7 @@ help prevent problems arising if users evaluate arbitrary expressions, such as
Fixed ImagePath.Path array handling Fixed ImagePath.Path array handling
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:cve:`CVE-2022-22815` (:cwe:`CWE-126`) and :cve:`CVE-2022-22816` (:cwe:`CWE-665`) were :cve:`2022-22815` (:cwe:`126`) and :cve:`2022-22816` (:cwe:`665`) were
found when initializing ``ImagePath.Path``. found when initializing ``ImagePath.Path``.
.. _OSS-Fuzz: https://github.com/google/oss-fuzz .. _OSS-Fuzz: https://github.com/google/oss-fuzz

View File

@ -6,12 +6,12 @@ Security
This release addresses several security problems. This release addresses several security problems.
:cve:`CVE-2022-24303`: If the path to the temporary directory on Linux or macOS :cve:`2022-24303`: If the path to the temporary directory on Linux or macOS
contained a space, this would break removal of the temporary image file after contained a space, this would break removal of the temporary image file after
``im.show()`` (and related actions), and potentially remove an unrelated file. This ``im.show()`` (and related actions), and potentially remove an unrelated file. This
has been present since PIL. has been present since PIL.
:cve:`CVE-2022-22817`: While Pillow 9.0 restricted top-level builtins available to :cve:`2022-22817`: While Pillow 9.0 restricted top-level builtins available to
:py:meth:`PIL.ImageMath.eval`, it did not prevent builtins available to lambda :py:meth:`PIL.ImageMath.eval`, it did not prevent builtins available to lambda
expressions. These are now also restricted. expressions. These are now also restricted.

View File

@ -6,7 +6,7 @@ Security
This release addresses several security problems. This release addresses several security problems.
:cve:`CVE-2022-30595`: When reading a TGA file with RLE packets that cross scan lines, :cve:`2022-30595`: When reading a TGA file with RLE packets that cross scan lines,
Pillow reads the information past the end of the first line without deducting that Pillow reads the information past the end of the first line without deducting that
from the length of the remaining file data. This vulnerability was introduced in Pillow from the length of the remaining file data. This vulnerability was introduced in Pillow
9.1.0, and can cause a heap buffer overflow. 9.1.0, and can cause a heap buffer overflow.

View File

@ -48,6 +48,12 @@ Added ``corners`` argument to ``ImageDraw.rounded_rectangle()``
``corners``. This a tuple of Booleans, specifying whether to round each corner, ``corners``. This a tuple of Booleans, specifying whether to round each corner,
``(top_left, top_right, bottom_right, bottom_left)``. ``(top_left, top_right, bottom_right, bottom_left)``.
Reading JPEG comments
^^^^^^^^^^^^^^^^^^^^^
When opening a JPEG2000 image, the comment may now be read into
:py:attr:`~PIL.Image.Image.info`.
Security Security
======== ========
@ -64,6 +70,12 @@ Added support for saving PDFs in RGBA mode
Using the JPXDecode filter, PDFs can now be saved in RGBA mode. Using the JPXDecode filter, PDFs can now be saved in RGBA mode.
Improved I;16N support
^^^^^^^^^^^^^^^^^^^^^^
Support has been added for I;16N access, packing and unpacking. Conversion to
and from L mode has also been added.
BGR;* modes BGR;* modes
^^^^^^^^^^^ ^^^^^^^^^^^

View File

@ -48,7 +48,6 @@ docs =
sphinx>=2.4 sphinx>=2.4
sphinx-copybutton sphinx-copybutton
sphinx-inline-tabs sphinx-inline-tabs
sphinx-issues>=3.0.1
sphinx-removed-in sphinx-removed-in
sphinxext-opengraph sphinxext-opengraph
tests = tests =

View File

@ -423,7 +423,6 @@ class ImageDraw:
self.draw.draw_rectangle(right, ink, 1) self.draw.draw_rectangle(right, ink, 1)
def _multiline_check(self, text): def _multiline_check(self, text):
"""Draw text."""
split_character = "\n" if isinstance(text, str) else b"\n" split_character = "\n" if isinstance(text, str) else b"\n"
return split_character in text return split_character in text
@ -464,6 +463,7 @@ class ImageDraw:
*args, *args,
**kwargs, **kwargs,
): ):
"""Draw text."""
if self._multiline_check(text): if self._multiline_check(text):
return self.multiline_text( return self.multiline_text(
xy, xy,

View File

@ -218,6 +218,8 @@ class Jpeg2KImageFile(ImageFile.ImageFile):
self._size, self.mode, self.custom_mimetype, dpi = header self._size, self.mode, self.custom_mimetype, dpi = header
if dpi is not None: if dpi is not None:
self.info["dpi"] = dpi self.info["dpi"] = dpi
if self.fp.read(12).endswith(b"jp2c\xff\x4f\xff\x51"):
self._parse_comment()
else: else:
msg = "not a JPEG 2000 file" msg = "not a JPEG 2000 file"
raise SyntaxError(msg) raise SyntaxError(msg)
@ -254,6 +256,28 @@ class Jpeg2KImageFile(ImageFile.ImageFile):
) )
] ]
def _parse_comment(self):
hdr = self.fp.read(2)
length = struct.unpack(">H", hdr)[0]
self.fp.seek(length - 2, os.SEEK_CUR)
while True:
marker = self.fp.read(2)
if not marker:
break
typ = marker[1]
if typ in (0x90, 0xD9):
# Start of tile or end of codestream
break
hdr = self.fp.read(2)
length = struct.unpack(">H", hdr)[0]
if typ == 0x64:
# Comment
self.info["comment"] = self.fp.read(length - 2)[2:]
break
else:
self.fp.seek(length - 2, os.SEEK_CUR)
@property @property
def reduce(self): def reduce(self):
# https://github.com/python-pillow/Pillow/issues/4343 found that the # https://github.com/python-pillow/Pillow/issues/4343 found that the

View File

@ -1003,9 +1003,13 @@ class PngImageFile(ImageFile.ImageFile):
else: else:
if self._prev_im and self.blend_op == Blend.OP_OVER: if self._prev_im and self.blend_op == Blend.OP_OVER:
updated = self._crop(self.im, self.dispose_extent) updated = self._crop(self.im, self.dispose_extent)
self._prev_im.paste( if self.im.mode == "RGB" and "transparency" in self.info:
updated, self.dispose_extent, updated.convert("RGBA") mask = updated.convert_transparent(
) "RGBA", self.info["transparency"]
)
else:
mask = updated.convert("RGBA")
self._prev_im.paste(updated, self.dispose_extent, mask)
self.im = self._prev_im self.im = self._prev_im
if self.pyaccess: if self.pyaccess:
self.pyaccess = None self.pyaccess = None

View File

@ -320,6 +320,7 @@ mode_map = {
"1": _PyAccess8, "1": _PyAccess8,
"L": _PyAccess8, "L": _PyAccess8,
"P": _PyAccess8, "P": _PyAccess8,
"I;16N": _PyAccessI16_N,
"LA": _PyAccess32_2, "LA": _PyAccess32_2,
"La": _PyAccess32_2, "La": _PyAccess32_2,
"PA": _PyAccess32_2, "PA": _PyAccess32_2,

View File

@ -1807,7 +1807,7 @@ def _save(im, fp, filename):
# Custom items are supported for int, float, unicode, string and byte # Custom items are supported for int, float, unicode, string and byte
# values. Other types and tuples require a tagtype. # values. Other types and tuples require a tagtype.
if tag not in TiffTags.LIBTIFF_CORE: if tag not in TiffTags.LIBTIFF_CORE:
if not Image.core.libtiff_support_custom_tags: if not getattr(Image.core, "libtiff_support_custom_tags", False):
continue continue
if tag in ifd.tagtype: if tag in ifd.tagtype:

View File

@ -285,7 +285,7 @@ def _save_all(im, fp, filename):
# Append the frame to the animation encoder # Append the frame to the animation encoder
enc.add( enc.add(
frame.tobytes("raw", rawmode), frame.tobytes("raw", rawmode),
timestamp, round(timestamp),
frame.size[0], frame.size[0],
frame.size[1], frame.size[1],
rawmode, rawmode,
@ -305,7 +305,7 @@ def _save_all(im, fp, filename):
im.seek(cur_idx) im.seek(cur_idx)
# Force encoder to flush frames # Force encoder to flush frames
enc.add(None, timestamp, 0, 0, "", lossless, quality, 0) enc.add(None, round(timestamp), 0, 0, "", lossless, quality, 0)
# Get the final output from the encoder # Get the final output from the encoder
data = enc.assemble(icc_profile, exif, xmp) data = enc.assemble(icc_profile, exif, xmp)

View File

@ -3846,6 +3846,7 @@ static PyTypeObject PixelAccess_Type = {
static PyObject * static PyObject *
_get_stats(PyObject *self, PyObject *args) { _get_stats(PyObject *self, PyObject *args) {
PyObject *d; PyObject *d;
PyObject *v;
ImagingMemoryArena arena = &ImagingDefaultArena; ImagingMemoryArena arena = &ImagingDefaultArena;
if (!PyArg_ParseTuple(args, ":get_stats")) { if (!PyArg_ParseTuple(args, ":get_stats")) {
@ -3856,15 +3857,29 @@ _get_stats(PyObject *self, PyObject *args) {
if (!d) { if (!d) {
return NULL; return NULL;
} }
PyDict_SetItemString(d, "new_count", PyLong_FromLong(arena->stats_new_count)); v = PyLong_FromLong(arena->stats_new_count);
PyDict_SetItemString( PyDict_SetItemString(d, "new_count", v ? v : Py_None);
d, "allocated_blocks", PyLong_FromLong(arena->stats_allocated_blocks)); Py_XDECREF(v);
PyDict_SetItemString(
d, "reused_blocks", PyLong_FromLong(arena->stats_reused_blocks)); v = PyLong_FromLong(arena->stats_allocated_blocks);
PyDict_SetItemString( PyDict_SetItemString(d, "allocated_blocks", v ? v : Py_None);
d, "reallocated_blocks", PyLong_FromLong(arena->stats_reallocated_blocks)); Py_XDECREF(v);
PyDict_SetItemString(d, "freed_blocks", PyLong_FromLong(arena->stats_freed_blocks));
PyDict_SetItemString(d, "blocks_cached", PyLong_FromLong(arena->blocks_cached)); v = PyLong_FromLong(arena->stats_reused_blocks);
PyDict_SetItemString(d, "reused_blocks", v ? v : Py_None);
Py_XDECREF(v);
v = PyLong_FromLong(arena->stats_reallocated_blocks);
PyDict_SetItemString(d, "reallocated_blocks", v ? v : Py_None);
Py_XDECREF(v);
v = PyLong_FromLong(arena->stats_freed_blocks);
PyDict_SetItemString(d, "freed_blocks", v ? v : Py_None);
Py_XDECREF(v);
v = PyLong_FromLong(arena->blocks_cached);
PyDict_SetItemString(d, "blocks_cached", v ? v : Py_None);
Py_XDECREF(v);
return d; return d;
} }
@ -4233,28 +4248,33 @@ setup_module(PyObject *m) {
#ifdef HAVE_LIBJPEG #ifdef HAVE_LIBJPEG
{ {
extern const char *ImagingJpegVersion(void); extern const char *ImagingJpegVersion(void);
PyDict_SetItemString( PyObject *v = PyUnicode_FromString(ImagingJpegVersion());
d, "jpeglib_version", PyUnicode_FromString(ImagingJpegVersion())); PyDict_SetItemString(d, "jpeglib_version", v ? v : Py_None);
Py_XDECREF(v);
} }
#endif #endif
#ifdef HAVE_OPENJPEG #ifdef HAVE_OPENJPEG
{ {
extern const char *ImagingJpeg2KVersion(void); extern const char *ImagingJpeg2KVersion(void);
PyDict_SetItemString( PyObject *v = PyUnicode_FromString(ImagingJpeg2KVersion());
d, "jp2klib_version", PyUnicode_FromString(ImagingJpeg2KVersion())); PyDict_SetItemString(d, "jp2klib_version", v ? v : Py_None);
Py_XDECREF(v);
} }
#endif #endif
PyObject *have_libjpegturbo; PyObject *have_libjpegturbo;
#ifdef LIBJPEG_TURBO_VERSION #ifdef LIBJPEG_TURBO_VERSION
have_libjpegturbo = Py_True; have_libjpegturbo = Py_True;
{
#define tostr1(a) #a #define tostr1(a) #a
#define tostr(a) tostr1(a) #define tostr(a) tostr1(a)
PyDict_SetItemString( PyObject *v = PyUnicode_FromString(tostr(LIBJPEG_TURBO_VERSION));
d, "libjpeg_turbo_version", PyUnicode_FromString(tostr(LIBJPEG_TURBO_VERSION))); PyDict_SetItemString(d, "libjpeg_turbo_version", v ? v : Py_None);
Py_XDECREF(v);
#undef tostr #undef tostr
#undef tostr1 #undef tostr1
}
#else #else
have_libjpegturbo = Py_False; have_libjpegturbo = Py_False;
#endif #endif
@ -4266,8 +4286,9 @@ setup_module(PyObject *m) {
have_libimagequant = Py_True; have_libimagequant = Py_True;
{ {
extern const char *ImagingImageQuantVersion(void); extern const char *ImagingImageQuantVersion(void);
PyDict_SetItemString( PyObject *v = PyUnicode_FromString(ImagingImageQuantVersion());
d, "imagequant_version", PyUnicode_FromString(ImagingImageQuantVersion())); PyDict_SetItemString(d, "imagequant_version", v ? v : Py_None);
Py_XDECREF(v);
} }
#else #else
have_libimagequant = Py_False; have_libimagequant = Py_False;
@ -4284,16 +4305,18 @@ setup_module(PyObject *m) {
PyModule_AddIntConstant(m, "FIXED", Z_FIXED); PyModule_AddIntConstant(m, "FIXED", Z_FIXED);
{ {
extern const char *ImagingZipVersion(void); extern const char *ImagingZipVersion(void);
PyDict_SetItemString( PyObject *v = PyUnicode_FromString(ImagingZipVersion());
d, "zlib_version", PyUnicode_FromString(ImagingZipVersion())); PyDict_SetItemString(d, "zlib_version", v ? v : Py_None);
Py_XDECREF(v);
} }
#endif #endif
#ifdef HAVE_LIBTIFF #ifdef HAVE_LIBTIFF
{ {
extern const char *ImagingTiffVersion(void); extern const char *ImagingTiffVersion(void);
PyDict_SetItemString( PyObject *v = PyUnicode_FromString(ImagingTiffVersion());
d, "libtiff_version", PyUnicode_FromString(ImagingTiffVersion())); PyDict_SetItemString(d, "libtiff_version", v ? v : Py_None);
Py_XDECREF(v);
// Test for libtiff 4.0 or later, excluding libtiff 3.9.6 and 3.9.7 // Test for libtiff 4.0 or later, excluding libtiff 3.9.6 and 3.9.7
PyObject *support_custom_tags; PyObject *support_custom_tags;
@ -4316,7 +4339,9 @@ setup_module(PyObject *m) {
Py_INCREF(have_xcb); Py_INCREF(have_xcb);
PyModule_AddObject(m, "HAVE_XCB", have_xcb); PyModule_AddObject(m, "HAVE_XCB", have_xcb);
PyDict_SetItemString(d, "PILLOW_VERSION", PyUnicode_FromString(version)); PyObject *pillow_version = PyUnicode_FromString(version);
PyDict_SetItemString(d, "PILLOW_VERSION", pillow_version ? pillow_version : Py_None);
Py_XDECREF(pillow_version);
return 0; return 0;
} }

View File

@ -950,6 +950,8 @@ _is_intent_supported(CmsProfileObject *self, int clut) {
return Py_None; return Py_None;
} }
PyDict_SetItem(result, id, entry); PyDict_SetItem(result, id, entry);
Py_DECREF(id);
Py_DECREF(entry);
} }
return result; return result;
} }
@ -1531,7 +1533,8 @@ setup_module(PyObject *m) {
} else { } else {
v = PyUnicode_FromFormat("%d.%d", vn / 1000, (vn / 10) % 100); v = PyUnicode_FromFormat("%d.%d", vn / 1000, (vn / 10) % 100);
} }
PyDict_SetItemString(d, "littlecms_version", v); PyDict_SetItemString(d, "littlecms_version", v ? v : Py_None);
Py_XDECREF(v);
return 0; return 0;
} }

View File

@ -1129,11 +1129,17 @@ font_getvaraxes(FontObject *self) {
axis = master->axis[i]; axis = master->axis[i];
list_axis = PyDict_New(); list_axis = PyDict_New();
PyDict_SetItemString( PyObject *minimum = PyLong_FromLong(axis.minimum / 65536);
list_axis, "minimum", PyLong_FromLong(axis.minimum / 65536)); PyDict_SetItemString(list_axis, "minimum", minimum ? minimum : Py_None);
PyDict_SetItemString(list_axis, "default", PyLong_FromLong(axis.def / 65536)); Py_XDECREF(minimum);
PyDict_SetItemString(
list_axis, "maximum", PyLong_FromLong(axis.maximum / 65536)); PyObject *def = PyLong_FromLong(axis.def / 65536);
PyDict_SetItemString(list_axis, "default", def ? def : Py_None);
Py_XDECREF(def);
PyObject *maximum = PyLong_FromLong(axis.maximum / 65536);
PyDict_SetItemString(list_axis, "maximum", maximum ? maximum : Py_None);
Py_XDECREF(maximum);
for (j = 0; j < name_count; j++) { for (j = 0; j < name_count; j++) {
error = FT_Get_Sfnt_Name(self->face, j, &name); error = FT_Get_Sfnt_Name(self->face, j, &name);
@ -1143,7 +1149,8 @@ font_getvaraxes(FontObject *self) {
if (name.name_id == axis.strid) { if (name.name_id == axis.strid) {
axis_name = Py_BuildValue("y#", name.string, name.string_len); axis_name = Py_BuildValue("y#", name.string, name.string_len);
PyDict_SetItemString(list_axis, "name", axis_name); PyDict_SetItemString(list_axis, "name", axis_name ? axis_name : Py_None);
Py_XDECREF(axis_name);
break; break;
} }
} }
@ -1358,7 +1365,8 @@ setup_module(PyObject *m) {
FT_Library_Version(library, &major, &minor, &patch); FT_Library_Version(library, &major, &minor, &patch);
v = PyUnicode_FromFormat("%d.%d.%d", major, minor, patch); v = PyUnicode_FromFormat("%d.%d.%d", major, minor, patch);
PyDict_SetItemString(d, "freetype2_version", v); PyDict_SetItemString(d, "freetype2_version", v ? v : Py_None);
Py_XDECREF(v);
#ifdef HAVE_RAQM #ifdef HAVE_RAQM
#if defined(HAVE_RAQM_SYSTEM) || defined(HAVE_FRIBIDI_SYSTEM) #if defined(HAVE_RAQM_SYSTEM) || defined(HAVE_FRIBIDI_SYSTEM)
@ -1376,35 +1384,34 @@ setup_module(PyObject *m) {
PyDict_SetItemString(d, "HAVE_RAQM", v); PyDict_SetItemString(d, "HAVE_RAQM", v);
PyDict_SetItemString(d, "HAVE_FRIBIDI", v); PyDict_SetItemString(d, "HAVE_FRIBIDI", v);
PyDict_SetItemString(d, "HAVE_HARFBUZZ", v); PyDict_SetItemString(d, "HAVE_HARFBUZZ", v);
Py_DECREF(v);
if (have_raqm) { if (have_raqm) {
v = NULL;
#ifdef RAQM_VERSION_MAJOR #ifdef RAQM_VERSION_MAJOR
v = PyUnicode_FromString(raqm_version_string()); v = PyUnicode_FromString(raqm_version_string());
#else
v = Py_None;
#endif #endif
PyDict_SetItemString(d, "raqm_version", v); PyDict_SetItemString(d, "raqm_version", v ? v : Py_None);
Py_XDECREF(v);
v = NULL;
#ifdef FRIBIDI_MAJOR_VERSION #ifdef FRIBIDI_MAJOR_VERSION
{ {
const char *a = strchr(fribidi_version_info, ')'); const char *a = strchr(fribidi_version_info, ')');
const char *b = strchr(fribidi_version_info, '\n'); const char *b = strchr(fribidi_version_info, '\n');
if (a && b && a + 2 < b) { if (a && b && a + 2 < b) {
v = PyUnicode_FromStringAndSize(a + 2, b - (a + 2)); v = PyUnicode_FromStringAndSize(a + 2, b - (a + 2));
} else {
v = Py_None;
} }
} }
#else
v = Py_None;
#endif #endif
PyDict_SetItemString(d, "fribidi_version", v); PyDict_SetItemString(d, "fribidi_version", v ? v : Py_None);
Py_XDECREF(v);
v = NULL;
#ifdef HB_VERSION_STRING #ifdef HB_VERSION_STRING
v = PyUnicode_FromString(hb_version_string()); v = PyUnicode_FromString(hb_version_string());
#else
v = Py_None;
#endif #endif
PyDict_SetItemString(d, "harfbuzz_version", v); PyDict_SetItemString(d, "harfbuzz_version", v ? v : Py_None);
Py_XDECREF(v);
} }
return 0; return 0;

View File

@ -194,6 +194,7 @@ match(PyObject *self, PyObject *args) {
if (lut[lut_idx]) { if (lut[lut_idx]) {
PyObject *coordObj = Py_BuildValue("(nn)", col_idx, row_idx); PyObject *coordObj = Py_BuildValue("(nn)", col_idx, row_idx);
PyList_Append(ret, coordObj); PyList_Append(ret, coordObj);
Py_XDECREF(coordObj);
} }
} }
} }
@ -230,21 +231,13 @@ get_on_pixels(PyObject *self, PyObject *args) {
if (row[col_idx]) { if (row[col_idx]) {
PyObject *coordObj = Py_BuildValue("(nn)", col_idx, row_idx); PyObject *coordObj = Py_BuildValue("(nn)", col_idx, row_idx);
PyList_Append(ret, coordObj); PyList_Append(ret, coordObj);
Py_XDECREF(coordObj);
} }
} }
} }
return ret; return ret;
} }
static int
setup_module(PyObject *m) {
PyObject *d = PyModule_GetDict(m);
PyDict_SetItemString(d, "__version", PyUnicode_FromString("0.1"));
return 0;
}
static PyMethodDef functions[] = { static PyMethodDef functions[] = {
/* Functions */ /* Functions */
{"apply", (PyCFunction)apply, METH_VARARGS, NULL}, {"apply", (PyCFunction)apply, METH_VARARGS, NULL},
@ -266,9 +259,5 @@ PyInit__imagingmorph(void) {
m = PyModule_Create(&module_def); m = PyModule_Create(&module_def);
if (setup_module(m) < 0) {
return NULL;
}
return m; return m;
} }

View File

@ -949,8 +949,10 @@ addAnimFlagToModule(PyObject *m) {
void void
addTransparencyFlagToModule(PyObject *m) { addTransparencyFlagToModule(PyObject *m) {
PyModule_AddObject( PyObject *have_transparency = PyBool_FromLong(!WebPDecoderBuggyAlpha());
m, "HAVE_TRANSPARENCY", PyBool_FromLong(!WebPDecoderBuggyAlpha())); if (PyModule_AddObject(m, "HAVE_TRANSPARENCY", have_transparency)) {
Py_DECREF(have_transparency);
}
} }
static int static int
@ -967,8 +969,9 @@ setup_module(PyObject *m) {
addAnimFlagToModule(m); addAnimFlagToModule(m);
addTransparencyFlagToModule(m); addTransparencyFlagToModule(m);
PyDict_SetItemString( PyObject *v = PyUnicode_FromString(WebPDecoderVersion_str());
d, "webpdecoder_version", PyUnicode_FromString(WebPDecoderVersion_str())); PyDict_SetItemString(d, "webpdecoder_version", v ? v : Py_None);
Py_XDECREF(v);
return 0; return 0;
} }

View File

@ -13,7 +13,7 @@
/* use make_hash.py from the pillow-scripts repository to calculate these values */ /* use make_hash.py from the pillow-scripts repository to calculate these values */
#define ACCESS_TABLE_SIZE 27 #define ACCESS_TABLE_SIZE 27
#define ACCESS_TABLE_HASH 3078 #define ACCESS_TABLE_HASH 33051
static struct ImagingAccessInstance access_table[ACCESS_TABLE_SIZE]; static struct ImagingAccessInstance access_table[ACCESS_TABLE_SIZE];
@ -92,6 +92,12 @@ get_pixel_16B(Imaging im, int x, int y, void *color) {
#endif #endif
} }
static void
get_pixel_16(Imaging im, int x, int y, void *color) {
UINT8 *in = (UINT8 *)&im->image[y][x + x];
memcpy(color, in, sizeof(UINT16));
}
static void static void
get_pixel_32(Imaging im, int x, int y, void *color) { get_pixel_32(Imaging im, int x, int y, void *color) {
memcpy(color, &im->image32[y][x], sizeof(INT32)); memcpy(color, &im->image32[y][x], sizeof(INT32));
@ -186,6 +192,7 @@ ImagingAccessInit() {
ADD("I;16", get_pixel_16L, put_pixel_16L); ADD("I;16", get_pixel_16L, put_pixel_16L);
ADD("I;16L", get_pixel_16L, put_pixel_16L); ADD("I;16L", get_pixel_16L, put_pixel_16L);
ADD("I;16B", get_pixel_16B, put_pixel_16B); ADD("I;16B", get_pixel_16B, put_pixel_16B);
ADD("I;16N", get_pixel_16, put_pixel_16L);
ADD("I;32L", get_pixel_32L, put_pixel_32L); ADD("I;32L", get_pixel_32L, put_pixel_32L);
ADD("I;32B", get_pixel_32B, put_pixel_32B); ADD("I;32B", get_pixel_32B, put_pixel_32B);
ADD("F", get_pixel_32, put_pixel_32); ADD("F", get_pixel_32, put_pixel_32);

View File

@ -990,6 +990,13 @@ static struct {
{"I;16L", "L", I16L_L}, {"I;16L", "L", I16L_L},
{"L", "I;16B", L_I16B}, {"L", "I;16B", L_I16B},
{"I;16B", "L", I16B_L}, {"I;16B", "L", I16B_L},
#ifdef WORDS_BIGENDIAN
{"L", "I;16N", L_I16B},
{"I;16N", "L", I16B_L},
#else
{"L", "I;16N", L_I16L},
{"I;16N", "L", I16L_L},
#endif
{"I;16", "F", I16L_F}, {"I;16", "F", I16L_F},
{"I;16L", "F", I16L_F}, {"I;16L", "F", I16L_F},

View File

@ -664,6 +664,7 @@ static struct {
#endif #endif
{"I;16B", "I;16B", 16, copy2}, {"I;16B", "I;16B", 16, copy2},
{"I;16L", "I;16L", 16, copy2}, {"I;16L", "I;16L", 16, copy2},
{"I;16N", "I;16N", 16, copy2},
{"I;16", "I;16N", 16, packI16N_I16}, // LibTiff native->image endian. {"I;16", "I;16N", 16, packI16N_I16}, // LibTiff native->image endian.
{"I;16L", "I;16N", 16, packI16N_I16}, {"I;16L", "I;16N", 16, packI16N_I16},
{"I;16B", "I;16N", 16, packI16N_I16B}, {"I;16B", "I;16N", 16, packI16N_I16B},

View File

@ -1762,6 +1762,7 @@ static struct {
{"I;16", "I;16", 16, copy2}, {"I;16", "I;16", 16, copy2},
{"I;16B", "I;16B", 16, copy2}, {"I;16B", "I;16B", 16, copy2},
{"I;16L", "I;16L", 16, copy2}, {"I;16L", "I;16L", 16, copy2},
{"I;16N", "I;16N", 16, copy2},
{"I;16", "I;16N", 16, unpackI16N_I16}, // LibTiff native->image endian. {"I;16", "I;16N", 16, unpackI16N_I16}, // LibTiff native->image endian.
{"I;16L", "I;16N", 16, unpackI16N_I16}, // LibTiff native->image endian. {"I;16L", "I;16N", 16, unpackI16N_I16}, // LibTiff native->image endian.

View File

@ -152,9 +152,9 @@ deps = {
"libs": [r"*.lib"], "libs": [r"*.lib"],
}, },
"xz": { "xz": {
"url": SF_PROJECTS + "/lzmautils/files/xz-5.4.1.tar.gz/download", "url": SF_PROJECTS + "/lzmautils/files/xz-5.4.2.tar.gz/download",
"filename": "xz-5.4.1.tar.gz", "filename": "xz-5.4.2.tar.gz",
"dir": "xz-5.4.1", "dir": "xz-5.4.2",
"license": "COPYING", "license": "COPYING",
"patch": { "patch": {
r"src\liblzma\api\lzma.h": { r"src\liblzma\api\lzma.h": {