mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-13 10:46:16 +03:00
Merge branch 'main' of upstream into add-cygwin-to-ci
This commit is contained in:
commit
fa536b4d34
2
.github/workflows/test-mingw.yml
vendored
2
.github/workflows/test-mingw.yml
vendored
|
@ -60,7 +60,7 @@ jobs:
|
|||
pushd depends && ./install_extra_test_images.sh && popd
|
||||
|
||||
- name: Build Pillow
|
||||
run: CFLAGS="-coverage" python3 setup.py build_ext install
|
||||
run: CFLAGS="-coverage" python3 -m pip install --global-option="build_ext" .
|
||||
|
||||
- name: Test Pillow
|
||||
run: |
|
||||
|
|
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
|
@ -9,7 +9,7 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
os: [
|
||||
"macOS-latest",
|
||||
"macos-latest",
|
||||
"ubuntu-latest",
|
||||
]
|
||||
python-version: [
|
||||
|
@ -29,7 +29,7 @@ jobs:
|
|||
# Include new variables for Codecov
|
||||
- os: ubuntu-latest
|
||||
codecov-flag: GHA_Ubuntu
|
||||
- os: macOS-latest
|
||||
- os: macos-latest
|
||||
codecov-flag: GHA_macOS
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
|
26
.github/workflows/tidelift.yml
vendored
Normal file
26
.github/workflows/tidelift.yml
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
name: Tidelift Align
|
||||
on:
|
||||
schedule:
|
||||
- cron: "30 2 * * *" # daily at 02:30 UTC
|
||||
push:
|
||||
paths:
|
||||
- ".github/workflows/tidelift.yml"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/tidelift.yml"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
if: github.repository_owner == 'python-pillow'
|
||||
name: Run Tidelift to ensure approved open source packages are in use
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Scan
|
||||
uses: tidelift/alignment-action@main
|
||||
env:
|
||||
TIDELIFT_API_KEY: ${{ secrets.TIDELIFT_API_KEY }}
|
||||
TIDELIFT_ORGANIZATION: team/aclark4life
|
||||
TIDELIFT_PROJECT: pillow
|
|
@ -5,6 +5,12 @@ Changelog (Pillow)
|
|||
9.0.0 (unreleased)
|
||||
------------------
|
||||
|
||||
- Added ImageShow support for xdg-open #5897
|
||||
[m-shinder, radarhere]
|
||||
|
||||
- Support 16-bit grayscale ImageQt conversion #5856
|
||||
[cmbruns, radarhere]
|
||||
|
||||
- Convert subsequent GIF frames to RGB or RGBA #5857
|
||||
[radarhere]
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
include *.c
|
||||
include *.h
|
||||
include *.in
|
||||
include *.lock
|
||||
include *.md
|
||||
include *.py
|
||||
include *.rst
|
||||
|
@ -9,6 +10,7 @@ include *.txt
|
|||
include *.yaml
|
||||
include LICENSE
|
||||
include Makefile
|
||||
include Pipfile
|
||||
include tox.ini
|
||||
graft Tests
|
||||
graft src
|
||||
|
|
12
Makefile
12
Makefile
|
@ -50,16 +50,16 @@ help:
|
|||
|
||||
.PHONY: inplace
|
||||
inplace: clean
|
||||
python3 setup.py develop build_ext --inplace
|
||||
python3 -m pip install -e --global-option="build_ext" --global-option="--inplace" .
|
||||
|
||||
.PHONY: install
|
||||
install:
|
||||
python3 setup.py install
|
||||
python3 -m pip install .
|
||||
python3 selftest.py
|
||||
|
||||
.PHONY: install-coverage
|
||||
install-coverage:
|
||||
CFLAGS="-coverage -Werror=implicit-function-declaration" python3 setup.py build_ext install
|
||||
CFLAGS="-coverage -Werror=implicit-function-declaration" python3 -m pip install --global-option="build_ext" .
|
||||
python3 selftest.py
|
||||
|
||||
.PHONY: debug
|
||||
|
@ -68,7 +68,7 @@ debug:
|
|||
# for our stuff, kills optimization, and redirects to dev null so we
|
||||
# see any build failures.
|
||||
make clean > /dev/null
|
||||
CFLAGS='-g -O0' python3 setup.py build_ext install > /dev/null
|
||||
CFLAGS='-g -O0' python3 -m pip install --global-option="build_ext" . > /dev/null
|
||||
|
||||
.PHONY: install-req
|
||||
install-req:
|
||||
|
@ -83,10 +83,10 @@ install-venv:
|
|||
.PHONY: release-test
|
||||
release-test:
|
||||
$(MAKE) install-req
|
||||
python3 setup.py develop
|
||||
python3 -m pip install -e .
|
||||
python3 selftest.py
|
||||
python3 -m pytest Tests
|
||||
python3 setup.py install
|
||||
python3 -m pip install .
|
||||
-rm dist/*.egg
|
||||
-rmdir dist
|
||||
python3 -m pytest -qq
|
||||
|
|
22
Pipfile
Normal file
22
Pipfile
Normal file
|
@ -0,0 +1,22 @@
|
|||
[[source]]
|
||||
url = "https://pypi.org/simple"
|
||||
verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
black = "*"
|
||||
check-manifest = "*"
|
||||
coverage = "*"
|
||||
defusedxml = "*"
|
||||
packaging = "*"
|
||||
markdown2 = "*"
|
||||
olefile = "*"
|
||||
pyroma = "*"
|
||||
pytest = "*"
|
||||
pytest-cov = "*"
|
||||
pytest-timeout = "*"
|
||||
|
||||
[dev-packages]
|
||||
|
||||
[requires]
|
||||
python_version = "3.9"
|
324
Pipfile.lock
generated
Normal file
324
Pipfile.lock
generated
Normal file
|
@ -0,0 +1,324 @@
|
|||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "e5cad23bf4187647d53b613a64dc4792b7064bf86b08dfb5737580e32943f54d"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
"python_version": "3.9"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"attrs": {
|
||||
"hashes": [
|
||||
"sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1",
|
||||
"sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==21.2.0"
|
||||
},
|
||||
"black": {
|
||||
"hashes": [
|
||||
"sha256:77b80f693a569e2e527958459634f18df9b0ba2625ba4e0c2d5da5be42e6f2b3",
|
||||
"sha256:a615e69ae185e08fdd73e4715e260e2479c861b5740057fde6e8b4e3b7dd589f"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==21.12b0"
|
||||
},
|
||||
"build": {
|
||||
"hashes": [
|
||||
"sha256:1aaadcd69338252ade4f7ec1265e1a19184bf916d84c9b7df095f423948cb89f",
|
||||
"sha256:21b7ebbd1b22499c4dac536abc7606696ea4d909fd755e00f09f3c0f2c05e3c8"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==0.7.0"
|
||||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
"sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872",
|
||||
"sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"
|
||||
],
|
||||
"version": "==2021.10.8"
|
||||
},
|
||||
"charset-normalizer": {
|
||||
"hashes": [
|
||||
"sha256:1eecaa09422db5be9e29d7fc65664e6c33bd06f9ced7838578ba40d58bdf3721",
|
||||
"sha256:b0b883e8e874edfdece9c28f314e3dd5badf067342e42fb162203335ae61aa2c"
|
||||
],
|
||||
"markers": "python_version >= '3'",
|
||||
"version": "==2.0.9"
|
||||
},
|
||||
"check-manifest": {
|
||||
"hashes": [
|
||||
"sha256:365c94d65de4c927d9d8b505371d08ee19f9f369c86b9ac3db97c2754c827c95",
|
||||
"sha256:56dadd260a9c7d550b159796d2894b6d0bcc176a94cbc426d9bb93e5e48d12ce"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.47"
|
||||
},
|
||||
"click": {
|
||||
"hashes": [
|
||||
"sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3",
|
||||
"sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==8.0.3"
|
||||
},
|
||||
"coverage": {
|
||||
"hashes": [
|
||||
"sha256:01774a2c2c729619760320270e42cd9e797427ecfddd32c2a7b639cdc481f3c0",
|
||||
"sha256:03b20e52b7d31be571c9c06b74746746d4eb82fc260e594dc662ed48145e9efd",
|
||||
"sha256:0a7726f74ff63f41e95ed3a89fef002916c828bb5fcae83b505b49d81a066884",
|
||||
"sha256:1219d760ccfafc03c0822ae2e06e3b1248a8e6d1a70928966bafc6838d3c9e48",
|
||||
"sha256:13362889b2d46e8d9f97c421539c97c963e34031ab0cb89e8ca83a10cc71ac76",
|
||||
"sha256:174cf9b4bef0db2e8244f82059a5a72bd47e1d40e71c68ab055425172b16b7d0",
|
||||
"sha256:17e6c11038d4ed6e8af1407d9e89a2904d573be29d51515f14262d7f10ef0a64",
|
||||
"sha256:215f8afcc02a24c2d9a10d3790b21054b58d71f4b3c6f055d4bb1b15cecce685",
|
||||
"sha256:22e60a3ca5acba37d1d4a2ee66e051f5b0e1b9ac950b5b0cf4aa5366eda41d47",
|
||||
"sha256:2641f803ee9f95b1f387f3e8f3bf28d83d9b69a39e9911e5bfee832bea75240d",
|
||||
"sha256:276651978c94a8c5672ea60a2656e95a3cce2a3f31e9fb2d5ebd4c215d095840",
|
||||
"sha256:3f7c17209eef285c86f819ff04a6d4cbee9b33ef05cbcaae4c0b4e8e06b3ec8f",
|
||||
"sha256:3feac4084291642165c3a0d9eaebedf19ffa505016c4d3db15bfe235718d4971",
|
||||
"sha256:49dbff64961bc9bdd2289a2bda6a3a5a331964ba5497f694e2cbd540d656dc1c",
|
||||
"sha256:4e547122ca2d244f7c090fe3f4b5a5861255ff66b7ab6d98f44a0222aaf8671a",
|
||||
"sha256:5829192582c0ec8ca4a2532407bc14c2f338d9878a10442f5d03804a95fac9de",
|
||||
"sha256:5d6b09c972ce9200264c35a1d53d43ca55ef61836d9ec60f0d44273a31aa9f17",
|
||||
"sha256:600617008aa82032ddeace2535626d1bc212dfff32b43989539deda63b3f36e4",
|
||||
"sha256:619346d57c7126ae49ac95b11b0dc8e36c1dd49d148477461bb66c8cf13bb521",
|
||||
"sha256:63c424e6f5b4ab1cf1e23a43b12f542b0ec2e54f99ec9f11b75382152981df57",
|
||||
"sha256:6dbc1536e105adda7a6312c778f15aaabe583b0e9a0b0a324990334fd458c94b",
|
||||
"sha256:6e1394d24d5938e561fbeaa0cd3d356207579c28bd1792f25a068743f2d5b282",
|
||||
"sha256:86f2e78b1eff847609b1ca8050c9e1fa3bd44ce755b2ec30e70f2d3ba3844644",
|
||||
"sha256:8bdfe9ff3a4ea37d17f172ac0dff1e1c383aec17a636b9b35906babc9f0f5475",
|
||||
"sha256:8e2c35a4c1f269704e90888e56f794e2d9c0262fb0c1b1c8c4ee44d9b9e77b5d",
|
||||
"sha256:92b8c845527eae547a2a6617d336adc56394050c3ed8a6918683646328fbb6da",
|
||||
"sha256:9365ed5cce5d0cf2c10afc6add145c5037d3148585b8ae0e77cc1efdd6aa2953",
|
||||
"sha256:9a29311bd6429be317c1f3fe4bc06c4c5ee45e2fa61b2a19d4d1d6111cb94af2",
|
||||
"sha256:9a2b5b52be0a8626fcbffd7e689781bf8c2ac01613e77feda93d96184949a98e",
|
||||
"sha256:a4bdeb0a52d1d04123b41d90a4390b096f3ef38eee35e11f0b22c2d031222c6c",
|
||||
"sha256:a9c8c4283e17690ff1a7427123ffb428ad6a52ed720d550e299e8291e33184dc",
|
||||
"sha256:b637c57fdb8be84e91fac60d9325a66a5981f8086c954ea2772efe28425eaf64",
|
||||
"sha256:bf154ba7ee2fd613eb541c2bc03d3d9ac667080a737449d1a3fb342740eb1a74",
|
||||
"sha256:c254b03032d5a06de049ce8bca8338a5185f07fb76600afff3c161e053d88617",
|
||||
"sha256:c332d8f8d448ded473b97fefe4a0983265af21917d8b0cdcb8bb06b2afe632c3",
|
||||
"sha256:c7912d1526299cb04c88288e148c6c87c0df600eca76efd99d84396cfe00ef1d",
|
||||
"sha256:cfd9386c1d6f13b37e05a91a8583e802f8059bebfccde61a418c5808dea6bbfa",
|
||||
"sha256:d5d2033d5db1d58ae2d62f095e1aefb6988af65b4b12cb8987af409587cc0739",
|
||||
"sha256:dca38a21e4423f3edb821292e97cec7ad38086f84313462098568baedf4331f8",
|
||||
"sha256:e2cad8093172b7d1595b4ad66f24270808658e11acf43a8f95b41276162eb5b8",
|
||||
"sha256:e3db840a4dee542e37e09f30859f1612da90e1c5239a6a2498c473183a50e781",
|
||||
"sha256:edcada2e24ed68f019175c2b2af2a8b481d3d084798b8c20d15d34f5c733fa58",
|
||||
"sha256:f467bbb837691ab5a8ca359199d3429a11a01e6dfb3d9dcc676dc035ca93c0a9",
|
||||
"sha256:f506af4f27def639ba45789fa6fde45f9a217da0be05f8910458e4557eed020c",
|
||||
"sha256:f614fc9956d76d8a88a88bb41ddc12709caa755666f580af3a688899721efecd",
|
||||
"sha256:f9afb5b746781fc2abce26193d1c817b7eb0e11459510fba65d2bd77fe161d9e",
|
||||
"sha256:fb8b8ee99b3fffe4fd86f4c81b35a6bf7e4462cba019997af2fe679365db0c49"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==6.2"
|
||||
},
|
||||
"defusedxml": {
|
||||
"hashes": [
|
||||
"sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69",
|
||||
"sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.7.1"
|
||||
},
|
||||
"docutils": {
|
||||
"hashes": [
|
||||
"sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c",
|
||||
"sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==0.18.1"
|
||||
},
|
||||
"idna": {
|
||||
"hashes": [
|
||||
"sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff",
|
||||
"sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"
|
||||
],
|
||||
"markers": "python_version >= '3'",
|
||||
"version": "==3.3"
|
||||
},
|
||||
"iniconfig": {
|
||||
"hashes": [
|
||||
"sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3",
|
||||
"sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"
|
||||
],
|
||||
"version": "==1.1.1"
|
||||
},
|
||||
"markdown2": {
|
||||
"hashes": [
|
||||
"sha256:8f4ac8d9a124ab408c67361090ed512deda746c04362c36c2ec16190c720c2b0",
|
||||
"sha256:91113caf23aa662570fe21984f08fe74f814695c0a0ea8e863a8b4c4f63f9f6e"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.4.2"
|
||||
},
|
||||
"mypy-extensions": {
|
||||
"hashes": [
|
||||
"sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d",
|
||||
"sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"
|
||||
],
|
||||
"version": "==0.4.3"
|
||||
},
|
||||
"olefile": {
|
||||
"hashes": [
|
||||
"sha256:133b031eaf8fd2c9399b78b8bc5b8fcbe4c31e85295749bb17a87cba8f3c3964"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.46"
|
||||
},
|
||||
"packaging": {
|
||||
"hashes": [
|
||||
"sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb",
|
||||
"sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==21.3"
|
||||
},
|
||||
"pathspec": {
|
||||
"hashes": [
|
||||
"sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a",
|
||||
"sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"
|
||||
],
|
||||
"version": "==0.9.0"
|
||||
},
|
||||
"pep517": {
|
||||
"hashes": [
|
||||
"sha256:931378d93d11b298cf511dd634cf5ea4cb249a28ef84160b3247ee9afb4e8ab0",
|
||||
"sha256:dd884c326898e2c6e11f9e0b64940606a93eb10ea022a2e067959f3a110cf161"
|
||||
],
|
||||
"version": "==0.12.0"
|
||||
},
|
||||
"platformdirs": {
|
||||
"hashes": [
|
||||
"sha256:367a5e80b3d04d2428ffa76d33f124cf11e8fff2acdaa9b43d545f5c7d661ef2",
|
||||
"sha256:8868bbe3c3c80d42f20156f22e7131d2fb321f5bc86a2a345375c6481a67021d"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==2.4.0"
|
||||
},
|
||||
"pluggy": {
|
||||
"hashes": [
|
||||
"sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159",
|
||||
"sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==1.0.0"
|
||||
},
|
||||
"py": {
|
||||
"hashes": [
|
||||
"sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719",
|
||||
"sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==1.11.0"
|
||||
},
|
||||
"pygments": {
|
||||
"hashes": [
|
||||
"sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380",
|
||||
"sha256:f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6"
|
||||
],
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==2.10.0"
|
||||
},
|
||||
"pyparsing": {
|
||||
"hashes": [
|
||||
"sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4",
|
||||
"sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==3.0.6"
|
||||
},
|
||||
"pyroma": {
|
||||
"hashes": [
|
||||
"sha256:0fba67322913026091590e68e0d9e0d4fbd6420fcf34d315b2ad6985ab104d65",
|
||||
"sha256:f8c181e0d5d292f11791afc18f7d0218a83c85cf64d6f8fb1571ce9d29a24e4a"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.2"
|
||||
},
|
||||
"pytest": {
|
||||
"hashes": [
|
||||
"sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89",
|
||||
"sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==6.2.5"
|
||||
},
|
||||
"pytest-cov": {
|
||||
"hashes": [
|
||||
"sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6",
|
||||
"sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.0.0"
|
||||
},
|
||||
"pytest-timeout": {
|
||||
"hashes": [
|
||||
"sha256:e6f98b54dafde8d70e4088467ff621260b641eb64895c4195b6e5c8f45638112",
|
||||
"sha256:fe9c3d5006c053bb9e062d60f641e6a76d6707aedb645350af9593e376fcc717"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.0.2"
|
||||
},
|
||||
"requests": {
|
||||
"hashes": [
|
||||
"sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24",
|
||||
"sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
|
||||
"version": "==2.26.0"
|
||||
},
|
||||
"setuptools": {
|
||||
"hashes": [
|
||||
"sha256:5ec2bbb534ed160b261acbbdd1b463eb3cf52a8d223d96a8ab9981f63798e85c",
|
||||
"sha256:75fd345a47ce3d79595b27bf57e6f49c2ca7904f3c7ce75f8a87012046c86b0b"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==60.0.0"
|
||||
},
|
||||
"toml": {
|
||||
"hashes": [
|
||||
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
|
||||
"sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
|
||||
],
|
||||
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'",
|
||||
"version": "==0.10.2"
|
||||
},
|
||||
"tomli": {
|
||||
"hashes": [
|
||||
"sha256:05b6166bff487dc068d322585c7ea4ef78deed501cc124060e0f238e89a9231f",
|
||||
"sha256:e3069e4be3ead9668e21cb9b074cd948f7b3113fd9c8bba083f48247aab8b11c"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==1.2.3"
|
||||
},
|
||||
"typing-extensions": {
|
||||
"hashes": [
|
||||
"sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e",
|
||||
"sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==4.0.1"
|
||||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
"sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece",
|
||||
"sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'",
|
||||
"version": "==1.26.7"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
}
|
|
@ -48,6 +48,9 @@ As of 2019, Pillow development is
|
|||
<a href="https://codecov.io/gh/python-pillow/Pillow"><img
|
||||
alt="Code coverage"
|
||||
src="https://codecov.io/gh/python-pillow/Pillow/branch/main/graph/badge.svg"></a>
|
||||
<a href="https://github.com/python-pillow/Pillow/actions/workflows/tidelift.yml"><img
|
||||
alt="Tidelift Align"
|
||||
src="https://github.com/python-pillow/Pillow/actions/workflows/tidelift.yml/badge.svg"></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -41,7 +41,7 @@ def test_sanity():
|
|||
def test_default():
|
||||
|
||||
im = hopper("P")
|
||||
assert_image(im, "P", im.size)
|
||||
assert im.mode == "P"
|
||||
converted_im = im.convert()
|
||||
assert_image(converted_im, "RGB", im.size)
|
||||
converted_im = im.convert()
|
||||
|
|
|
@ -2,18 +2,18 @@ import pytest
|
|||
|
||||
from PIL import Image
|
||||
|
||||
from .helper import assert_image, assert_image_similar, hopper, is_ppc64le
|
||||
from .helper import assert_image_similar, hopper, is_ppc64le
|
||||
|
||||
|
||||
def test_sanity():
|
||||
image = hopper()
|
||||
converted = image.quantize()
|
||||
assert_image(converted, "P", converted.size)
|
||||
assert converted.mode == "P"
|
||||
assert_image_similar(converted.convert("RGB"), image, 10)
|
||||
|
||||
image = hopper()
|
||||
converted = image.quantize(palette=hopper("P"))
|
||||
assert_image(converted, "P", converted.size)
|
||||
assert converted.mode == "P"
|
||||
assert_image_similar(converted.convert("RGB"), image, 60)
|
||||
|
||||
|
||||
|
@ -27,7 +27,7 @@ def test_libimagequant_quantize():
|
|||
pytest.skip("libimagequant support not available")
|
||||
else:
|
||||
raise
|
||||
assert_image(converted, "P", converted.size)
|
||||
assert converted.mode == "P"
|
||||
assert_image_similar(converted.convert("RGB"), image, 15)
|
||||
assert len(converted.getcolors()) == 100
|
||||
|
||||
|
@ -35,7 +35,7 @@ def test_libimagequant_quantize():
|
|||
def test_octree_quantize():
|
||||
image = hopper()
|
||||
converted = image.quantize(100, Image.FASTOCTREE)
|
||||
assert_image(converted, "P", converted.size)
|
||||
assert converted.mode == "P"
|
||||
assert_image_similar(converted.convert("RGB"), image, 20)
|
||||
assert len(converted.getcolors()) == 100
|
||||
|
||||
|
@ -52,7 +52,7 @@ def test_quantize():
|
|||
with Image.open("Tests/images/caption_6_33_22.png") as image:
|
||||
image = image.convert("RGB")
|
||||
converted = image.quantize()
|
||||
assert_image(converted, "P", converted.size)
|
||||
assert converted.mode == "P"
|
||||
assert_image_similar(converted.convert("RGB"), image, 1)
|
||||
|
||||
|
||||
|
@ -62,7 +62,7 @@ def test_quantize_no_dither():
|
|||
palette = palette.convert("P")
|
||||
|
||||
converted = image.quantize(dither=0, palette=palette)
|
||||
assert_image(converted, "P", converted.size)
|
||||
assert converted.mode == "P"
|
||||
assert converted.palette.palette == palette.palette.palette
|
||||
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import pytest
|
|||
|
||||
from PIL import Image, ImageGrab
|
||||
|
||||
from .helper import assert_image, assert_image_equal_tofile, skip_unless_feature
|
||||
from .helper import assert_image_equal_tofile, skip_unless_feature
|
||||
|
||||
|
||||
class TestImageGrab:
|
||||
|
@ -14,25 +14,20 @@ class TestImageGrab:
|
|||
sys.platform not in ("win32", "darwin"), reason="requires Windows or macOS"
|
||||
)
|
||||
def test_grab(self):
|
||||
for im in [
|
||||
ImageGrab.grab(),
|
||||
ImageGrab.grab(include_layered_windows=True),
|
||||
ImageGrab.grab(all_screens=True),
|
||||
]:
|
||||
assert_image(im, im.mode, im.size)
|
||||
ImageGrab.grab()
|
||||
ImageGrab.grab(include_layered_windows=True)
|
||||
ImageGrab.grab(all_screens=True)
|
||||
|
||||
im = ImageGrab.grab(bbox=(10, 20, 50, 80))
|
||||
assert_image(im, im.mode, (40, 60))
|
||||
assert im.size == (40, 60)
|
||||
|
||||
@skip_unless_feature("xcb")
|
||||
def test_grab_x11(self):
|
||||
try:
|
||||
if sys.platform not in ("win32", "darwin"):
|
||||
im = ImageGrab.grab()
|
||||
assert_image(im, im.mode, im.size)
|
||||
ImageGrab.grab()
|
||||
|
||||
im2 = ImageGrab.grab(xdisplay="")
|
||||
assert_image(im2, im2.mode, im2.size)
|
||||
ImageGrab.grab(xdisplay="")
|
||||
except OSError as e:
|
||||
pytest.skip(str(e))
|
||||
|
||||
|
@ -71,8 +66,7 @@ $bmp = New-Object Drawing.Bitmap 200, 200
|
|||
assert str(e.value) == "ImageGrab.grabclipboard() is macOS and Windows only"
|
||||
return
|
||||
|
||||
im = ImageGrab.grabclipboard()
|
||||
assert_image(im, im.mode, im.size)
|
||||
ImageGrab.grabclipboard()
|
||||
|
||||
@pytest.mark.skipif(sys.platform != "win32", reason="Windows only")
|
||||
def test_grabclipboard_file(self):
|
||||
|
|
|
@ -2,7 +2,7 @@ import pytest
|
|||
|
||||
from PIL import ImageQt
|
||||
|
||||
from .helper import hopper
|
||||
from .helper import assert_image_similar, hopper
|
||||
|
||||
pytestmark = pytest.mark.skipif(
|
||||
not ImageQt.qt_is_installed, reason="Qt bindings are not installed"
|
||||
|
@ -42,8 +42,17 @@ def test_rgb():
|
|||
|
||||
|
||||
def test_image():
|
||||
for mode in ("1", "RGB", "RGBA", "L", "P"):
|
||||
ImageQt.ImageQt(hopper(mode))
|
||||
modes = ["1", "RGB", "RGBA", "L", "P"]
|
||||
qt_format = ImageQt.QImage.Format if ImageQt.qt_version == "6" else ImageQt.QImage
|
||||
if hasattr(qt_format, "Format_Grayscale16"): # Qt 5.13+
|
||||
modes.append("I;16")
|
||||
|
||||
for mode in modes:
|
||||
im = hopper(mode)
|
||||
roundtripped_im = ImageQt.fromqimage(ImageQt.ImageQt(im))
|
||||
if mode not in ("RGB", "RGBA"):
|
||||
im = im.convert("RGB")
|
||||
assert_image_similar(roundtripped_im, im, 1)
|
||||
|
||||
|
||||
def test_closed_file():
|
||||
|
|
|
@ -497,6 +497,43 @@ Reading from a tar archive
|
|||
fp = TarIO.TarIO("Tests/images/hopper.tar", "hopper.jpg")
|
||||
im = Image.open(fp)
|
||||
|
||||
|
||||
Batch processing
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
Operations can be applied to multiple image files. For example, all PNG images
|
||||
in the current directory can be saved as JPEGs at reduced quality.
|
||||
|
||||
::
|
||||
|
||||
import glob
|
||||
from PIL import Image
|
||||
|
||||
|
||||
def compress_image(source_path, dest_path):
|
||||
with Image.open(source_path) as img:
|
||||
if img.mode != "RGB":
|
||||
img = img.convert("RGB")
|
||||
img.save(dest_path, "JPEG", optimize=True, quality=80)
|
||||
|
||||
|
||||
paths = glob.glob("*.png")
|
||||
for path in paths:
|
||||
compress_image(path, path[:-4] + ".jpg")
|
||||
|
||||
Since images can also be opened from a ``Path`` from the ``pathlib`` module,
|
||||
the example could be modified to use ``pathlib`` instead of the ``glob``
|
||||
module.
|
||||
|
||||
::
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
paths = Path(".").glob("*.png")
|
||||
for path in paths:
|
||||
compress_image(path, path.stem + ".jpg")
|
||||
|
||||
|
||||
Controlling the decoder
|
||||
-----------------------
|
||||
|
||||
|
|
|
@ -49,6 +49,10 @@ Pillow for enterprise is available via the Tidelift Subscription. `Learn more <h
|
|||
:target: https://tidelift.com/subscription/pkg/pypi-pillow?utm_source=pypi-pillow&utm_medium=badge
|
||||
:alt: Tidelift
|
||||
|
||||
.. image:: https://github.com/python-pillow/Pillow/actions/workflows/tidelift.yml/badge.svg
|
||||
:target: https://github.com/python-pillow/Pillow/actions/workflows/tidelift.yml
|
||||
:alt: Tidelift Align
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/pillow.svg
|
||||
:target: https://pypi.org/project/Pillow/
|
||||
:alt: Latest PyPI version
|
||||
|
|
|
@ -275,10 +275,6 @@ Build Options
|
|||
|
||||
Sample usage::
|
||||
|
||||
MAX_CONCURRENCY=1 python3 setup.py build_ext --enable-[feature] install
|
||||
|
||||
or using pip::
|
||||
|
||||
python3 -m pip install --upgrade Pillow --global-option="build_ext" --global-option="--enable-[feature]"
|
||||
|
||||
|
||||
|
@ -310,7 +306,7 @@ Now install Pillow with::
|
|||
|
||||
or from within the uncompressed source directory::
|
||||
|
||||
python3 setup.py install
|
||||
python3 -m pip install .
|
||||
|
||||
Building on Windows
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -17,6 +17,7 @@ All default viewers convert the image to be shown to PNG format.
|
|||
|
||||
The following viewers may be registered on Unix-based systems, if the given command is found:
|
||||
|
||||
.. autoclass:: PIL.ImageShow.XDGViewer
|
||||
.. autoclass:: PIL.ImageShow.DisplayViewer
|
||||
.. autoclass:: PIL.ImageShow.GmDisplayViewer
|
||||
.. autoclass:: PIL.ImageShow.EogViewer
|
||||
|
|
|
@ -1,6 +1,29 @@
|
|||
9.0.0
|
||||
-----
|
||||
|
||||
Fredrik Lundh
|
||||
=============
|
||||
|
||||
This release is dedicated to the memory of Fredrik Lundh, aka Effbot, who died in
|
||||
November 2021. Fredrik created PIL in 1995 and he was instrumental in the early
|
||||
success of Python.
|
||||
|
||||
`Guido wrote <https://mail.python.org/archives/list/python-dev@python.org/thread/36Q5QBILL3QIFIA3KHNGFBNJQKXKN7SD/>`_:
|
||||
|
||||
Fredrik was an early Python contributor (e.g. Elementtree and the 're'
|
||||
module) and his enthusiasm for the language and community were inspiring
|
||||
for all who encountered him or his work. He spent countless hours on
|
||||
comp.lang.python answering questions from newbies and advanced users alike.
|
||||
|
||||
He also co-founded an early Python startup, Secret Labs AB, which among
|
||||
other software released an IDE named PythonWorks. Fredrik also created the
|
||||
Python Imaging Library (PIL) which is still THE way to interact with images
|
||||
in Python, now most often through its Pillow fork. His effbot.org site was
|
||||
a valuable resource for generations of Python users, especially its Tkinter
|
||||
documentation.
|
||||
|
||||
Thank you, Fredrik.
|
||||
|
||||
Backwards Incompatible Changes
|
||||
==============================
|
||||
|
||||
|
@ -44,14 +67,6 @@ ImageFile.raise_ioerror
|
|||
has been removed. Use ``ImageFile.raise_oserror`` instead.
|
||||
|
||||
|
||||
Deprecations
|
||||
============
|
||||
|
||||
TODO
|
||||
^^^^
|
||||
|
||||
TODO
|
||||
|
||||
API Changes
|
||||
===========
|
||||
|
||||
|
@ -60,11 +75,19 @@ Added line width parameter to ImageDraw polygon
|
|||
|
||||
An optional line ``width`` parameter has been added to ``ImageDraw.Draw.polygon``.
|
||||
|
||||
TODO
|
||||
|
||||
API Additions
|
||||
=============
|
||||
|
||||
ImageShow.XDGViewer
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If ``xdg-open`` is present on Linux, this new :py:class:`PIL.ImageShow.Viewer` subclass
|
||||
will be registered. It displays images using the application selected by the system.
|
||||
|
||||
It is higher in priority than the other default :py:class:`PIL.ImageShow.Viewer`
|
||||
instances, so it will be preferred by ``im.show()`` or :py:func:`.ImageShow.show()`.
|
||||
|
||||
Added support for "title" argument to DisplayViewer
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -108,7 +108,7 @@ def align8to32(bytes, width, mode):
|
|||
converts each scanline of data from 8 bit to 32 bit aligned
|
||||
"""
|
||||
|
||||
bits_per_pixel = {"1": 1, "L": 8, "P": 8}[mode]
|
||||
bits_per_pixel = {"1": 1, "L": 8, "P": 8, "I;16": 16}[mode]
|
||||
|
||||
# calculate bytes per line and the extra padding if needed
|
||||
bits_per_line = bits_per_pixel * width
|
||||
|
@ -167,6 +167,10 @@ def _toqclass_helper(im):
|
|||
elif im.mode == "RGBA":
|
||||
data = im.tobytes("raw", "BGRA")
|
||||
format = qt_format.Format_ARGB32
|
||||
elif im.mode == "I;16" and hasattr(qt_format, "Format_Grayscale16"): # Qt 5.13+
|
||||
im = im.point(lambda i: i * 256)
|
||||
|
||||
format = qt_format.Format_Grayscale16
|
||||
else:
|
||||
if exclusive_fp:
|
||||
im.close()
|
||||
|
|
|
@ -186,6 +186,16 @@ class UnixViewer(Viewer):
|
|||
return 1
|
||||
|
||||
|
||||
class XDGViewer(UnixViewer):
|
||||
"""
|
||||
The freedesktop.org ``xdg-open`` command.
|
||||
"""
|
||||
|
||||
def get_command_ex(self, file, **options):
|
||||
command = executable = "xdg-open"
|
||||
return command, executable
|
||||
|
||||
|
||||
class DisplayViewer(UnixViewer):
|
||||
"""
|
||||
The ImageMagick ``display`` command.
|
||||
|
@ -233,6 +243,8 @@ class XVViewer(UnixViewer):
|
|||
|
||||
|
||||
if sys.platform not in ("win32", "darwin"): # unixoids
|
||||
if shutil.which("xdg-open"):
|
||||
register(XDGViewer)
|
||||
if shutil.which("display"):
|
||||
register(DisplayViewer)
|
||||
if shutil.which("gm"):
|
||||
|
|
|
@ -486,7 +486,7 @@ static struct PyMethodDef _anim_encoder_methods[] = {
|
|||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
// WebPAnimDecoder type definition
|
||||
// WebPAnimEncoder type definition
|
||||
static PyTypeObject WebPAnimEncoder_Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0) "WebPAnimEncoder", /*tp_name */
|
||||
sizeof(WebPAnimEncoderObject), /*tp_size */
|
||||
|
|
4
tox.ini
4
tox.ini
|
@ -11,8 +11,8 @@ minversion = 1.9
|
|||
|
||||
[testenv]
|
||||
commands =
|
||||
{envpython} setup.py clean
|
||||
{envpython} setup.py build_ext --inplace
|
||||
make clean
|
||||
{envpython} -m pip install --global-option="build_ext" --global-option="--inplace" .
|
||||
{envpython} selftest.py
|
||||
{envpython} -m pytest -W always {posargs}
|
||||
deps =
|
||||
|
|
|
@ -278,9 +278,9 @@ deps = {
|
|||
"libs": [r"imagequant.lib"],
|
||||
},
|
||||
"harfbuzz": {
|
||||
"url": "https://github.com/harfbuzz/harfbuzz/archive/3.1.2.zip",
|
||||
"filename": "harfbuzz-3.1.2.zip",
|
||||
"dir": "harfbuzz-3.1.2",
|
||||
"url": "https://github.com/harfbuzz/harfbuzz/archive/3.2.0.zip",
|
||||
"filename": "harfbuzz-3.2.0.zip",
|
||||
"dir": "harfbuzz-3.2.0",
|
||||
"build": [
|
||||
cmd_cmake("-DHB_HAVE_FREETYPE:BOOL=TRUE"),
|
||||
cmd_nmake(target="clean"),
|
||||
|
|
Loading…
Reference in New Issue
Block a user