mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-13 10:46:16 +03:00
Merge branch 'master' into mingw-setup
This commit is contained in:
commit
9667d5c6cc
52
.github/workflows/test-windows.yml
vendored
52
.github/workflows/test-windows.yml
vendored
|
@ -198,15 +198,27 @@ jobs:
|
||||||
msys:
|
msys:
|
||||||
runs-on: windows-2019
|
runs-on: windows-2019
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
mingw: ["MINGW32", "MINGW64"]
|
||||||
|
include:
|
||||||
|
- mingw: "MINGW32"
|
||||||
|
name: "MSYS2 MinGW 32-bit"
|
||||||
|
package: "mingw-w64-i686"
|
||||||
|
- mingw: "MINGW64"
|
||||||
|
name: "MSYS2 MinGW 64-bit"
|
||||||
|
package: "mingw-w64-x86_64"
|
||||||
|
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: bash.exe --login -eo pipefail "{0}"
|
shell: bash.exe --login -eo pipefail "{0}"
|
||||||
env:
|
env:
|
||||||
MSYSTEM: MINGW64
|
MSYSTEM: ${{ matrix.mingw }}
|
||||||
CHERE_INVOKING: 1
|
CHERE_INVOKING: 1
|
||||||
|
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
name: MSYS2 MinGW 64-bit
|
name: ${{ matrix.name }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
@ -218,23 +230,23 @@ jobs:
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: |
|
run: |
|
||||||
pacman -S --noconfirm \
|
pacman -S --noconfirm \
|
||||||
mingw-w64-x86_64-python3-cffi \
|
${{ matrix.package }}-python3-cffi \
|
||||||
mingw-w64-x86_64-python3-numpy \
|
${{ matrix.package }}-python3-numpy \
|
||||||
mingw-w64-x86_64-python3-olefile \
|
${{ matrix.package }}-python3-olefile \
|
||||||
mingw-w64-x86_64-python3-pip \
|
${{ matrix.package }}-python3-pip \
|
||||||
mingw-w64-x86_64-python3-pyqt5 \
|
${{ matrix.package }}-python3-pyqt5 \
|
||||||
mingw-w64-x86_64-python3-pytest \
|
${{ matrix.package }}-python3-pytest \
|
||||||
mingw-w64-x86_64-python3-pytest-cov \
|
${{ matrix.package }}-python3-pytest-cov \
|
||||||
mingw-w64-x86_64-python3-setuptools \
|
${{ matrix.package }}-python3-setuptools \
|
||||||
mingw-w64-x86_64-freetype \
|
${{ matrix.package }}-freetype \
|
||||||
mingw-w64-x86_64-ghostscript \
|
${{ matrix.package }}-ghostscript \
|
||||||
mingw-w64-x86_64-lcms2 \
|
${{ matrix.package }}-lcms2 \
|
||||||
mingw-w64-x86_64-libimagequant \
|
${{ matrix.package }}-libimagequant \
|
||||||
mingw-w64-x86_64-libjpeg-turbo \
|
${{ matrix.package }}-libjpeg-turbo \
|
||||||
mingw-w64-x86_64-libraqm \
|
${{ matrix.package }}-libraqm \
|
||||||
mingw-w64-x86_64-libtiff \
|
${{ matrix.package }}-libtiff \
|
||||||
mingw-w64-x86_64-libwebp \
|
${{ matrix.package }}-libwebp \
|
||||||
mingw-w64-x86_64-openjpeg2 \
|
${{ matrix.package }}-openjpeg2 \
|
||||||
subversion
|
subversion
|
||||||
|
|
||||||
python3 -m pip install pyroma
|
python3 -m pip install pyroma
|
||||||
|
@ -254,4 +266,4 @@ jobs:
|
||||||
python3 -m pip install codecov
|
python3 -m pip install codecov
|
||||||
bash <(curl -s https://codecov.io/bash) -F GHA_Windows
|
bash <(curl -s https://codecov.io/bash) -F GHA_Windows
|
||||||
env:
|
env:
|
||||||
CODECOV_NAME: MSYS2 MinGW 64-bit
|
CODECOV_NAME: ${{ matrix.name }}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/psf/black
|
- repo: https://github.com/psf/black
|
||||||
rev: 6bedb5c58a7d8c25aa9509f8217bc24e9797e90d # frozen: 19.10b0
|
rev: e66be67b9b6811913470f70c28b4d50f94d05b22 # frozen: 20.8b1
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: black
|
||||||
args: ["--target-version", "py35"]
|
args: ["--target-version", "py35"]
|
||||||
|
@ -9,7 +9,7 @@ repos:
|
||||||
types: []
|
types: []
|
||||||
|
|
||||||
- repo: https://github.com/timothycrosley/isort
|
- repo: https://github.com/timothycrosley/isort
|
||||||
rev: 9ae09866e278fbc6ec0383ccb16b5c84e78e6e4d # frozen: 5.3.2
|
rev: 377d260ffa6f746693f97b46d95025afc4bd8275 # frozen: 5.4.2
|
||||||
hooks:
|
hooks:
|
||||||
- id: isort
|
- id: isort
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ repos:
|
||||||
additional_dependencies: [flake8-2020, flake8-implicit-str-concat]
|
additional_dependencies: [flake8-2020, flake8-implicit-str-concat]
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/pygrep-hooks
|
- repo: https://github.com/pre-commit/pygrep-hooks
|
||||||
rev: 20b9ac745c5adaab12b845b3564c773dcc051d0e # frozen: v1.5.2
|
rev: eae6397e4c259ed3d057511f6dd5330b92867e62 # frozen: v1.6.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: python-check-blanket-noqa
|
- id: python-check-blanket-noqa
|
||||||
- id: rst-backticks
|
- id: rst-backticks
|
||||||
|
|
18
CHANGES.rst
18
CHANGES.rst
|
@ -5,6 +5,24 @@ Changelog (Pillow)
|
||||||
8.0.0 (unreleased)
|
8.0.0 (unreleased)
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
- Fix IFDRational __eq__ bug #4888
|
||||||
|
[luphord, radarhere]
|
||||||
|
|
||||||
|
- Fixed duplicate variable name #4885
|
||||||
|
[liZe, radarhere]
|
||||||
|
|
||||||
|
- Added homebrew zlib include directory #4842
|
||||||
|
[radarhere]
|
||||||
|
|
||||||
|
- Corrected inverted PDF CMYK colors #4866
|
||||||
|
[radarhere]
|
||||||
|
|
||||||
|
- Do not try to close file pointer if file pointer is empty #4823
|
||||||
|
[radarhere]
|
||||||
|
|
||||||
|
- ImageOps.autocontrast: add mask parameter #4843
|
||||||
|
[navneeth, hugovk]
|
||||||
|
|
||||||
- Read EXIF data tEXt chunk into info as bytes instead of string #4828
|
- Read EXIF data tEXt chunk into info as bytes instead of string #4828
|
||||||
[radarhere]
|
[radarhere]
|
||||||
|
|
||||||
|
|
|
@ -171,7 +171,6 @@ post patch:
|
||||||
| @ @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
| @ @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||||
0 +----------------------------------------------------------------------->Gi
|
0 +----------------------------------------------------------------------->Gi
|
||||||
0 11.33
|
0 11.33
|
||||||
|
|
||||||
"""
|
"""
|
||||||
im = hopper("RGB")
|
im = hopper("RGB")
|
||||||
exif = b"12345678" * 4096
|
exif = b"12345678" * 4096
|
||||||
|
@ -206,8 +205,7 @@ base case:
|
||||||
| :@ @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
| :@ @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||||
| :@ @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
| :@ @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||||
0 +----------------------------------------------------------------------->Gi
|
0 +----------------------------------------------------------------------->Gi
|
||||||
0 7.882
|
0 7.882"""
|
||||||
"""
|
|
||||||
im = hopper("RGB")
|
im = hopper("RGB")
|
||||||
|
|
||||||
for _ in range(iterations):
|
for _ in range(iterations):
|
||||||
|
|
|
@ -359,7 +359,10 @@ def test_apng_save_split_fdat(tmp_path):
|
||||||
with Image.open("Tests/images/old-style-jpeg-compression.png") as im:
|
with Image.open("Tests/images/old-style-jpeg-compression.png") as im:
|
||||||
frames = [im.copy(), Image.new("RGBA", im.size, (255, 0, 0, 255))]
|
frames = [im.copy(), Image.new("RGBA", im.size, (255, 0, 0, 255))]
|
||||||
im.save(
|
im.save(
|
||||||
test_file, save_all=True, default_image=True, append_images=frames,
|
test_file,
|
||||||
|
save_all=True,
|
||||||
|
default_image=True,
|
||||||
|
append_images=frames,
|
||||||
)
|
)
|
||||||
with Image.open(test_file) as im:
|
with Image.open(test_file) as im:
|
||||||
exception = None
|
exception = None
|
||||||
|
|
|
@ -99,7 +99,8 @@ class TestFileJpeg:
|
||||||
assert k > 0.9
|
assert k > 0.9
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"test_image_path", [TEST_FILE, "Tests/images/pil_sample_cmyk.jpg"],
|
"test_image_path",
|
||||||
|
[TEST_FILE, "Tests/images/pil_sample_cmyk.jpg"],
|
||||||
)
|
)
|
||||||
def test_dpi(self, test_image_path):
|
def test_dpi(self, test_image_path):
|
||||||
def test(xdpi, ydpi=None):
|
def test(xdpi, ydpi=None):
|
||||||
|
|
|
@ -768,7 +768,7 @@ class TestFileLibTiff(LibTiffTestCase):
|
||||||
assert im.mode == "RGBA"
|
assert im.mode == "RGBA"
|
||||||
assert im.size == (100, 40)
|
assert im.size == (100, 40)
|
||||||
assert im.tile, [
|
assert im.tile, [
|
||||||
("libtiff", (0, 0, 100, 40), 0, ("RGBa;16N", "tiff_lzw", False, 38236),)
|
("libtiff", (0, 0, 100, 40), 0, ("RGBa;16N", "tiff_lzw", False, 38236))
|
||||||
]
|
]
|
||||||
im.load()
|
im.load()
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,10 @@ def test_wedge():
|
||||||
im.getchannel(0), comparable.getchannel(0), 1, "Hue conversion is wrong"
|
im.getchannel(0), comparable.getchannel(0), 1, "Hue conversion is wrong"
|
||||||
)
|
)
|
||||||
assert_image_similar(
|
assert_image_similar(
|
||||||
im.getchannel(1), comparable.getchannel(1), 1, "Saturation conversion is wrong",
|
im.getchannel(1),
|
||||||
|
comparable.getchannel(1),
|
||||||
|
1,
|
||||||
|
"Saturation conversion is wrong",
|
||||||
)
|
)
|
||||||
assert_image_similar(
|
assert_image_similar(
|
||||||
im.getchannel(2), comparable.getchannel(2), 1, "Value conversion is wrong"
|
im.getchannel(2), comparable.getchannel(2), 1, "Value conversion is wrong"
|
||||||
|
@ -113,7 +116,10 @@ def test_convert():
|
||||||
im.getchannel(0), comparable.getchannel(0), 1, "Hue conversion is wrong"
|
im.getchannel(0), comparable.getchannel(0), 1, "Hue conversion is wrong"
|
||||||
)
|
)
|
||||||
assert_image_similar(
|
assert_image_similar(
|
||||||
im.getchannel(1), comparable.getchannel(1), 1, "Saturation conversion is wrong",
|
im.getchannel(1),
|
||||||
|
comparable.getchannel(1),
|
||||||
|
1,
|
||||||
|
"Saturation conversion is wrong",
|
||||||
)
|
)
|
||||||
assert_image_similar(
|
assert_image_similar(
|
||||||
im.getchannel(2), comparable.getchannel(2), 1, "Value conversion is wrong"
|
im.getchannel(2), comparable.getchannel(2), 1, "Value conversion is wrong"
|
||||||
|
@ -126,11 +132,20 @@ def test_hsv_to_rgb():
|
||||||
comparable = to_rgb_colorsys(comparable)
|
comparable = to_rgb_colorsys(comparable)
|
||||||
|
|
||||||
assert_image_similar(
|
assert_image_similar(
|
||||||
converted.getchannel(0), comparable.getchannel(0), 3, "R conversion is wrong",
|
converted.getchannel(0),
|
||||||
|
comparable.getchannel(0),
|
||||||
|
3,
|
||||||
|
"R conversion is wrong",
|
||||||
)
|
)
|
||||||
assert_image_similar(
|
assert_image_similar(
|
||||||
converted.getchannel(1), comparable.getchannel(1), 3, "G conversion is wrong",
|
converted.getchannel(1),
|
||||||
|
comparable.getchannel(1),
|
||||||
|
3,
|
||||||
|
"G conversion is wrong",
|
||||||
)
|
)
|
||||||
assert_image_similar(
|
assert_image_similar(
|
||||||
converted.getchannel(2), comparable.getchannel(2), 3, "B conversion is wrong",
|
converted.getchannel(2),
|
||||||
|
comparable.getchannel(2),
|
||||||
|
3,
|
||||||
|
"B conversion is wrong",
|
||||||
)
|
)
|
||||||
|
|
|
@ -707,7 +707,8 @@ class TestImage:
|
||||||
}
|
}
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"test_module", [PIL, Image],
|
"test_module",
|
||||||
|
[PIL, Image],
|
||||||
)
|
)
|
||||||
def test_pillow_version(self, test_module):
|
def test_pillow_version(self, test_module):
|
||||||
with pytest.warns(DeprecationWarning):
|
with pytest.warns(DeprecationWarning):
|
||||||
|
|
|
@ -132,9 +132,11 @@ class TestImageGetPixel(AccessTest):
|
||||||
|
|
||||||
# check putpixel negative index
|
# check putpixel negative index
|
||||||
im.putpixel((-1, -1), c)
|
im.putpixel((-1, -1), c)
|
||||||
assert im.getpixel((-1, -1)) == c, (
|
assert (
|
||||||
"put/getpixel roundtrip negative index failed for mode %s, color %s"
|
im.getpixel((-1, -1)) == c
|
||||||
% (mode, c)
|
), "put/getpixel roundtrip negative index failed for mode %s, color %s" % (
|
||||||
|
mode,
|
||||||
|
c,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check 0
|
# Check 0
|
||||||
|
|
|
@ -667,7 +667,10 @@ def test_floodfill_border():
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
ImageDraw.floodfill(
|
ImageDraw.floodfill(
|
||||||
im, centre_point, ImageColor.getrgb("red"), border=ImageColor.getrgb("black"),
|
im,
|
||||||
|
centre_point,
|
||||||
|
ImageColor.getrgb("red"),
|
||||||
|
border=ImageColor.getrgb("black"),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
|
|
|
@ -34,6 +34,9 @@ def test_similar():
|
||||||
(0, size_final[1] - size_bitmap[1]), text, fill=(0, 0, 0), font=font_bitmap
|
(0, size_final[1] - size_bitmap[1]), text, fill=(0, 0, 0), font=font_bitmap
|
||||||
)
|
)
|
||||||
draw_outline.text(
|
draw_outline.text(
|
||||||
(0, size_final[1] - size_outline[1]), text, fill=(0, 0, 0), font=font_outline,
|
(0, size_final[1] - size_outline[1]),
|
||||||
|
text,
|
||||||
|
fill=(0, 0, 0),
|
||||||
|
font=font_outline,
|
||||||
)
|
)
|
||||||
assert_image_similar(im_bitmap, im_outline, 20)
|
assert_image_similar(im_bitmap, im_outline, 20)
|
||||||
|
|
|
@ -19,7 +19,8 @@ def test_register():
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"order", [-1, 0],
|
"order",
|
||||||
|
[-1, 0],
|
||||||
)
|
)
|
||||||
def test_viewer_show(order):
|
def test_viewer_show(order):
|
||||||
class TestViewer(ImageShow.Viewer):
|
class TestViewer(ImageShow.Viewer):
|
||||||
|
@ -41,7 +42,8 @@ def test_viewer_show(order):
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif(
|
@pytest.mark.skipif(
|
||||||
not on_ci() or is_win32(), reason="Only run on CIs; hangs on Windows CIs",
|
not on_ci() or is_win32(),
|
||||||
|
reason="Only run on CIs; hangs on Windows CIs",
|
||||||
)
|
)
|
||||||
def test_show():
|
def test_show():
|
||||||
for mode in ("1", "I;16", "LA", "RGB", "RGBA"):
|
for mode in ("1", "I;16", "LA", "RGB", "RGBA"):
|
||||||
|
|
|
@ -450,12 +450,12 @@ These platforms are built and tested for every change.
|
||||||
| Windows Server 2016 | 3.8 |x86 |
|
| Windows Server 2016 | 3.8 |x86 |
|
||||||
| +--------------------------+-----------------------+
|
| +--------------------------+-----------------------+
|
||||||
| | 3.6 |x86-64 |
|
| | 3.6 |x86-64 |
|
||||||
| +--------------------------+-----------------------+
|
|
||||||
| | 3.7/MinGW |x86 |
|
|
||||||
+----------------------------------+--------------------------+-----------------------+
|
+----------------------------------+--------------------------+-----------------------+
|
||||||
| Windows Server 2019 | 3.6, 3.7, 3.8 |x86, x86-64 |
|
| Windows Server 2019 | 3.6, 3.7, 3.8 |x86, x86-64 |
|
||||||
| +--------------------------+-----------------------+
|
| +--------------------------+-----------------------+
|
||||||
| | PyPy3 |x86 |
|
| | PyPy3 |x86 |
|
||||||
|
| +--------------------------+-----------------------+
|
||||||
|
| | 3.8/MinGW |x86, x86-64 |
|
||||||
+----------------------------------+--------------------------+-----------------------+
|
+----------------------------------+--------------------------+-----------------------+
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1110,7 +1110,10 @@ def _write_multiple_frames(im, fp, chunk, rawmode):
|
||||||
|
|
||||||
# animation control
|
# animation control
|
||||||
chunk(
|
chunk(
|
||||||
fp, b"acTL", o32(len(im_frames)), o32(loop), # 0: num_frames # 4: num_plays
|
fp,
|
||||||
|
b"acTL",
|
||||||
|
o32(len(im_frames)), # 0: num_frames
|
||||||
|
o32(loop), # 4: num_plays
|
||||||
)
|
)
|
||||||
|
|
||||||
# default image IDAT (if it exists)
|
# default image IDAT (if it exists)
|
||||||
|
@ -1155,7 +1158,9 @@ def _write_multiple_frames(im, fp, chunk, rawmode):
|
||||||
else:
|
else:
|
||||||
fdat_chunks = _fdat(fp, chunk, seq_num)
|
fdat_chunks = _fdat(fp, chunk, seq_num)
|
||||||
ImageFile._save(
|
ImageFile._save(
|
||||||
im_frame, fdat_chunks, [("zip", (0, 0) + im_frame.size, 0, rawmode)],
|
im_frame,
|
||||||
|
fdat_chunks,
|
||||||
|
[("zip", (0, 0) + im_frame.size, 0, rawmode)],
|
||||||
)
|
)
|
||||||
seq_num = fdat_chunks.seq_num
|
seq_num = fdat_chunks.seq_num
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user