mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-04-21 17:52:00 +03:00
Merge pull request #1 from jovanovicisidora/duru
merge() function tool and coverage improvement
This commit is contained in:
commit
611cf8c815
200
.appveyor.yml
200
.appveyor.yml
|
@ -1,100 +1,100 @@
|
|||
skip_commits:
|
||||
files:
|
||||
- ".github/**/*"
|
||||
- ".gitmodules"
|
||||
- "docs/**/*"
|
||||
- "wheels/**/*"
|
||||
|
||||
version: '{build}'
|
||||
clone_folder: c:\pillow
|
||||
init:
|
||||
- ECHO %PYTHON%
|
||||
#- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
# Uncomment previous line to get RDP access during the build.
|
||||
|
||||
environment:
|
||||
COVERAGE_CORE: sysmon
|
||||
EXECUTABLE: python.exe
|
||||
TEST_OPTIONS:
|
||||
DEPLOY: YES
|
||||
matrix:
|
||||
- PYTHON: C:/Python312
|
||||
ARCHITECTURE: x86
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
|
||||
- PYTHON: C:/Python38-x64
|
||||
ARCHITECTURE: AMD64
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
|
||||
|
||||
install:
|
||||
- '%PYTHON%\%EXECUTABLE% --version'
|
||||
- '%PYTHON%\%EXECUTABLE% -m pip install --upgrade pip'
|
||||
- curl -fsSL -o pillow-test-images.zip https://github.com/python-pillow/test-images/archive/main.zip
|
||||
- 7z x pillow-test-images.zip -oc:\
|
||||
- xcopy /S /Y c:\test-images-main\* c:\pillow\tests\images
|
||||
- curl -fsSL -o nasm-win64.zip https://raw.githubusercontent.com/python-pillow/pillow-depends/main/nasm-2.16.03-win64.zip
|
||||
- 7z x nasm-win64.zip -oc:\
|
||||
- choco install ghostscript --version=10.3.1
|
||||
- path c:\nasm-2.16.03;C:\Program Files\gs\gs10.03.1\bin;%PATH%
|
||||
- cd c:\pillow\winbuild\
|
||||
- ps: |
|
||||
c:\python38\python.exe c:\pillow\winbuild\build_prepare.py -v --depends=C:\pillow-depends\
|
||||
c:\pillow\winbuild\build\build_dep_all.cmd
|
||||
$host.SetShouldExit(0)
|
||||
- path C:\pillow\winbuild\build\bin;%PATH%
|
||||
|
||||
build_script:
|
||||
- cd c:\pillow
|
||||
- winbuild\build\build_env.cmd
|
||||
- '%PYTHON%\%EXECUTABLE% -m pip install -v -C raqm=vendor -C fribidi=vendor .'
|
||||
- '%PYTHON%\%EXECUTABLE% selftest.py --installed'
|
||||
|
||||
test_script:
|
||||
- cd c:\pillow
|
||||
- '%PYTHON%\%EXECUTABLE% -m pip install pytest pytest-cov pytest-timeout defusedxml numpy olefile pyroma'
|
||||
- c:\"Program Files (x86)"\"Windows Kits"\10\Debuggers\x86\gflags.exe /p /enable %PYTHON%\%EXECUTABLE%
|
||||
- '%PYTHON%\%EXECUTABLE% -c "from PIL import Image"'
|
||||
- '%PYTHON%\%EXECUTABLE% -m pytest -vx --cov PIL --cov Tests --cov-report term --cov-report xml Tests'
|
||||
#- '%PYTHON%\%EXECUTABLE% test-installed.py -v -s %TEST_OPTIONS%' TODO TEST_OPTIONS with pytest?
|
||||
|
||||
after_test:
|
||||
- curl -Os https://uploader.codecov.io/latest/windows/codecov.exe
|
||||
- .\codecov.exe --file coverage.xml --name %PYTHON% --flags AppVeyor
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
cache:
|
||||
- '%LOCALAPPDATA%\pip\Cache'
|
||||
|
||||
artifacts:
|
||||
- path: pillow\*.egg
|
||||
name: egg
|
||||
- path: pillow\*.whl
|
||||
name: wheel
|
||||
|
||||
before_deploy:
|
||||
- cd c:\pillow
|
||||
- '%PYTHON%\%EXECUTABLE% -m pip wheel -v -C raqm=vendor -C fribidi=vendor .'
|
||||
- ps: Get-ChildItem .\*.whl | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
|
||||
|
||||
deploy:
|
||||
provider: S3
|
||||
region: us-west-2
|
||||
access_key_id: AKIAIRAXC62ZNTVQJMOQ
|
||||
secret_access_key:
|
||||
secure: Hwb6klTqtBeMgxAjRoDltiiqpuH8xbwD4UooDzBSiCWXjuFj1lyl4kHgHwTCCGqi
|
||||
bucket: pillow-nightly
|
||||
folder: win/$(APPVEYOR_BUILD_NUMBER)/
|
||||
artifact: /.*egg|wheel/
|
||||
on:
|
||||
APPVEYOR_REPO_NAME: python-pillow/Pillow
|
||||
branch: main
|
||||
deploy: YES
|
||||
|
||||
|
||||
# Uncomment the following lines to get RDP access after the build/test and block for
|
||||
# up to the timeout limit (~1hr)
|
||||
#
|
||||
#on_finish:
|
||||
#- ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
skip_commits:
|
||||
files:
|
||||
- ".github/**/*"
|
||||
- ".gitmodules"
|
||||
- "docs/**/*"
|
||||
- "wheels/**/*"
|
||||
|
||||
version: '{build}'
|
||||
clone_folder: c:\pillow
|
||||
init:
|
||||
- ECHO %PYTHON%
|
||||
#- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
# Uncomment previous line to get RDP access during the build.
|
||||
|
||||
environment:
|
||||
COVERAGE_CORE: sysmon
|
||||
EXECUTABLE: python.exe
|
||||
TEST_OPTIONS:
|
||||
DEPLOY: YES
|
||||
matrix:
|
||||
- PYTHON: C:/Python312
|
||||
ARCHITECTURE: x86
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
|
||||
- PYTHON: C:/Python38-x64
|
||||
ARCHITECTURE: AMD64
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
|
||||
|
||||
install:
|
||||
- '%PYTHON%\%EXECUTABLE% --version'
|
||||
- '%PYTHON%\%EXECUTABLE% -m pip install --upgrade pip'
|
||||
- curl -fsSL -o pillow-test-images.zip https://github.com/python-pillow/test-images/archive/main.zip
|
||||
- 7z x pillow-test-images.zip -oc:\
|
||||
- xcopy /S /Y c:\test-images-main\* c:\pillow\tests\images
|
||||
- curl -fsSL -o nasm-win64.zip https://raw.githubusercontent.com/python-pillow/pillow-depends/main/nasm-2.16.03-win64.zip
|
||||
- 7z x nasm-win64.zip -oc:\
|
||||
- choco install ghostscript --version=10.3.1
|
||||
- path c:\nasm-2.16.03;C:\Program Files\gs\gs10.03.1\bin;%PATH%
|
||||
- cd c:\pillow\winbuild\
|
||||
- ps: |
|
||||
c:\python38\python.exe c:\pillow\winbuild\build_prepare.py -v --depends=C:\pillow-depends\
|
||||
c:\pillow\winbuild\build\build_dep_all.cmd
|
||||
$host.SetShouldExit(0)
|
||||
- path C:\pillow\winbuild\build\bin;%PATH%
|
||||
|
||||
build_script:
|
||||
- cd c:\pillow
|
||||
- winbuild\build\build_env.cmd
|
||||
- '%PYTHON%\%EXECUTABLE% -m pip install -v -C raqm=vendor -C fribidi=vendor .'
|
||||
- '%PYTHON%\%EXECUTABLE% selftest.py --installed'
|
||||
|
||||
test_script:
|
||||
- cd c:\pillow
|
||||
- '%PYTHON%\%EXECUTABLE% -m pip install pytest pytest-cov pytest-timeout defusedxml numpy olefile pyroma'
|
||||
- c:\"Program Files (x86)"\"Windows Kits"\10\Debuggers\x86\gflags.exe /p /enable %PYTHON%\%EXECUTABLE%
|
||||
- '%PYTHON%\%EXECUTABLE% -c "from PIL import Image"'
|
||||
- '%PYTHON%\%EXECUTABLE% -m pytest -vx --cov PIL --cov Tests --cov-report term --cov-report xml Tests'
|
||||
#- '%PYTHON%\%EXECUTABLE% test-installed.py -v -s %TEST_OPTIONS%' TODO TEST_OPTIONS with pytest?
|
||||
|
||||
after_test:
|
||||
- curl -Os https://uploader.codecov.io/latest/windows/codecov.exe
|
||||
- .\codecov.exe --file coverage.xml --name %PYTHON% --flags AppVeyor
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
cache:
|
||||
- '%LOCALAPPDATA%\pip\Cache'
|
||||
|
||||
artifacts:
|
||||
- path: pillow\*.egg
|
||||
name: egg
|
||||
- path: pillow\*.whl
|
||||
name: wheel
|
||||
|
||||
before_deploy:
|
||||
- cd c:\pillow
|
||||
- '%PYTHON%\%EXECUTABLE% -m pip wheel -v -C raqm=vendor -C fribidi=vendor .'
|
||||
- ps: Get-ChildItem .\*.whl | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
|
||||
|
||||
deploy:
|
||||
provider: S3
|
||||
region: us-west-2
|
||||
access_key_id: AKIAIRAXC62ZNTVQJMOQ
|
||||
secret_access_key:
|
||||
secure: Hwb6klTqtBeMgxAjRoDltiiqpuH8xbwD4UooDzBSiCWXjuFj1lyl4kHgHwTCCGqi
|
||||
bucket: pillow-nightly
|
||||
folder: win/$(APPVEYOR_BUILD_NUMBER)/
|
||||
artifact: /.*egg|wheel/
|
||||
on:
|
||||
APPVEYOR_REPO_NAME: python-pillow/Pillow
|
||||
branch: main
|
||||
deploy: YES
|
||||
|
||||
|
||||
# Uncomment the following lines to get RDP access after the build/test and block for
|
||||
# up to the timeout limit (~1hr)
|
||||
#
|
||||
#on_finish:
|
||||
#- ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#!/bin/bash
|
||||
|
||||
# gather the coverage data
|
||||
python3 -m pip install coverage
|
||||
if [[ $MATRIX_DOCKER ]]; then
|
||||
python3 -m coverage xml --ignore-errors
|
||||
else
|
||||
python3 -m coverage xml
|
||||
fi
|
||||
#!/bin/bash
|
||||
|
||||
# gather the coverage data
|
||||
python3 -m pip install coverage
|
||||
if [[ $MATRIX_DOCKER ]]; then
|
||||
python3 -m coverage xml --ignore-errors
|
||||
else
|
||||
python3 -m coverage xml
|
||||
fi
|
||||
|
|
|
@ -1 +1 @@
|
|||
cibuildwheel==2.19.1
|
||||
cibuildwheel==2.19.1
|
||||
|
|
|
@ -1 +1 @@
|
|||
mypy==1.10.0
|
||||
mypy==1.10.0
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
# A clang-format style that approximates Python's PEP 7
|
||||
# Useful for IDE integration
|
||||
BasedOnStyle: Google
|
||||
AlwaysBreakAfterReturnType: All
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AlignAfterOpenBracket: AlwaysBreak
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BreakBeforeBraces: Attach
|
||||
ColumnLimit: 88
|
||||
DerivePointerAlignment: false
|
||||
IndentGotoLabels: false
|
||||
IndentWidth: 4
|
||||
Language: Cpp
|
||||
PointerAlignment: Right
|
||||
ReflowComments: true
|
||||
SortIncludes: false
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpacesInParentheses: false
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
# A clang-format style that approximates Python's PEP 7
|
||||
# Useful for IDE integration
|
||||
BasedOnStyle: Google
|
||||
AlwaysBreakAfterReturnType: All
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AlignAfterOpenBracket: AlwaysBreak
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BreakBeforeBraces: Attach
|
||||
ColumnLimit: 88
|
||||
DerivePointerAlignment: false
|
||||
IndentGotoLabels: false
|
||||
IndentWidth: 4
|
||||
Language: Cpp
|
||||
PointerAlignment: Right
|
||||
ReflowComments: true
|
||||
SortIncludes: false
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpacesInParentheses: false
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
|
|
51
.coveragerc
51
.coveragerc
|
@ -1,24 +1,27 @@
|
|||
# .coveragerc to control coverage.py
|
||||
|
||||
[report]
|
||||
# Regexes for lines to exclude from consideration
|
||||
exclude_also =
|
||||
# Don't complain if non-runnable code isn't run
|
||||
if 0:
|
||||
if __name__ == .__main__.:
|
||||
# Don't complain about debug code
|
||||
if DEBUG:
|
||||
# Don't complain about compatibility code for missing optional dependencies
|
||||
except ImportError
|
||||
if TYPE_CHECKING:
|
||||
@abc.abstractmethod
|
||||
# Empty bodies in protocols or abstract methods
|
||||
^\s*def [a-zA-Z0-9_]+\(.*\)(\s*->.*)?:\s*\.\.\.(\s*#.*)?$
|
||||
^\s*\.\.\.(\s*#.*)?$
|
||||
|
||||
[run]
|
||||
omit =
|
||||
Tests/32bit_segfault_check.py
|
||||
Tests/bench_cffi_access.py
|
||||
Tests/check_*.py
|
||||
Tests/createfontdatachunk.py
|
||||
# .coveragerc to control coverage.py
|
||||
|
||||
[report]
|
||||
# Regexes for lines to exclude from consideration
|
||||
exclude_also =
|
||||
# Don't complain if non-runnable code isn't run
|
||||
if 0:
|
||||
if __name__ == .__main__.:
|
||||
# Don't complain about debug code
|
||||
if DEBUG:
|
||||
# Don't complain about compatibility code for missing optional dependencies
|
||||
except ImportError
|
||||
if TYPE_CHECKING:
|
||||
@abc.abstractmethod
|
||||
# Empty bodies in protocols or abstract methods
|
||||
^\s*def [a-zA-Z0-9_]+\(.*\)(\s*->.*)?:\s*\.\.\.(\s*#.*)?$
|
||||
^\s*\.\.\.(\s*#.*)?$
|
||||
|
||||
[run]
|
||||
omit =
|
||||
# Tests/32bit_segfault_check.py
|
||||
# Tests/bench_cffi_access.py
|
||||
# Tests/check_*.py
|
||||
# Tests/createfontdatachunk.py
|
||||
Tests/*
|
||||
src/*
|
||||
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
# Top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
[*]
|
||||
# Unix-style newlines with a newline ending every file
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
|
||||
# Four-space indentation
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{toml,yml}]
|
||||
# Two-space indentation
|
||||
indent_size = 2
|
||||
|
||||
# Tab indentation (no size specified)
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
# Top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
[*]
|
||||
# Unix-style newlines with a newline ending every file
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
|
||||
# Four-space indentation
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{toml,yml}]
|
||||
# Two-space indentation
|
||||
indent_size = 2
|
||||
|
||||
# Tab indentation (no size specified)
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Flake8
|
||||
8de95676e0fd89f2326b3953488ab66ff29cd2d0
|
||||
# Format with Black
|
||||
53a7e3500437a9fd5826bc04758f7116bd7e52dc
|
||||
# Format the C code with ClangFormat
|
||||
46b7e86bab79450ec0a2866c6c0c679afb659d17
|
||||
# Flake8
|
||||
8de95676e0fd89f2326b3953488ab66ff29cd2d0
|
||||
# Format with Black
|
||||
53a7e3500437a9fd5826bc04758f7116bd7e52dc
|
||||
# Format the C code with ClangFormat
|
||||
46b7e86bab79450ec0a2866c6c0c679afb659d17
|
||||
|
|
6
.gitattributes
vendored
6
.gitattributes
vendored
|
@ -1,3 +1,3 @@
|
|||
*.eps binary
|
||||
*.ppm binary
|
||||
*.container binary
|
||||
*.eps binary
|
||||
*.ppm binary
|
||||
*.container binary
|
||||
|
|
78
.github/CONTRIBUTING.md
vendored
78
.github/CONTRIBUTING.md
vendored
|
@ -1,39 +1,39 @@
|
|||
# Contributing to Pillow
|
||||
|
||||
Bug fixes, feature additions, tests, documentation and more can be contributed via [issues](https://github.com/python-pillow/Pillow/issues) and/or [pull requests](https://github.com/python-pillow/Pillow/pulls). All contributions are welcome.
|
||||
|
||||
## Bug fixes, feature additions, etc.
|
||||
|
||||
Please send a pull request to the `main` branch. Please include [documentation](https://pillow.readthedocs.io) and [tests](../Tests/README.rst) for new features. Tests or documentation without bug fixes or feature additions are welcome too. Feel free to ask questions [via issues](https://github.com/python-pillow/Pillow/issues/new), [discussions](https://github.com/python-pillow/Pillow/discussions/new), [Gitter](https://gitter.im/python-pillow/Pillow) or irc://irc.freenode.net#pil
|
||||
|
||||
- Fork the Pillow repository.
|
||||
- Create a branch from `main`.
|
||||
- Develop bug fixes, features, tests, etc.
|
||||
- Run the test suite. You can enable GitHub Actions (https://github.com/MY-USERNAME/Pillow/actions) and [AppVeyor](https://ci.appveyor.com/projects/new) on your repo to catch test failures prior to the pull request, and [Codecov](https://codecov.io/gh) to see if the changed code is covered by tests.
|
||||
- Create a pull request to pull the changes from your branch to the Pillow `main`.
|
||||
|
||||
### Guidelines
|
||||
|
||||
- Separate code commits from reformatting commits.
|
||||
- Provide tests for any newly added code.
|
||||
- Follow PEP 8.
|
||||
- When committing only documentation changes please include `[ci skip]` in the commit message to avoid running tests on AppVeyor.
|
||||
- Include [release notes](https://github.com/python-pillow/Pillow/tree/main/docs/releasenotes) as needed or appropriate with your bug fixes, feature additions and tests.
|
||||
- Do not add to the [changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst) for proposed changes, as that is updated after changes are merged.
|
||||
|
||||
## Reporting Issues
|
||||
|
||||
When reporting issues, please include code that reproduces the issue and whenever possible, an image that demonstrates the issue. Please upload images to GitHub, not to third-party file hosting sites. If necessary, add the image to a zip or tar archive.
|
||||
|
||||
The best reproductions are self-contained scripts with minimal dependencies. If you are using a framework such as plone, Django, or buildout, try to replicate the issue just using Pillow.
|
||||
|
||||
### Provide details
|
||||
|
||||
- What did you do?
|
||||
- What did you expect to happen?
|
||||
- What actually happened?
|
||||
- What versions of Pillow and Python are you using?
|
||||
|
||||
## Security vulnerabilities
|
||||
|
||||
Please see our [security policy](https://github.com/python-pillow/Pillow/blob/main/.github/SECURITY.md).
|
||||
# Contributing to Pillow
|
||||
|
||||
Bug fixes, feature additions, tests, documentation and more can be contributed via [issues](https://github.com/python-pillow/Pillow/issues) and/or [pull requests](https://github.com/python-pillow/Pillow/pulls). All contributions are welcome.
|
||||
|
||||
## Bug fixes, feature additions, etc.
|
||||
|
||||
Please send a pull request to the `main` branch. Please include [documentation](https://pillow.readthedocs.io) and [tests](../Tests/README.rst) for new features. Tests or documentation without bug fixes or feature additions are welcome too. Feel free to ask questions [via issues](https://github.com/python-pillow/Pillow/issues/new), [discussions](https://github.com/python-pillow/Pillow/discussions/new), [Gitter](https://gitter.im/python-pillow/Pillow) or irc://irc.freenode.net#pil
|
||||
|
||||
- Fork the Pillow repository.
|
||||
- Create a branch from `main`.
|
||||
- Develop bug fixes, features, tests, etc.
|
||||
- Run the test suite. You can enable GitHub Actions (https://github.com/MY-USERNAME/Pillow/actions) and [AppVeyor](https://ci.appveyor.com/projects/new) on your repo to catch test failures prior to the pull request, and [Codecov](https://codecov.io/gh) to see if the changed code is covered by tests.
|
||||
- Create a pull request to pull the changes from your branch to the Pillow `main`.
|
||||
|
||||
### Guidelines
|
||||
|
||||
- Separate code commits from reformatting commits.
|
||||
- Provide tests for any newly added code.
|
||||
- Follow PEP 8.
|
||||
- When committing only documentation changes please include `[ci skip]` in the commit message to avoid running tests on AppVeyor.
|
||||
- Include [release notes](https://github.com/python-pillow/Pillow/tree/main/docs/releasenotes) as needed or appropriate with your bug fixes, feature additions and tests.
|
||||
- Do not add to the [changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst) for proposed changes, as that is updated after changes are merged.
|
||||
|
||||
## Reporting Issues
|
||||
|
||||
When reporting issues, please include code that reproduces the issue and whenever possible, an image that demonstrates the issue. Please upload images to GitHub, not to third-party file hosting sites. If necessary, add the image to a zip or tar archive.
|
||||
|
||||
The best reproductions are self-contained scripts with minimal dependencies. If you are using a framework such as plone, Django, or buildout, try to replicate the issue just using Pillow.
|
||||
|
||||
### Provide details
|
||||
|
||||
- What did you do?
|
||||
- What did you expect to happen?
|
||||
- What actually happened?
|
||||
- What versions of Pillow and Python are you using?
|
||||
|
||||
## Security vulnerabilities
|
||||
|
||||
Please see our [security policy](https://github.com/python-pillow/Pillow/blob/main/.github/SECURITY.md).
|
||||
|
|
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
|
@ -1 +1 @@
|
|||
tidelift: "pypi/pillow"
|
||||
tidelift: "pypi/pillow"
|
||||
|
|
148
.github/ISSUE_TEMPLATE/ISSUE_REPORT.md
vendored
148
.github/ISSUE_TEMPLATE/ISSUE_REPORT.md
vendored
|
@ -1,74 +1,74 @@
|
|||
---
|
||||
name: Issue report
|
||||
about: Create a report to help us improve Pillow
|
||||
---
|
||||
|
||||
<!--
|
||||
Thank you for reporting an issue.
|
||||
|
||||
Follow these guidelines to ensure your issue is handled properly.
|
||||
|
||||
If you have a ...
|
||||
|
||||
1. General question: consider asking the question on Stack Overflow
|
||||
with the python-imaging-library tag:
|
||||
|
||||
* https://stackoverflow.com/questions/tagged/python-imaging-library
|
||||
|
||||
Do not ask a question in both places.
|
||||
|
||||
If you think you have found a bug or have an unexplained exception
|
||||
then file a bug report here.
|
||||
|
||||
2. Bug report: include a self-contained, copy-pastable example that
|
||||
generates the issue if possible. Be concise with code posted.
|
||||
Guidelines on how to provide a good bug report:
|
||||
|
||||
* https://stackoverflow.com/help/mcve
|
||||
|
||||
Bug reports which follow these guidelines are easier to diagnose,
|
||||
and are often handled much more quickly.
|
||||
|
||||
3. Feature request: do a quick search of existing issues
|
||||
to make sure this has not been asked before.
|
||||
|
||||
We know asking good questions takes effort, and we appreciate your time.
|
||||
Thank you.
|
||||
-->
|
||||
|
||||
### What did you do?
|
||||
|
||||
### What did you expect to happen?
|
||||
|
||||
### What actually happened?
|
||||
|
||||
### What are your OS, Python and Pillow versions?
|
||||
|
||||
* OS:
|
||||
* Python:
|
||||
* Pillow:
|
||||
|
||||
```text
|
||||
Please paste here the output of running:
|
||||
|
||||
python3 -m PIL.report
|
||||
or
|
||||
python3 -m PIL --report
|
||||
|
||||
Or the output of the following Python code:
|
||||
|
||||
from PIL import report
|
||||
# or
|
||||
from PIL import features
|
||||
features.pilinfo(supported_formats=False)
|
||||
```
|
||||
|
||||
<!--
|
||||
Please include **code** that reproduces the issue and whenever possible, an **image** that demonstrates the issue. Please upload images to GitHub, not to third-party file hosting sites. If necessary, add the image to a zip or tar archive.
|
||||
|
||||
The best reproductions are self-contained scripts with minimal dependencies. If you are using a framework such as Plone, Django, or Buildout, try to replicate the issue just using Pillow.
|
||||
-->
|
||||
|
||||
```python
|
||||
code goes here
|
||||
```
|
||||
---
|
||||
name: Issue report
|
||||
about: Create a report to help us improve Pillow
|
||||
---
|
||||
|
||||
<!--
|
||||
Thank you for reporting an issue.
|
||||
|
||||
Follow these guidelines to ensure your issue is handled properly.
|
||||
|
||||
If you have a ...
|
||||
|
||||
1. General question: consider asking the question on Stack Overflow
|
||||
with the python-imaging-library tag:
|
||||
|
||||
* https://stackoverflow.com/questions/tagged/python-imaging-library
|
||||
|
||||
Do not ask a question in both places.
|
||||
|
||||
If you think you have found a bug or have an unexplained exception
|
||||
then file a bug report here.
|
||||
|
||||
2. Bug report: include a self-contained, copy-pastable example that
|
||||
generates the issue if possible. Be concise with code posted.
|
||||
Guidelines on how to provide a good bug report:
|
||||
|
||||
* https://stackoverflow.com/help/mcve
|
||||
|
||||
Bug reports which follow these guidelines are easier to diagnose,
|
||||
and are often handled much more quickly.
|
||||
|
||||
3. Feature request: do a quick search of existing issues
|
||||
to make sure this has not been asked before.
|
||||
|
||||
We know asking good questions takes effort, and we appreciate your time.
|
||||
Thank you.
|
||||
-->
|
||||
|
||||
### What did you do?
|
||||
|
||||
### What did you expect to happen?
|
||||
|
||||
### What actually happened?
|
||||
|
||||
### What are your OS, Python and Pillow versions?
|
||||
|
||||
* OS:
|
||||
* Python:
|
||||
* Pillow:
|
||||
|
||||
```text
|
||||
Please paste here the output of running:
|
||||
|
||||
python3 -m PIL.report
|
||||
or
|
||||
python3 -m PIL --report
|
||||
|
||||
Or the output of the following Python code:
|
||||
|
||||
from PIL import report
|
||||
# or
|
||||
from PIL import features
|
||||
features.pilinfo(supported_formats=False)
|
||||
```
|
||||
|
||||
<!--
|
||||
Please include **code** that reproduces the issue and whenever possible, an **image** that demonstrates the issue. Please upload images to GitHub, not to third-party file hosting sites. If necessary, add the image to a zip or tar archive.
|
||||
|
||||
The best reproductions are self-contained scripts with minimal dependencies. If you are using a framework such as Plone, Django, or Buildout, try to replicate the issue just using Pillow.
|
||||
-->
|
||||
|
||||
```python
|
||||
code goes here
|
||||
```
|
||||
|
|
14
.github/PULL_REQUEST_TEMPLATE.md
vendored
14
.github/PULL_REQUEST_TEMPLATE.md
vendored
|
@ -1,7 +1,7 @@
|
|||
Fixes # .
|
||||
|
||||
Changes proposed in this pull request:
|
||||
|
||||
*
|
||||
*
|
||||
*
|
||||
Fixes # .
|
||||
|
||||
Changes proposed in this pull request:
|
||||
|
||||
*
|
||||
*
|
||||
*
|
||||
|
|
10
.github/SECURITY.md
vendored
10
.github/SECURITY.md
vendored
|
@ -1,5 +1,5 @@
|
|||
# Security policy
|
||||
|
||||
To report sensitive vulnerability information, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure.
|
||||
|
||||
If your organisation/employer is a distributor of Pillow and would like advance notification of security-related bugs, please let us know your preferred contact method.
|
||||
# Security policy
|
||||
|
||||
To report sensitive vulnerability information, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure.
|
||||
|
||||
If your organisation/employer is a distributor of Pillow and would like advance notification of security-related bugs, please let us know your preferred contact method.
|
||||
|
|
30
.github/mergify.yml
vendored
30
.github/mergify.yml
vendored
|
@ -1,15 +1,15 @@
|
|||
pull_request_rules:
|
||||
- name: Automatic merge
|
||||
conditions:
|
||||
- "#approved-reviews-by>=1"
|
||||
- label=automerge
|
||||
- status-success=Lint
|
||||
- status-success=Test Successful
|
||||
- status-success=Docker Test Successful
|
||||
- status-success=Windows Test Successful
|
||||
- status-success=MinGW
|
||||
- status-success=Cygwin Test Successful
|
||||
- status-success=continuous-integration/appveyor/pr
|
||||
actions:
|
||||
merge:
|
||||
method: merge
|
||||
pull_request_rules:
|
||||
- name: Automatic merge
|
||||
conditions:
|
||||
- "#approved-reviews-by>=1"
|
||||
- label=automerge
|
||||
- status-success=Lint
|
||||
- status-success=Test Successful
|
||||
- status-success=Docker Test Successful
|
||||
- status-success=Windows Test Successful
|
||||
- status-success=MinGW
|
||||
- status-success=Cygwin Test Successful
|
||||
- status-success=continuous-integration/appveyor/pr
|
||||
actions:
|
||||
merge:
|
||||
method: merge
|
||||
|
|
36
.github/problem-matchers/gcc.json
vendored
36
.github/problem-matchers/gcc.json
vendored
|
@ -1,18 +1,18 @@
|
|||
{
|
||||
"__comment": "Based on vscode-cpptools' Extension/package.json gcc rule",
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "gcc-problem-matcher",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^\\s*(.*):(\\d+):(\\d+):\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"column": 3,
|
||||
"severity": 4,
|
||||
"message": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
{
|
||||
"__comment": "Based on vscode-cpptools' Extension/package.json gcc rule",
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "gcc-problem-matcher",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^\\s*(.*):(\\d+):(\\d+):\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"column": 3,
|
||||
"severity": 4,
|
||||
"message": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
56
.github/release-drafter.yml
vendored
56
.github/release-drafter.yml
vendored
|
@ -1,28 +1,28 @@
|
|||
name-template: "$NEXT_MINOR_VERSION"
|
||||
tag-template: "$NEXT_MINOR_VERSION"
|
||||
change-template: '- $TITLE #$NUMBER [@$AUTHOR]'
|
||||
|
||||
categories:
|
||||
- title: "Dependencies"
|
||||
label: "Dependency"
|
||||
- title: "Deprecations"
|
||||
label: "Deprecation"
|
||||
- title: "Documentation"
|
||||
label: "Documentation"
|
||||
- title: "Removals"
|
||||
label: "Removal"
|
||||
- title: "Testing"
|
||||
label: "Testing"
|
||||
- title: "Type hints"
|
||||
label: "Type hints"
|
||||
|
||||
exclude-labels:
|
||||
- "changelog: skip"
|
||||
|
||||
template: |
|
||||
|
||||
https://pillow.readthedocs.io/en/stable/releasenotes/$NEXT_MINOR_VERSION.html
|
||||
|
||||
## Changes
|
||||
|
||||
$CHANGES
|
||||
name-template: "$NEXT_MINOR_VERSION"
|
||||
tag-template: "$NEXT_MINOR_VERSION"
|
||||
change-template: '- $TITLE #$NUMBER [@$AUTHOR]'
|
||||
|
||||
categories:
|
||||
- title: "Dependencies"
|
||||
label: "Dependency"
|
||||
- title: "Deprecations"
|
||||
label: "Deprecation"
|
||||
- title: "Documentation"
|
||||
label: "Documentation"
|
||||
- title: "Removals"
|
||||
label: "Removal"
|
||||
- title: "Testing"
|
||||
label: "Testing"
|
||||
- title: "Type hints"
|
||||
label: "Type hints"
|
||||
|
||||
exclude-labels:
|
||||
- "changelog: skip"
|
||||
|
||||
template: |
|
||||
|
||||
https://pillow.readthedocs.io/en/stable/releasenotes/$NEXT_MINOR_VERSION.html
|
||||
|
||||
## Changes
|
||||
|
||||
$CHANGES
|
||||
|
|
34
.github/renovate.json
vendored
34
.github/renovate.json
vendored
|
@ -1,17 +1,17 @@
|
|||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:base"
|
||||
],
|
||||
"labels": [
|
||||
"Dependency"
|
||||
],
|
||||
"packageRules": [
|
||||
{
|
||||
"groupName": "github-actions",
|
||||
"matchManagers": ["github-actions"],
|
||||
"separateMajorMinor": "false"
|
||||
}
|
||||
],
|
||||
"schedule": ["on the 3rd day of the month"]
|
||||
}
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:base"
|
||||
],
|
||||
"labels": [
|
||||
"Dependency"
|
||||
],
|
||||
"packageRules": [
|
||||
{
|
||||
"groupName": "github-actions",
|
||||
"matchManagers": ["github-actions"],
|
||||
"separateMajorMinor": "false"
|
||||
}
|
||||
],
|
||||
"schedule": ["on the 3rd day of the month"]
|
||||
}
|
||||
|
|
120
.github/workflows/cifuzz.yml
vendored
120
.github/workflows/cifuzz.yml
vendored
|
@ -1,60 +1,60 @@
|
|||
name: CIFuzz
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
paths:
|
||||
- ".github/workflows/cifuzz.yml"
|
||||
- "**.c"
|
||||
- "**.h"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/cifuzz.yml"
|
||||
- "**.c"
|
||||
- "**.h"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
Fuzzing:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Build Fuzzers
|
||||
id: build
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'pillow'
|
||||
language: python
|
||||
dry-run: false
|
||||
- name: Run Fuzzers
|
||||
id: run
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'pillow'
|
||||
fuzz-seconds: 600
|
||||
language: python
|
||||
dry-run: false
|
||||
- name: Upload New Crash
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure() && steps.build.outcome == 'success'
|
||||
with:
|
||||
name: artifacts
|
||||
path: ./out/artifacts
|
||||
- name: Upload Legacy Crash
|
||||
uses: actions/upload-artifact@v4
|
||||
if: steps.run.outcome == 'success'
|
||||
with:
|
||||
name: crash
|
||||
path: ./out/crash*
|
||||
- name: Fail on legacy crash
|
||||
if: success()
|
||||
run: |
|
||||
[ ! -e out/crash-* ]
|
||||
echo No legacy crash detected
|
||||
name: CIFuzz
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
paths:
|
||||
- ".github/workflows/cifuzz.yml"
|
||||
- "**.c"
|
||||
- "**.h"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/cifuzz.yml"
|
||||
- "**.c"
|
||||
- "**.h"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
Fuzzing:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Build Fuzzers
|
||||
id: build
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'pillow'
|
||||
language: python
|
||||
dry-run: false
|
||||
- name: Run Fuzzers
|
||||
id: run
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'pillow'
|
||||
fuzz-seconds: 600
|
||||
language: python
|
||||
dry-run: false
|
||||
- name: Upload New Crash
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure() && steps.build.outcome == 'success'
|
||||
with:
|
||||
name: artifacts
|
||||
path: ./out/artifacts
|
||||
- name: Upload Legacy Crash
|
||||
uses: actions/upload-artifact@v4
|
||||
if: steps.run.outcome == 'success'
|
||||
with:
|
||||
name: crash
|
||||
path: ./out/crash*
|
||||
- name: Fail on legacy crash
|
||||
if: success()
|
||||
run: |
|
||||
[ ! -e out/crash-* ]
|
||||
echo No legacy crash detected
|
||||
|
|
138
.github/workflows/docs.yml
vendored
138
.github/workflows/docs.yml
vendored
|
@ -1,69 +1,69 @@
|
|||
name: Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
paths:
|
||||
- ".github/workflows/docs.yml"
|
||||
- "docs/**"
|
||||
- "src/PIL/**"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/docs.yml"
|
||||
- "docs/**"
|
||||
- "src/PIL/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
name: Docs
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.x"
|
||||
cache: pip
|
||||
cache-dependency-path: |
|
||||
".ci/*.sh"
|
||||
"pyproject.toml"
|
||||
|
||||
- name: Build system information
|
||||
run: python3 .github/workflows/system-info.py
|
||||
|
||||
- name: Cache libimagequant
|
||||
uses: actions/cache@v4
|
||||
id: cache-libimagequant
|
||||
with:
|
||||
path: ~/cache-libimagequant
|
||||
key: ${{ runner.os }}-libimagequant-${{ hashFiles('depends/install_imagequant.sh') }}
|
||||
|
||||
- name: Install Linux dependencies
|
||||
run: |
|
||||
.ci/install.sh
|
||||
env:
|
||||
GHA_PYTHON_VERSION: "3.x"
|
||||
GHA_LIBIMAGEQUANT_CACHE_HIT: ${{ steps.cache-libimagequant.outputs.cache-hit }}
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
.ci/build.sh
|
||||
|
||||
- name: Docs
|
||||
run: |
|
||||
make doccheck
|
||||
name: Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
paths:
|
||||
- ".github/workflows/docs.yml"
|
||||
- "docs/**"
|
||||
- "src/PIL/**"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/docs.yml"
|
||||
- "docs/**"
|
||||
- "src/PIL/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
name: Docs
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.x"
|
||||
cache: pip
|
||||
cache-dependency-path: |
|
||||
".ci/*.sh"
|
||||
"pyproject.toml"
|
||||
|
||||
- name: Build system information
|
||||
run: python3 .github/workflows/system-info.py
|
||||
|
||||
- name: Cache libimagequant
|
||||
uses: actions/cache@v4
|
||||
id: cache-libimagequant
|
||||
with:
|
||||
path: ~/cache-libimagequant
|
||||
key: ${{ runner.os }}-libimagequant-${{ hashFiles('depends/install_imagequant.sh') }}
|
||||
|
||||
- name: Install Linux dependencies
|
||||
run: |
|
||||
.ci/install.sh
|
||||
env:
|
||||
GHA_PYTHON_VERSION: "3.x"
|
||||
GHA_LIBIMAGEQUANT_CACHE_HIT: ${{ steps.cache-libimagequant.outputs.cache-hit }}
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
.ci/build.sh
|
||||
|
||||
- name: Docs
|
||||
run: |
|
||||
make doccheck
|
||||
|
|
108
.github/workflows/lint.yml
vendored
108
.github/workflows/lint.yml
vendored
|
@ -1,54 +1,54 @@
|
|||
name: Lint
|
||||
|
||||
on: [push, pull_request, workflow_dispatch]
|
||||
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
name: Lint
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: pre-commit cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/pre-commit
|
||||
key: lint-pre-commit-${{ hashFiles('**/.pre-commit-config.yaml') }}
|
||||
restore-keys: |
|
||||
lint-pre-commit-
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.x"
|
||||
cache: pip
|
||||
cache-dependency-path: "setup.py"
|
||||
|
||||
- name: Build system information
|
||||
run: python3 .github/workflows/system-info.py
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python3 -m pip install -U pip
|
||||
python3 -m pip install -U tox
|
||||
|
||||
- name: Lint
|
||||
run: tox -e lint
|
||||
env:
|
||||
PRE_COMMIT_COLOR: always
|
||||
|
||||
- name: Mypy
|
||||
run: tox -e mypy
|
||||
name: Lint
|
||||
|
||||
on: [push, pull_request, workflow_dispatch]
|
||||
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
name: Lint
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: pre-commit cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/pre-commit
|
||||
key: lint-pre-commit-${{ hashFiles('**/.pre-commit-config.yaml') }}
|
||||
restore-keys: |
|
||||
lint-pre-commit-
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.x"
|
||||
cache: pip
|
||||
cache-dependency-path: "setup.py"
|
||||
|
||||
- name: Build system information
|
||||
run: python3 .github/workflows/system-info.py
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python3 -m pip install -U pip
|
||||
python3 -m pip install -U tox
|
||||
|
||||
- name: Lint
|
||||
run: tox -e lint
|
||||
env:
|
||||
PRE_COMMIT_COLOR: always
|
||||
|
||||
- name: Mypy
|
||||
run: tox -e mypy
|
||||
|
|
72
.github/workflows/macos-install.sh
vendored
72
.github/workflows/macos-install.sh
vendored
|
@ -1,36 +1,36 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
brew install \
|
||||
freetype \
|
||||
ghostscript \
|
||||
libimagequant \
|
||||
libjpeg \
|
||||
libtiff \
|
||||
little-cms2 \
|
||||
openjpeg \
|
||||
webp
|
||||
if [[ "$ImageOS" == "macos13" ]]; then
|
||||
brew install --ignore-dependencies libraqm
|
||||
else
|
||||
brew install libraqm
|
||||
fi
|
||||
export PKG_CONFIG_PATH="/usr/local/opt/openblas/lib/pkgconfig"
|
||||
|
||||
# TODO Update condition when cffi supports 3.13
|
||||
if ! [[ "$GHA_PYTHON_VERSION" == "3.13" ]]; then PYTHONOPTIMIZE=0 python3 -m pip install cffi ; fi
|
||||
|
||||
python3 -m pip install coverage
|
||||
python3 -m pip install defusedxml
|
||||
python3 -m pip install olefile
|
||||
python3 -m pip install -U pytest
|
||||
python3 -m pip install -U pytest-cov
|
||||
python3 -m pip install -U pytest-timeout
|
||||
python3 -m pip install pyroma
|
||||
|
||||
# TODO Update condition when NumPy supports 3.13
|
||||
if ! [[ "$GHA_PYTHON_VERSION" == "3.13" ]]; then python3 -m pip install numpy ; fi
|
||||
|
||||
# extra test images
|
||||
pushd depends && ./install_extra_test_images.sh && popd
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
brew install \
|
||||
freetype \
|
||||
ghostscript \
|
||||
libimagequant \
|
||||
libjpeg \
|
||||
libtiff \
|
||||
little-cms2 \
|
||||
openjpeg \
|
||||
webp
|
||||
if [[ "$ImageOS" == "macos13" ]]; then
|
||||
brew install --ignore-dependencies libraqm
|
||||
else
|
||||
brew install libraqm
|
||||
fi
|
||||
export PKG_CONFIG_PATH="/usr/local/opt/openblas/lib/pkgconfig"
|
||||
|
||||
# TODO Update condition when cffi supports 3.13
|
||||
if ! [[ "$GHA_PYTHON_VERSION" == "3.13" ]]; then PYTHONOPTIMIZE=0 python3 -m pip install cffi ; fi
|
||||
|
||||
python3 -m pip install coverage
|
||||
python3 -m pip install defusedxml
|
||||
python3 -m pip install olefile
|
||||
python3 -m pip install -U pytest
|
||||
python3 -m pip install -U pytest-cov
|
||||
python3 -m pip install -U pytest-timeout
|
||||
python3 -m pip install pyroma
|
||||
|
||||
# TODO Update condition when NumPy supports 3.13
|
||||
if ! [[ "$GHA_PYTHON_VERSION" == "3.13" ]]; then python3 -m pip install numpy ; fi
|
||||
|
||||
# extra test images
|
||||
pushd depends && ./install_extra_test_images.sh && popd
|
||||
|
|
56
.github/workflows/release-drafter.yml
vendored
56
.github/workflows/release-drafter.yml
vendored
|
@ -1,28 +1,28 @@
|
|||
name: Release drafter
|
||||
|
||||
on:
|
||||
push:
|
||||
# branches to consider in the event; optional, defaults to all
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
update_release_draft:
|
||||
permissions:
|
||||
contents: write # for release-drafter/release-drafter to create a github release
|
||||
pull-requests: write # for release-drafter/release-drafter to add label to PR
|
||||
if: github.repository == 'python-pillow/Pillow'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Drafts your next release notes as pull requests are merged into "main"
|
||||
- uses: release-drafter/release-drafter@v6
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: Release drafter
|
||||
|
||||
on:
|
||||
push:
|
||||
# branches to consider in the event; optional, defaults to all
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
update_release_draft:
|
||||
permissions:
|
||||
contents: write # for release-drafter/release-drafter to create a github release
|
||||
pull-requests: write # for release-drafter/release-drafter to add label to PR
|
||||
if: github.repository == 'python-pillow/Pillow'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Drafts your next release notes as pull requests are merged into "main"
|
||||
- uses: release-drafter/release-drafter@v6
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
|
62
.github/workflows/stale.yml
vendored
62
.github/workflows/stale.yml
vendored
|
@ -1,31 +1,31 @@
|
|||
name: Close stale issues
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "10 0 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
if: github.repository_owner == 'python-pillow'
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: "Check issues"
|
||||
uses: actions/stale@v9
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
only-labels: "Awaiting OP Action"
|
||||
close-issue-message: "Closing this issue as no feedback has been received."
|
||||
days-before-stale: 7
|
||||
days-before-issue-close: 0
|
||||
days-before-pr-close: -1
|
||||
labels-to-remove-when-unstale: "Awaiting OP Action"
|
||||
name: Close stale issues
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "10 0 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
if: github.repository_owner == 'python-pillow'
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: "Check issues"
|
||||
uses: actions/stale@v9
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
only-labels: "Awaiting OP Action"
|
||||
close-issue-message: "Closing this issue as no feedback has been received."
|
||||
days-before-stale: 7
|
||||
days-before-issue-close: 0
|
||||
days-before-pr-close: -1
|
||||
labels-to-remove-when-unstale: "Awaiting OP Action"
|
||||
|
|
56
.github/workflows/system-info.py
vendored
56
.github/workflows/system-info.py
vendored
|
@ -1,28 +1,28 @@
|
|||
"""
|
||||
Print out some handy system info like Travis CI does.
|
||||
|
||||
This sort of info is missing from GitHub Actions.
|
||||
|
||||
Requested here:
|
||||
https://github.com/actions/virtual-environments/issues/79
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
|
||||
print("Build system information")
|
||||
print()
|
||||
|
||||
print("sys.version\t\t", sys.version.split("\n"))
|
||||
print("os.name\t\t\t", os.name)
|
||||
print("sys.platform\t\t", sys.platform)
|
||||
print("platform.system()\t", platform.system())
|
||||
print("platform.machine()\t", platform.machine())
|
||||
print("platform.platform()\t", platform.platform())
|
||||
print("platform.version()\t", platform.version())
|
||||
print("platform.uname()\t", platform.uname())
|
||||
if sys.platform == "darwin":
|
||||
print("platform.mac_ver()\t", platform.mac_ver())
|
||||
"""
|
||||
Print out some handy system info like Travis CI does.
|
||||
|
||||
This sort of info is missing from GitHub Actions.
|
||||
|
||||
Requested here:
|
||||
https://github.com/actions/virtual-environments/issues/79
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
|
||||
print("Build system information")
|
||||
print()
|
||||
|
||||
print("sys.version\t\t", sys.version.split("\n"))
|
||||
print("os.name\t\t\t", os.name)
|
||||
print("sys.platform\t\t", sys.platform)
|
||||
print("platform.system()\t", platform.system())
|
||||
print("platform.machine()\t", platform.machine())
|
||||
print("platform.platform()\t", platform.platform())
|
||||
print("platform.version()\t", platform.version())
|
||||
print("platform.uname()\t", platform.uname())
|
||||
if sys.platform == "darwin":
|
||||
print("platform.mac_ver()\t", platform.mac_ver())
|
||||
|
|
302
.github/workflows/test-cygwin.yml
vendored
302
.github/workflows/test-cygwin.yml
vendored
|
@ -1,151 +1,151 @@
|
|||
name: Test Cygwin
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
COVERAGE_CORE: sysmon
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-minor-version: [8, 9]
|
||||
|
||||
timeout-minutes: 40
|
||||
|
||||
name: Python 3.${{ matrix.python-minor-version }}
|
||||
|
||||
steps:
|
||||
- name: Fix line endings
|
||||
run: |
|
||||
git config --global core.autocrlf input
|
||||
|
||||
- name: Checkout Pillow
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Cygwin
|
||||
uses: cygwin/cygwin-install-action@v4
|
||||
with:
|
||||
packages: >
|
||||
gcc-g++
|
||||
ghostscript
|
||||
git
|
||||
ImageMagick
|
||||
jpeg
|
||||
libfreetype-devel
|
||||
libimagequant-devel
|
||||
libjpeg-devel
|
||||
liblapack-devel
|
||||
liblcms2-devel
|
||||
libopenjp2-devel
|
||||
libraqm-devel
|
||||
libtiff-devel
|
||||
libwebp-devel
|
||||
libxcb-devel
|
||||
libxcb-xinerama0
|
||||
make
|
||||
netpbm
|
||||
perl
|
||||
python3${{ matrix.python-minor-version }}-cffi
|
||||
python3${{ matrix.python-minor-version }}-cython
|
||||
python3${{ matrix.python-minor-version }}-devel
|
||||
python3${{ matrix.python-minor-version }}-numpy
|
||||
python3${{ matrix.python-minor-version }}-sip
|
||||
python3${{ matrix.python-minor-version }}-tkinter
|
||||
wget
|
||||
xorg-server-extra
|
||||
zlib-devel
|
||||
|
||||
- name: Add Lapack to PATH
|
||||
uses: egor-tensin/cleanup-path@v4
|
||||
with:
|
||||
dirs: 'C:\cygwin\bin;C:\cygwin\lib\lapack'
|
||||
|
||||
- name: Select Python version
|
||||
run: |
|
||||
ln -sf c:/cygwin/bin/python3.${{ matrix.python-minor-version }} c:/cygwin/bin/python3
|
||||
|
||||
- name: pip cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: 'C:\cygwin\home\runneradmin\.cache\pip'
|
||||
key: ${{ runner.os }}-cygwin-pip3.${{ matrix.python-minor-version }}-${{ hashFiles('.ci/install.sh') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cygwin-pip3.${{ matrix.python-minor-version }}-
|
||||
|
||||
- name: Build system information
|
||||
run: |
|
||||
dash.exe -c "python3 .github/workflows/system-info.py"
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
bash.exe .ci/install.sh
|
||||
|
||||
- name: Build
|
||||
shell: bash.exe -eo pipefail -o igncr "{0}"
|
||||
run: |
|
||||
.ci/build.sh
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
bash.exe xvfb-run -s '-screen 0 1024x768x24' .ci/test.sh
|
||||
|
||||
- name: Prepare to upload errors
|
||||
if: failure()
|
||||
run: |
|
||||
dash.exe -c "mkdir -p Tests/errors"
|
||||
|
||||
- name: Upload errors
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: errors
|
||||
path: Tests/errors
|
||||
|
||||
- name: After success
|
||||
run: |
|
||||
bash.exe .ci/after_success.sh
|
||||
|
||||
- name: Upload coverage
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
file: ./coverage.xml
|
||||
flags: GHA_Cygwin
|
||||
name: Cygwin Python 3.${{ matrix.python-minor-version }}
|
||||
token: ${{ secrets.CODECOV_ORG_TOKEN }}
|
||||
|
||||
success:
|
||||
permissions:
|
||||
contents: none
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
name: Cygwin Test Successful
|
||||
steps:
|
||||
- name: Success
|
||||
run: echo Cygwin Test Successful
|
||||
name: Test Cygwin
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
COVERAGE_CORE: sysmon
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-minor-version: [8, 9]
|
||||
|
||||
timeout-minutes: 40
|
||||
|
||||
name: Python 3.${{ matrix.python-minor-version }}
|
||||
|
||||
steps:
|
||||
- name: Fix line endings
|
||||
run: |
|
||||
git config --global core.autocrlf input
|
||||
|
||||
- name: Checkout Pillow
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Cygwin
|
||||
uses: cygwin/cygwin-install-action@v4
|
||||
with:
|
||||
packages: >
|
||||
gcc-g++
|
||||
ghostscript
|
||||
git
|
||||
ImageMagick
|
||||
jpeg
|
||||
libfreetype-devel
|
||||
libimagequant-devel
|
||||
libjpeg-devel
|
||||
liblapack-devel
|
||||
liblcms2-devel
|
||||
libopenjp2-devel
|
||||
libraqm-devel
|
||||
libtiff-devel
|
||||
libwebp-devel
|
||||
libxcb-devel
|
||||
libxcb-xinerama0
|
||||
make
|
||||
netpbm
|
||||
perl
|
||||
python3${{ matrix.python-minor-version }}-cffi
|
||||
python3${{ matrix.python-minor-version }}-cython
|
||||
python3${{ matrix.python-minor-version }}-devel
|
||||
python3${{ matrix.python-minor-version }}-numpy
|
||||
python3${{ matrix.python-minor-version }}-sip
|
||||
python3${{ matrix.python-minor-version }}-tkinter
|
||||
wget
|
||||
xorg-server-extra
|
||||
zlib-devel
|
||||
|
||||
- name: Add Lapack to PATH
|
||||
uses: egor-tensin/cleanup-path@v4
|
||||
with:
|
||||
dirs: 'C:\cygwin\bin;C:\cygwin\lib\lapack'
|
||||
|
||||
- name: Select Python version
|
||||
run: |
|
||||
ln -sf c:/cygwin/bin/python3.${{ matrix.python-minor-version }} c:/cygwin/bin/python3
|
||||
|
||||
- name: pip cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: 'C:\cygwin\home\runneradmin\.cache\pip'
|
||||
key: ${{ runner.os }}-cygwin-pip3.${{ matrix.python-minor-version }}-${{ hashFiles('.ci/install.sh') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cygwin-pip3.${{ matrix.python-minor-version }}-
|
||||
|
||||
- name: Build system information
|
||||
run: |
|
||||
dash.exe -c "python3 .github/workflows/system-info.py"
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
bash.exe .ci/install.sh
|
||||
|
||||
- name: Build
|
||||
shell: bash.exe -eo pipefail -o igncr "{0}"
|
||||
run: |
|
||||
.ci/build.sh
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
bash.exe xvfb-run -s '-screen 0 1024x768x24' .ci/test.sh
|
||||
|
||||
- name: Prepare to upload errors
|
||||
if: failure()
|
||||
run: |
|
||||
dash.exe -c "mkdir -p Tests/errors"
|
||||
|
||||
- name: Upload errors
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: errors
|
||||
path: Tests/errors
|
||||
|
||||
- name: After success
|
||||
run: |
|
||||
bash.exe .ci/after_success.sh
|
||||
|
||||
- name: Upload coverage
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
file: ./coverage.xml
|
||||
flags: GHA_Cygwin
|
||||
name: Cygwin Python 3.${{ matrix.python-minor-version }}
|
||||
token: ${{ secrets.CODECOV_ORG_TOKEN }}
|
||||
|
||||
success:
|
||||
permissions:
|
||||
contents: none
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
name: Cygwin Test Successful
|
||||
steps:
|
||||
- name: Success
|
||||
run: echo Cygwin Test Successful
|
||||
|
|
236
.github/workflows/test-docker.yml
vendored
236
.github/workflows/test-docker.yml
vendored
|
@ -1,118 +1,118 @@
|
|||
name: Test Docker
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
docker: [
|
||||
# Run slower jobs first to give them a headstart and reduce waiting time
|
||||
ubuntu-22.04-jammy-arm64v8,
|
||||
ubuntu-24.04-noble-ppc64le,
|
||||
ubuntu-24.04-noble-s390x,
|
||||
# Then run the remainder
|
||||
alpine,
|
||||
amazon-2-amd64,
|
||||
amazon-2023-amd64,
|
||||
arch,
|
||||
centos-stream-9-amd64,
|
||||
debian-11-bullseye-amd64,
|
||||
debian-12-bookworm-x86,
|
||||
debian-12-bookworm-amd64,
|
||||
fedora-39-amd64,
|
||||
fedora-40-amd64,
|
||||
gentoo,
|
||||
ubuntu-20.04-focal-amd64,
|
||||
ubuntu-22.04-jammy-amd64,
|
||||
ubuntu-24.04-noble-amd64,
|
||||
]
|
||||
dockerTag: [main]
|
||||
include:
|
||||
- docker: "ubuntu-22.04-jammy-arm64v8"
|
||||
qemu-arch: "aarch64"
|
||||
- docker: "ubuntu-24.04-noble-ppc64le"
|
||||
qemu-arch: "ppc64le"
|
||||
- docker: "ubuntu-24.04-noble-s390x"
|
||||
qemu-arch: "s390x"
|
||||
|
||||
name: ${{ matrix.docker }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build system information
|
||||
run: python3 .github/workflows/system-info.py
|
||||
|
||||
- name: Set up QEMU
|
||||
if: "matrix.qemu-arch"
|
||||
run: |
|
||||
docker run --rm --privileged aptman/qus -s -- -p ${{ matrix.qemu-arch }}
|
||||
|
||||
- name: Docker pull
|
||||
run: |
|
||||
docker pull pythonpillow/${{ matrix.docker }}:${{ matrix.dockerTag }}
|
||||
|
||||
- name: Docker build
|
||||
run: |
|
||||
# The Pillow user in the docker container is UID 1001
|
||||
sudo chown -R 1001 $GITHUB_WORKSPACE
|
||||
docker run --name pillow_container -v $GITHUB_WORKSPACE:/Pillow pythonpillow/${{ matrix.docker }}:${{ matrix.dockerTag }}
|
||||
sudo chown -R runner $GITHUB_WORKSPACE
|
||||
|
||||
- name: After success
|
||||
run: |
|
||||
PATH="$PATH:~/.local/bin"
|
||||
docker start pillow_container
|
||||
pil_path=`docker exec pillow_container /vpy3/bin/python -c 'import os, PIL;print(os.path.realpath(os.path.dirname(PIL.__file__)))'`
|
||||
docker stop pillow_container
|
||||
sudo mkdir -p $pil_path
|
||||
sudo cp src/PIL/*.py $pil_path
|
||||
.ci/after_success.sh
|
||||
env:
|
||||
MATRIX_DOCKER: ${{ matrix.docker }}
|
||||
|
||||
- name: Upload coverage
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
flags: GHA_Docker
|
||||
name: ${{ matrix.docker }}
|
||||
gcov: true
|
||||
token: ${{ secrets.CODECOV_ORG_TOKEN }}
|
||||
|
||||
success:
|
||||
permissions:
|
||||
contents: none
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
name: Docker Test Successful
|
||||
steps:
|
||||
- name: Success
|
||||
run: echo Docker Test Successful
|
||||
name: Test Docker
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
docker: [
|
||||
# Run slower jobs first to give them a headstart and reduce waiting time
|
||||
ubuntu-22.04-jammy-arm64v8,
|
||||
ubuntu-24.04-noble-ppc64le,
|
||||
ubuntu-24.04-noble-s390x,
|
||||
# Then run the remainder
|
||||
alpine,
|
||||
amazon-2-amd64,
|
||||
amazon-2023-amd64,
|
||||
arch,
|
||||
centos-stream-9-amd64,
|
||||
debian-11-bullseye-amd64,
|
||||
debian-12-bookworm-x86,
|
||||
debian-12-bookworm-amd64,
|
||||
fedora-39-amd64,
|
||||
fedora-40-amd64,
|
||||
gentoo,
|
||||
ubuntu-20.04-focal-amd64,
|
||||
ubuntu-22.04-jammy-amd64,
|
||||
ubuntu-24.04-noble-amd64,
|
||||
]
|
||||
dockerTag: [main]
|
||||
include:
|
||||
- docker: "ubuntu-22.04-jammy-arm64v8"
|
||||
qemu-arch: "aarch64"
|
||||
- docker: "ubuntu-24.04-noble-ppc64le"
|
||||
qemu-arch: "ppc64le"
|
||||
- docker: "ubuntu-24.04-noble-s390x"
|
||||
qemu-arch: "s390x"
|
||||
|
||||
name: ${{ matrix.docker }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build system information
|
||||
run: python3 .github/workflows/system-info.py
|
||||
|
||||
- name: Set up QEMU
|
||||
if: "matrix.qemu-arch"
|
||||
run: |
|
||||
docker run --rm --privileged aptman/qus -s -- -p ${{ matrix.qemu-arch }}
|
||||
|
||||
- name: Docker pull
|
||||
run: |
|
||||
docker pull pythonpillow/${{ matrix.docker }}:${{ matrix.dockerTag }}
|
||||
|
||||
- name: Docker build
|
||||
run: |
|
||||
# The Pillow user in the docker container is UID 1001
|
||||
sudo chown -R 1001 $GITHUB_WORKSPACE
|
||||
docker run --name pillow_container -v $GITHUB_WORKSPACE:/Pillow pythonpillow/${{ matrix.docker }}:${{ matrix.dockerTag }}
|
||||
sudo chown -R runner $GITHUB_WORKSPACE
|
||||
|
||||
- name: After success
|
||||
run: |
|
||||
PATH="$PATH:~/.local/bin"
|
||||
docker start pillow_container
|
||||
pil_path=`docker exec pillow_container /vpy3/bin/python -c 'import os, PIL;print(os.path.realpath(os.path.dirname(PIL.__file__)))'`
|
||||
docker stop pillow_container
|
||||
sudo mkdir -p $pil_path
|
||||
sudo cp src/PIL/*.py $pil_path
|
||||
.ci/after_success.sh
|
||||
env:
|
||||
MATRIX_DOCKER: ${{ matrix.docker }}
|
||||
|
||||
- name: Upload coverage
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
flags: GHA_Docker
|
||||
name: ${{ matrix.docker }}
|
||||
gcov: true
|
||||
token: ${{ secrets.CODECOV_ORG_TOKEN }}
|
||||
|
||||
success:
|
||||
permissions:
|
||||
contents: none
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
name: Docker Test Successful
|
||||
steps:
|
||||
- name: Success
|
||||
run: echo Docker Test Successful
|
||||
|
|
186
.github/workflows/test-mingw.yml
vendored
186
.github/workflows/test-mingw.yml
vendored
|
@ -1,93 +1,93 @@
|
|||
name: Test MinGW
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
COVERAGE_CORE: sysmon
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash.exe --login -eo pipefail "{0}"
|
||||
env:
|
||||
MSYSTEM: MINGW64
|
||||
CHERE_INVOKING: 1
|
||||
|
||||
timeout-minutes: 30
|
||||
name: "MinGW"
|
||||
|
||||
steps:
|
||||
- name: Checkout Pillow
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up shell
|
||||
run: echo "C:\msys64\usr\bin\" >> $env:GITHUB_PATH
|
||||
shell: pwsh
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pacman -S --noconfirm \
|
||||
mingw-w64-x86_64-freetype \
|
||||
mingw-w64-x86_64-gcc \
|
||||
mingw-w64-x86_64-ghostscript \
|
||||
mingw-w64-x86_64-lcms2 \
|
||||
mingw-w64-x86_64-libimagequant \
|
||||
mingw-w64-x86_64-libjpeg-turbo \
|
||||
mingw-w64-x86_64-libraqm \
|
||||
mingw-w64-x86_64-libtiff \
|
||||
mingw-w64-x86_64-libwebp \
|
||||
mingw-w64-x86_64-openjpeg2 \
|
||||
mingw-w64-x86_64-python3-cffi \
|
||||
mingw-w64-x86_64-python3-numpy \
|
||||
mingw-w64-x86_64-python3-olefile \
|
||||
mingw-w64-x86_64-python3-setuptools \
|
||||
mingw-w64-x86_64-python-pyqt6
|
||||
|
||||
python3 -m ensurepip
|
||||
python3 -m pip install pyroma pytest pytest-cov pytest-timeout
|
||||
|
||||
pushd depends && ./install_extra_test_images.sh && popd
|
||||
|
||||
- name: Build Pillow
|
||||
run: SETUPTOOLS_USE_DISTUTILS="stdlib" CFLAGS="-coverage" python3 -m pip install .
|
||||
|
||||
- name: Test Pillow
|
||||
run: |
|
||||
python3 selftest.py --installed
|
||||
python3 -c "from PIL import Image"
|
||||
python3 -m pytest -vx --cov PIL --cov Tests --cov-report term --cov-report xml Tests
|
||||
|
||||
- name: Upload coverage
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
file: ./coverage.xml
|
||||
flags: GHA_Windows
|
||||
name: "MSYS2 MinGW"
|
||||
token: ${{ secrets.CODECOV_ORG_TOKEN }}
|
||||
name: Test MinGW
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
COVERAGE_CORE: sysmon
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash.exe --login -eo pipefail "{0}"
|
||||
env:
|
||||
MSYSTEM: MINGW64
|
||||
CHERE_INVOKING: 1
|
||||
|
||||
timeout-minutes: 30
|
||||
name: "MinGW"
|
||||
|
||||
steps:
|
||||
- name: Checkout Pillow
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up shell
|
||||
run: echo "C:\msys64\usr\bin\" >> $env:GITHUB_PATH
|
||||
shell: pwsh
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pacman -S --noconfirm \
|
||||
mingw-w64-x86_64-freetype \
|
||||
mingw-w64-x86_64-gcc \
|
||||
mingw-w64-x86_64-ghostscript \
|
||||
mingw-w64-x86_64-lcms2 \
|
||||
mingw-w64-x86_64-libimagequant \
|
||||
mingw-w64-x86_64-libjpeg-turbo \
|
||||
mingw-w64-x86_64-libraqm \
|
||||
mingw-w64-x86_64-libtiff \
|
||||
mingw-w64-x86_64-libwebp \
|
||||
mingw-w64-x86_64-openjpeg2 \
|
||||
mingw-w64-x86_64-python3-cffi \
|
||||
mingw-w64-x86_64-python3-numpy \
|
||||
mingw-w64-x86_64-python3-olefile \
|
||||
mingw-w64-x86_64-python3-setuptools \
|
||||
mingw-w64-x86_64-python-pyqt6
|
||||
|
||||
python3 -m ensurepip
|
||||
python3 -m pip install pyroma pytest pytest-cov pytest-timeout
|
||||
|
||||
pushd depends && ./install_extra_test_images.sh && popd
|
||||
|
||||
- name: Build Pillow
|
||||
run: SETUPTOOLS_USE_DISTUTILS="stdlib" CFLAGS="-coverage" python3 -m pip install .
|
||||
|
||||
- name: Test Pillow
|
||||
run: |
|
||||
python3 selftest.py --installed
|
||||
python3 -c "from PIL import Image"
|
||||
python3 -m pytest -vx --cov PIL --cov Tests --cov-report term --cov-report xml Tests
|
||||
|
||||
- name: Upload coverage
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
file: ./coverage.xml
|
||||
flags: GHA_Windows
|
||||
name: "MSYS2 MinGW"
|
||||
token: ${{ secrets.CODECOV_ORG_TOKEN }}
|
||||
|
|
112
.github/workflows/test-valgrind.yml
vendored
112
.github/workflows/test-valgrind.yml
vendored
|
@ -1,56 +1,56 @@
|
|||
name: Test Valgrind
|
||||
|
||||
# like the Docker tests, but running valgrind only on *.c/*.h changes.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
paths:
|
||||
- ".github/workflows/test-valgrind.yml"
|
||||
- "**.c"
|
||||
- "**.h"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/test-valgrind.yml"
|
||||
- "**.c"
|
||||
- "**.h"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
docker: [
|
||||
ubuntu-22.04-jammy-amd64-valgrind,
|
||||
]
|
||||
dockerTag: [main]
|
||||
|
||||
name: ${{ matrix.docker }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build system information
|
||||
run: python3 .github/workflows/system-info.py
|
||||
|
||||
- name: Docker pull
|
||||
run: |
|
||||
docker pull pythonpillow/${{ matrix.docker }}:${{ matrix.dockerTag }}
|
||||
|
||||
- name: Build and Run Valgrind
|
||||
run: |
|
||||
# The Pillow user in the docker container is UID 1001
|
||||
sudo chown -R 1001 $GITHUB_WORKSPACE
|
||||
docker run --name pillow_container -e "PILLOW_VALGRIND_TEST=true" -v $GITHUB_WORKSPACE:/Pillow pythonpillow/${{ matrix.docker }}:${{ matrix.dockerTag }}
|
||||
sudo chown -R runner $GITHUB_WORKSPACE
|
||||
name: Test Valgrind
|
||||
|
||||
# like the Docker tests, but running valgrind only on *.c/*.h changes.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
paths:
|
||||
- ".github/workflows/test-valgrind.yml"
|
||||
- "**.c"
|
||||
- "**.h"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/test-valgrind.yml"
|
||||
- "**.c"
|
||||
- "**.h"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
docker: [
|
||||
ubuntu-22.04-jammy-amd64-valgrind,
|
||||
]
|
||||
dockerTag: [main]
|
||||
|
||||
name: ${{ matrix.docker }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build system information
|
||||
run: python3 .github/workflows/system-info.py
|
||||
|
||||
- name: Docker pull
|
||||
run: |
|
||||
docker pull pythonpillow/${{ matrix.docker }}:${{ matrix.dockerTag }}
|
||||
|
||||
- name: Build and Run Valgrind
|
||||
run: |
|
||||
# The Pillow user in the docker container is UID 1001
|
||||
sudo chown -R 1001 $GITHUB_WORKSPACE
|
||||
docker run --name pillow_container -e "PILLOW_VALGRIND_TEST=true" -v $GITHUB_WORKSPACE:/Pillow pythonpillow/${{ matrix.docker }}:${{ matrix.dockerTag }}
|
||||
sudo chown -R runner $GITHUB_WORKSPACE
|
||||
|
|
462
.github/workflows/test-windows.yml
vendored
462
.github/workflows/test-windows.yml
vendored
|
@ -1,231 +1,231 @@
|
|||
name: Test Windows
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
COVERAGE_CORE: sysmon
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: ["pypy3.10", "pypy3.9", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
|
||||
|
||||
timeout-minutes: 30
|
||||
|
||||
name: Python ${{ matrix.python-version }}
|
||||
|
||||
steps:
|
||||
- name: Checkout Pillow
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Checkout cached dependencies
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: python-pillow/pillow-depends
|
||||
path: winbuild\depends
|
||||
|
||||
- name: Checkout extra test images
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: python-pillow/test-images
|
||||
path: Tests\test-images
|
||||
|
||||
# sets env: pythonLocation
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
allow-prereleases: true
|
||||
cache: pip
|
||||
cache-dependency-path: ".github/workflows/test-windows.yml"
|
||||
|
||||
- name: Print build system information
|
||||
run: python3 .github/workflows/system-info.py
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: >
|
||||
python3 -m pip install
|
||||
coverage>=7.4.2
|
||||
defusedxml
|
||||
olefile
|
||||
pyroma
|
||||
pytest
|
||||
pytest-cov
|
||||
pytest-timeout
|
||||
|
||||
- name: Install dependencies
|
||||
id: install
|
||||
run: |
|
||||
choco install nasm --no-progress
|
||||
echo "C:\Program Files\NASM" >> $env:GITHUB_PATH
|
||||
|
||||
choco install ghostscript --version=10.3.1 --no-progress
|
||||
echo "C:\Program Files\gs\gs10.00.0\bin" >> $env:GITHUB_PATH
|
||||
|
||||
# Install extra test images
|
||||
xcopy /S /Y Tests\test-images\* Tests\images
|
||||
|
||||
# make cache key depend on VS version
|
||||
& "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" `
|
||||
| find """catalog_buildVersion""" `
|
||||
| ForEach-Object { $a = $_.split(" ")[1]; echo "vs=$a" >> $env:GITHUB_OUTPUT }
|
||||
shell: pwsh
|
||||
|
||||
- name: Cache build
|
||||
id: build-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: winbuild\build
|
||||
key:
|
||||
${{ hashFiles('winbuild\build_prepare.py') }}-${{ hashFiles('.github\workflows\test-windows.yml') }}-${{ env.pythonLocation }}-${{ steps.install.outputs.vs }}
|
||||
|
||||
- name: Prepare build
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
& python.exe winbuild\build_prepare.py -v
|
||||
shell: pwsh
|
||||
|
||||
- name: Build dependencies / libjpeg-turbo
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_libjpeg.cmd"
|
||||
|
||||
- name: Build dependencies / zlib
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_zlib.cmd"
|
||||
|
||||
- name: Build dependencies / xz
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_xz.cmd"
|
||||
|
||||
- name: Build dependencies / WebP
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_libwebp.cmd"
|
||||
|
||||
- name: Build dependencies / LibTiff
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_libtiff.cmd"
|
||||
|
||||
# for FreeType CBDT/SBIX font support
|
||||
- name: Build dependencies / libpng
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_libpng.cmd"
|
||||
|
||||
# for FreeType WOFF2 font support
|
||||
- name: Build dependencies / brotli
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_brotli.cmd"
|
||||
|
||||
- name: Build dependencies / FreeType
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_freetype.cmd"
|
||||
|
||||
- name: Build dependencies / LCMS2
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_lcms2.cmd"
|
||||
|
||||
- name: Build dependencies / OpenJPEG
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_openjpeg.cmd"
|
||||
|
||||
# GPL licensed
|
||||
- name: Build dependencies / libimagequant
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_libimagequant.cmd"
|
||||
|
||||
# Raqm dependencies
|
||||
- name: Build dependencies / HarfBuzz
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_harfbuzz.cmd"
|
||||
|
||||
# Raqm dependencies
|
||||
- name: Build dependencies / FriBidi
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_fribidi.cmd"
|
||||
|
||||
# trim ~150MB for each job
|
||||
- name: Optimize build cache
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: rmdir /S /Q winbuild\build\src
|
||||
shell: cmd
|
||||
|
||||
- name: Build Pillow
|
||||
run: |
|
||||
$FLAGS="-C raqm=vendor -C fribidi=vendor"
|
||||
cmd /c "winbuild\build\build_env.cmd && $env:pythonLocation\python.exe -m pip install -v $FLAGS ."
|
||||
& $env:pythonLocation\python.exe selftest.py --installed
|
||||
shell: pwsh
|
||||
|
||||
# skip PyPy for speed
|
||||
- name: Enable heap verification
|
||||
if: "!contains(matrix.python-version, 'pypy')"
|
||||
run: |
|
||||
& reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\python.exe" /v "GlobalFlag" /t REG_SZ /d "0x02000000" /f
|
||||
|
||||
- name: Test Pillow
|
||||
run: |
|
||||
path %GITHUB_WORKSPACE%\\winbuild\\build\\bin;%PATH%
|
||||
python.exe -m pytest -vx -W always --cov PIL --cov Tests --cov-report term --cov-report xml Tests
|
||||
shell: cmd
|
||||
|
||||
- name: Prepare to upload errors
|
||||
if: failure()
|
||||
run: |
|
||||
mkdir -p Tests/errors
|
||||
shell: bash
|
||||
|
||||
- name: Upload errors
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: errors
|
||||
path: Tests/errors
|
||||
|
||||
- name: After success
|
||||
run: |
|
||||
.ci/after_success.sh
|
||||
shell: pwsh
|
||||
|
||||
- name: Upload coverage
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
file: ./coverage.xml
|
||||
flags: GHA_Windows
|
||||
name: ${{ runner.os }} Python ${{ matrix.python-version }}
|
||||
token: ${{ secrets.CODECOV_ORG_TOKEN }}
|
||||
|
||||
success:
|
||||
permissions:
|
||||
contents: none
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
name: Windows Test Successful
|
||||
steps:
|
||||
- name: Success
|
||||
run: echo Windows Test Successful
|
||||
name: Test Windows
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
COVERAGE_CORE: sysmon
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: ["pypy3.10", "pypy3.9", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
|
||||
|
||||
timeout-minutes: 30
|
||||
|
||||
name: Python ${{ matrix.python-version }}
|
||||
|
||||
steps:
|
||||
- name: Checkout Pillow
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Checkout cached dependencies
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: python-pillow/pillow-depends
|
||||
path: winbuild\depends
|
||||
|
||||
- name: Checkout extra test images
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: python-pillow/test-images
|
||||
path: Tests\test-images
|
||||
|
||||
# sets env: pythonLocation
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
allow-prereleases: true
|
||||
cache: pip
|
||||
cache-dependency-path: ".github/workflows/test-windows.yml"
|
||||
|
||||
- name: Print build system information
|
||||
run: python3 .github/workflows/system-info.py
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: >
|
||||
python3 -m pip install
|
||||
coverage>=7.4.2
|
||||
defusedxml
|
||||
olefile
|
||||
pyroma
|
||||
pytest
|
||||
pytest-cov
|
||||
pytest-timeout
|
||||
|
||||
- name: Install dependencies
|
||||
id: install
|
||||
run: |
|
||||
choco install nasm --no-progress
|
||||
echo "C:\Program Files\NASM" >> $env:GITHUB_PATH
|
||||
|
||||
choco install ghostscript --version=10.3.1 --no-progress
|
||||
echo "C:\Program Files\gs\gs10.00.0\bin" >> $env:GITHUB_PATH
|
||||
|
||||
# Install extra test images
|
||||
xcopy /S /Y Tests\test-images\* Tests\images
|
||||
|
||||
# make cache key depend on VS version
|
||||
& "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" `
|
||||
| find """catalog_buildVersion""" `
|
||||
| ForEach-Object { $a = $_.split(" ")[1]; echo "vs=$a" >> $env:GITHUB_OUTPUT }
|
||||
shell: pwsh
|
||||
|
||||
- name: Cache build
|
||||
id: build-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: winbuild\build
|
||||
key:
|
||||
${{ hashFiles('winbuild\build_prepare.py') }}-${{ hashFiles('.github\workflows\test-windows.yml') }}-${{ env.pythonLocation }}-${{ steps.install.outputs.vs }}
|
||||
|
||||
- name: Prepare build
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
& python.exe winbuild\build_prepare.py -v
|
||||
shell: pwsh
|
||||
|
||||
- name: Build dependencies / libjpeg-turbo
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_libjpeg.cmd"
|
||||
|
||||
- name: Build dependencies / zlib
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_zlib.cmd"
|
||||
|
||||
- name: Build dependencies / xz
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_xz.cmd"
|
||||
|
||||
- name: Build dependencies / WebP
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_libwebp.cmd"
|
||||
|
||||
- name: Build dependencies / LibTiff
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_libtiff.cmd"
|
||||
|
||||
# for FreeType CBDT/SBIX font support
|
||||
- name: Build dependencies / libpng
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_libpng.cmd"
|
||||
|
||||
# for FreeType WOFF2 font support
|
||||
- name: Build dependencies / brotli
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_brotli.cmd"
|
||||
|
||||
- name: Build dependencies / FreeType
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_freetype.cmd"
|
||||
|
||||
- name: Build dependencies / LCMS2
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_lcms2.cmd"
|
||||
|
||||
- name: Build dependencies / OpenJPEG
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_openjpeg.cmd"
|
||||
|
||||
# GPL licensed
|
||||
- name: Build dependencies / libimagequant
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_libimagequant.cmd"
|
||||
|
||||
# Raqm dependencies
|
||||
- name: Build dependencies / HarfBuzz
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_harfbuzz.cmd"
|
||||
|
||||
# Raqm dependencies
|
||||
- name: Build dependencies / FriBidi
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: "& winbuild\\build\\build_dep_fribidi.cmd"
|
||||
|
||||
# trim ~150MB for each job
|
||||
- name: Optimize build cache
|
||||
if: steps.build-cache.outputs.cache-hit != 'true'
|
||||
run: rmdir /S /Q winbuild\build\src
|
||||
shell: cmd
|
||||
|
||||
- name: Build Pillow
|
||||
run: |
|
||||
$FLAGS="-C raqm=vendor -C fribidi=vendor"
|
||||
cmd /c "winbuild\build\build_env.cmd && $env:pythonLocation\python.exe -m pip install -v $FLAGS ."
|
||||
& $env:pythonLocation\python.exe selftest.py --installed
|
||||
shell: pwsh
|
||||
|
||||
# skip PyPy for speed
|
||||
- name: Enable heap verification
|
||||
if: "!contains(matrix.python-version, 'pypy')"
|
||||
run: |
|
||||
& reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\python.exe" /v "GlobalFlag" /t REG_SZ /d "0x02000000" /f
|
||||
|
||||
- name: Test Pillow
|
||||
run: |
|
||||
path %GITHUB_WORKSPACE%\\winbuild\\build\\bin;%PATH%
|
||||
python.exe -m pytest -vx -W always --cov PIL --cov Tests --cov-report term --cov-report xml Tests
|
||||
shell: cmd
|
||||
|
||||
- name: Prepare to upload errors
|
||||
if: failure()
|
||||
run: |
|
||||
mkdir -p Tests/errors
|
||||
shell: bash
|
||||
|
||||
- name: Upload errors
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: errors
|
||||
path: Tests/errors
|
||||
|
||||
- name: After success
|
||||
run: |
|
||||
.ci/after_success.sh
|
||||
shell: pwsh
|
||||
|
||||
- name: Upload coverage
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
file: ./coverage.xml
|
||||
flags: GHA_Windows
|
||||
name: ${{ runner.os }} Python ${{ matrix.python-version }}
|
||||
token: ${{ secrets.CODECOV_ORG_TOKEN }}
|
||||
|
||||
success:
|
||||
permissions:
|
||||
contents: none
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
name: Windows Test Successful
|
||||
steps:
|
||||
- name: Success
|
||||
run: echo Windows Test Successful
|
||||
|
|
336
.github/workflows/test.yml
vendored
336
.github/workflows/test.yml
vendored
|
@ -1,168 +1,168 @@
|
|||
name: Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
COVERAGE_CORE: sysmon
|
||||
FORCE_COLOR: 1
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [
|
||||
"macos-14",
|
||||
"ubuntu-latest",
|
||||
]
|
||||
python-version: [
|
||||
"pypy3.10",
|
||||
"pypy3.9",
|
||||
"3.13",
|
||||
"3.12",
|
||||
"3.11",
|
||||
"3.10",
|
||||
"3.9",
|
||||
"3.8",
|
||||
]
|
||||
include:
|
||||
- python-version: "3.11"
|
||||
PYTHONOPTIMIZE: 1
|
||||
REVERSE: "--reverse"
|
||||
- python-version: "3.10"
|
||||
PYTHONOPTIMIZE: 2
|
||||
# M1 only available for 3.10+
|
||||
- os: "macos-13"
|
||||
python-version: "3.9"
|
||||
- os: "macos-13"
|
||||
python-version: "3.8"
|
||||
exclude:
|
||||
- os: "macos-14"
|
||||
python-version: "3.9"
|
||||
- os: "macos-14"
|
||||
python-version: "3.8"
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: ${{ matrix.os }} Python ${{ matrix.python-version }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
allow-prereleases: true
|
||||
cache: pip
|
||||
cache-dependency-path: |
|
||||
".ci/*.sh"
|
||||
"pyproject.toml"
|
||||
|
||||
- name: Build system information
|
||||
run: python3 .github/workflows/system-info.py
|
||||
|
||||
- name: Cache libimagequant
|
||||
if: startsWith(matrix.os, 'ubuntu')
|
||||
uses: actions/cache@v4
|
||||
id: cache-libimagequant
|
||||
with:
|
||||
path: ~/cache-libimagequant
|
||||
key: ${{ runner.os }}-libimagequant-${{ hashFiles('depends/install_imagequant.sh') }}
|
||||
|
||||
- name: Install Linux dependencies
|
||||
if: startsWith(matrix.os, 'ubuntu')
|
||||
run: |
|
||||
.ci/install.sh
|
||||
env:
|
||||
GHA_PYTHON_VERSION: ${{ matrix.python-version }}
|
||||
GHA_LIBIMAGEQUANT_CACHE_HIT: ${{ steps.cache-libimagequant.outputs.cache-hit }}
|
||||
|
||||
- name: Install macOS dependencies
|
||||
if: startsWith(matrix.os, 'macOS')
|
||||
run: |
|
||||
.github/workflows/macos-install.sh
|
||||
env:
|
||||
GHA_PYTHON_VERSION: ${{ matrix.python-version }}
|
||||
|
||||
- name: Register gcc problem matcher
|
||||
if: "matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12'"
|
||||
run: echo "::add-matcher::.github/problem-matchers/gcc.json"
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
.ci/build.sh
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
if [ $REVERSE ]; then
|
||||
python3 -m pip install pytest-reverse
|
||||
fi
|
||||
if [ "${{ matrix.os }}" = "ubuntu-latest" ]; then
|
||||
xvfb-run -s '-screen 0 1024x768x24' sway&
|
||||
export WAYLAND_DISPLAY=wayland-1
|
||||
.ci/test.sh
|
||||
else
|
||||
.ci/test.sh
|
||||
fi
|
||||
env:
|
||||
PYTHONOPTIMIZE: ${{ matrix.PYTHONOPTIMIZE }}
|
||||
REVERSE: ${{ matrix.REVERSE }}
|
||||
|
||||
- name: Prepare to upload errors
|
||||
if: failure()
|
||||
run: |
|
||||
mkdir -p Tests/errors
|
||||
|
||||
- name: Upload errors
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: errors
|
||||
path: Tests/errors
|
||||
|
||||
- name: After success
|
||||
run: |
|
||||
.ci/after_success.sh
|
||||
|
||||
- name: Upload coverage
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
flags: ${{ matrix.os == 'ubuntu-latest' && 'GHA_Ubuntu' || 'GHA_macOS' }}
|
||||
name: ${{ matrix.os }} Python ${{ matrix.python-version }}
|
||||
gcov: true
|
||||
token: ${{ secrets.CODECOV_ORG_TOKEN }}
|
||||
|
||||
success:
|
||||
permissions:
|
||||
contents: none
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
name: Test Successful
|
||||
steps:
|
||||
- name: Success
|
||||
run: echo Test Successful
|
||||
name: Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
COVERAGE_CORE: sysmon
|
||||
FORCE_COLOR: 1
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [
|
||||
"macos-14",
|
||||
"ubuntu-latest",
|
||||
]
|
||||
python-version: [
|
||||
"pypy3.10",
|
||||
"pypy3.9",
|
||||
"3.13",
|
||||
"3.12",
|
||||
"3.11",
|
||||
"3.10",
|
||||
"3.9",
|
||||
"3.8",
|
||||
]
|
||||
include:
|
||||
- python-version: "3.11"
|
||||
PYTHONOPTIMIZE: 1
|
||||
REVERSE: "--reverse"
|
||||
- python-version: "3.10"
|
||||
PYTHONOPTIMIZE: 2
|
||||
# M1 only available for 3.10+
|
||||
- os: "macos-13"
|
||||
python-version: "3.9"
|
||||
- os: "macos-13"
|
||||
python-version: "3.8"
|
||||
exclude:
|
||||
- os: "macos-14"
|
||||
python-version: "3.9"
|
||||
- os: "macos-14"
|
||||
python-version: "3.8"
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: ${{ matrix.os }} Python ${{ matrix.python-version }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
allow-prereleases: true
|
||||
cache: pip
|
||||
cache-dependency-path: |
|
||||
".ci/*.sh"
|
||||
"pyproject.toml"
|
||||
|
||||
- name: Build system information
|
||||
run: python3 .github/workflows/system-info.py
|
||||
|
||||
- name: Cache libimagequant
|
||||
if: startsWith(matrix.os, 'ubuntu')
|
||||
uses: actions/cache@v4
|
||||
id: cache-libimagequant
|
||||
with:
|
||||
path: ~/cache-libimagequant
|
||||
key: ${{ runner.os }}-libimagequant-${{ hashFiles('depends/install_imagequant.sh') }}
|
||||
|
||||
- name: Install Linux dependencies
|
||||
if: startsWith(matrix.os, 'ubuntu')
|
||||
run: |
|
||||
.ci/install.sh
|
||||
env:
|
||||
GHA_PYTHON_VERSION: ${{ matrix.python-version }}
|
||||
GHA_LIBIMAGEQUANT_CACHE_HIT: ${{ steps.cache-libimagequant.outputs.cache-hit }}
|
||||
|
||||
- name: Install macOS dependencies
|
||||
if: startsWith(matrix.os, 'macOS')
|
||||
run: |
|
||||
.github/workflows/macos-install.sh
|
||||
env:
|
||||
GHA_PYTHON_VERSION: ${{ matrix.python-version }}
|
||||
|
||||
- name: Register gcc problem matcher
|
||||
if: "matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12'"
|
||||
run: echo "::add-matcher::.github/problem-matchers/gcc.json"
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
.ci/build.sh
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
if [ $REVERSE ]; then
|
||||
python3 -m pip install pytest-reverse
|
||||
fi
|
||||
if [ "${{ matrix.os }}" = "ubuntu-latest" ]; then
|
||||
xvfb-run -s '-screen 0 1024x768x24' sway&
|
||||
export WAYLAND_DISPLAY=wayland-1
|
||||
.ci/test.sh
|
||||
else
|
||||
.ci/test.sh
|
||||
fi
|
||||
env:
|
||||
PYTHONOPTIMIZE: ${{ matrix.PYTHONOPTIMIZE }}
|
||||
REVERSE: ${{ matrix.REVERSE }}
|
||||
|
||||
- name: Prepare to upload errors
|
||||
if: failure()
|
||||
run: |
|
||||
mkdir -p Tests/errors
|
||||
|
||||
- name: Upload errors
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: errors
|
||||
path: Tests/errors
|
||||
|
||||
- name: After success
|
||||
run: |
|
||||
.ci/after_success.sh
|
||||
|
||||
- name: Upload coverage
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
flags: ${{ matrix.os == 'ubuntu-latest' && 'GHA_Ubuntu' || 'GHA_macOS' }}
|
||||
name: ${{ matrix.os }} Python ${{ matrix.python-version }}
|
||||
gcov: true
|
||||
token: ${{ secrets.CODECOV_ORG_TOKEN }}
|
||||
|
||||
success:
|
||||
permissions:
|
||||
contents: none
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
name: Test Successful
|
||||
steps:
|
||||
- name: Success
|
||||
run: echo Test Successful
|
||||
|
|
304
.github/workflows/wheels-dependencies.sh
vendored
304
.github/workflows/wheels-dependencies.sh
vendored
|
@ -1,152 +1,152 @@
|
|||
#!/bin/bash
|
||||
# Define custom utilities
|
||||
# Test for macOS with [ -n "$IS_MACOS" ]
|
||||
if [ -z "$IS_MACOS" ]; then
|
||||
export MB_ML_LIBC=${AUDITWHEEL_POLICY::9}
|
||||
export MB_ML_VER=${AUDITWHEEL_POLICY:9}
|
||||
fi
|
||||
export PLAT=$CIBW_ARCHS
|
||||
source wheels/multibuild/common_utils.sh
|
||||
source wheels/multibuild/library_builders.sh
|
||||
if [ -z "$IS_MACOS" ]; then
|
||||
source wheels/multibuild/manylinux_utils.sh
|
||||
fi
|
||||
|
||||
ARCHIVE_SDIR=pillow-depends-main
|
||||
|
||||
# Package versions for fresh source builds
|
||||
FREETYPE_VERSION=2.13.2
|
||||
HARFBUZZ_VERSION=8.5.0
|
||||
LIBPNG_VERSION=1.6.43
|
||||
JPEGTURBO_VERSION=3.0.3
|
||||
OPENJPEG_VERSION=2.5.2
|
||||
XZ_VERSION=5.4.5
|
||||
TIFF_VERSION=4.6.0
|
||||
LCMS2_VERSION=2.16
|
||||
if [[ -n "$IS_MACOS" ]]; then
|
||||
GIFLIB_VERSION=5.2.2
|
||||
else
|
||||
GIFLIB_VERSION=5.2.1
|
||||
fi
|
||||
if [[ -n "$IS_MACOS" ]] || [[ "$MB_ML_VER" != 2014 ]]; then
|
||||
ZLIB_VERSION=1.3.1
|
||||
else
|
||||
ZLIB_VERSION=1.2.8
|
||||
fi
|
||||
LIBWEBP_VERSION=1.4.0
|
||||
BZIP2_VERSION=1.0.8
|
||||
LIBXCB_VERSION=1.17.0
|
||||
BROTLI_VERSION=1.1.0
|
||||
|
||||
if [[ -n "$IS_MACOS" ]] && [[ "$CIBW_ARCHS" == "x86_64" ]]; then
|
||||
function build_openjpeg {
|
||||
local out_dir=$(fetch_unpack https://github.com/uclouvain/openjpeg/archive/v${OPENJPEG_VERSION}.tar.gz openjpeg-${OPENJPEG_VERSION}.tar.gz)
|
||||
(cd $out_dir \
|
||||
&& cmake -DCMAKE_INSTALL_PREFIX=$BUILD_PREFIX -DCMAKE_INSTALL_NAME_DIR=$BUILD_PREFIX/lib . \
|
||||
&& make install)
|
||||
touch openjpeg-stamp
|
||||
}
|
||||
fi
|
||||
|
||||
function build_brotli {
|
||||
local cmake=$(get_modern_cmake)
|
||||
local out_dir=$(fetch_unpack https://github.com/google/brotli/archive/v$BROTLI_VERSION.tar.gz brotli-1.1.0.tar.gz)
|
||||
(cd $out_dir \
|
||||
&& $cmake -DCMAKE_INSTALL_PREFIX=$BUILD_PREFIX -DCMAKE_INSTALL_NAME_DIR=$BUILD_PREFIX/lib . \
|
||||
&& make install)
|
||||
if [[ "$MB_ML_LIBC" == "manylinux" ]]; then
|
||||
cp /usr/local/lib64/libbrotli* /usr/local/lib
|
||||
cp /usr/local/lib64/pkgconfig/libbrotli* /usr/local/lib/pkgconfig
|
||||
fi
|
||||
}
|
||||
|
||||
function build {
|
||||
if [[ -n "$IS_MACOS" ]] && [[ "$CIBW_ARCHS" == "arm64" ]]; then
|
||||
sudo chown -R runner /usr/local
|
||||
fi
|
||||
build_xz
|
||||
if [ -z "$IS_ALPINE" ] && [ -z "$IS_MACOS" ]; then
|
||||
yum remove -y zlib-devel
|
||||
fi
|
||||
build_new_zlib
|
||||
|
||||
build_simple xcb-proto 1.17.0 https://xorg.freedesktop.org/archive/individual/proto
|
||||
if [ -n "$IS_MACOS" ]; then
|
||||
build_simple xorgproto 2024.1 https://www.x.org/pub/individual/proto
|
||||
build_simple libXau 1.0.11 https://www.x.org/pub/individual/lib
|
||||
build_simple libpthread-stubs 0.5 https://xcb.freedesktop.org/dist
|
||||
if [[ "$CIBW_ARCHS" == "arm64" ]]; then
|
||||
cp /usr/local/share/pkgconfig/xcb-proto.pc /usr/local/lib/pkgconfig
|
||||
fi
|
||||
else
|
||||
sed s/\${pc_sysrootdir\}// /usr/local/share/pkgconfig/xcb-proto.pc > /usr/local/lib/pkgconfig/xcb-proto.pc
|
||||
fi
|
||||
build_simple libxcb $LIBXCB_VERSION https://www.x.org/releases/individual/lib
|
||||
|
||||
build_libjpeg_turbo
|
||||
build_tiff
|
||||
build_libpng
|
||||
build_lcms2
|
||||
build_openjpeg
|
||||
if [ -f /usr/local/lib64/libopenjp2.so ]; then
|
||||
cp /usr/local/lib64/libopenjp2.so /usr/local/lib
|
||||
fi
|
||||
|
||||
ORIGINAL_CFLAGS=$CFLAGS
|
||||
CFLAGS="$CFLAGS -O3 -DNDEBUG"
|
||||
if [[ -n "$IS_MACOS" ]]; then
|
||||
CFLAGS="$CFLAGS -Wl,-headerpad_max_install_names"
|
||||
fi
|
||||
build_libwebp
|
||||
CFLAGS=$ORIGINAL_CFLAGS
|
||||
|
||||
build_brotli
|
||||
|
||||
if [ -n "$IS_MACOS" ]; then
|
||||
# Custom freetype build
|
||||
build_simple freetype $FREETYPE_VERSION https://download.savannah.gnu.org/releases/freetype tar.gz --with-harfbuzz=no
|
||||
else
|
||||
build_freetype
|
||||
fi
|
||||
|
||||
if [ -z "$IS_MACOS" ]; then
|
||||
export FREETYPE_LIBS=-lfreetype
|
||||
export FREETYPE_CFLAGS=-I/usr/local/include/freetype2/
|
||||
fi
|
||||
build_simple harfbuzz $HARFBUZZ_VERSION https://github.com/harfbuzz/harfbuzz/releases/download/$HARFBUZZ_VERSION tar.xz --with-freetype=yes --with-glib=no
|
||||
if [ -z "$IS_MACOS" ]; then
|
||||
export FREETYPE_LIBS=""
|
||||
export FREETYPE_CFLAGS=""
|
||||
fi
|
||||
}
|
||||
|
||||
# Any stuff that you need to do before you start building the wheels
|
||||
# Runs in the root directory of this repository.
|
||||
curl -fsSL -o pillow-depends-main.zip https://github.com/python-pillow/pillow-depends/archive/main.zip
|
||||
untar pillow-depends-main.zip
|
||||
|
||||
if [[ -n "$IS_MACOS" ]]; then
|
||||
# libtiff and libxcb cause a conflict with building libtiff and libxcb
|
||||
# libxau and libxdmcp cause an issue on macOS < 11
|
||||
# remove cairo to fix building harfbuzz on arm64
|
||||
# remove lcms2 and libpng to fix building openjpeg on arm64
|
||||
# remove jpeg-turbo to avoid inclusion on arm64
|
||||
# remove webp and zstd to avoid inclusion on x86_64
|
||||
# curl from brew requires zstd, use system curl
|
||||
brew remove --ignore-dependencies libpng libtiff libxcb libxau libxdmcp curl cairo lcms2 zstd
|
||||
if [[ "$CIBW_ARCHS" == "arm64" ]]; then
|
||||
brew remove --ignore-dependencies jpeg-turbo
|
||||
else
|
||||
brew remove --ignore-dependencies webp
|
||||
fi
|
||||
|
||||
brew install pkg-config
|
||||
fi
|
||||
|
||||
wrap_wheel_builder build
|
||||
|
||||
# Append licenses
|
||||
for filename in wheels/dependency_licenses/*; do
|
||||
echo -e "\n\n----\n\n$(basename $filename | cut -f 1 -d '.')\n" | cat >> LICENSE
|
||||
cat $filename >> LICENSE
|
||||
done
|
||||
#!/bin/bash
|
||||
# Define custom utilities
|
||||
# Test for macOS with [ -n "$IS_MACOS" ]
|
||||
if [ -z "$IS_MACOS" ]; then
|
||||
export MB_ML_LIBC=${AUDITWHEEL_POLICY::9}
|
||||
export MB_ML_VER=${AUDITWHEEL_POLICY:9}
|
||||
fi
|
||||
export PLAT=$CIBW_ARCHS
|
||||
source wheels/multibuild/common_utils.sh
|
||||
source wheels/multibuild/library_builders.sh
|
||||
if [ -z "$IS_MACOS" ]; then
|
||||
source wheels/multibuild/manylinux_utils.sh
|
||||
fi
|
||||
|
||||
ARCHIVE_SDIR=pillow-depends-main
|
||||
|
||||
# Package versions for fresh source builds
|
||||
FREETYPE_VERSION=2.13.2
|
||||
HARFBUZZ_VERSION=8.5.0
|
||||
LIBPNG_VERSION=1.6.43
|
||||
JPEGTURBO_VERSION=3.0.3
|
||||
OPENJPEG_VERSION=2.5.2
|
||||
XZ_VERSION=5.4.5
|
||||
TIFF_VERSION=4.6.0
|
||||
LCMS2_VERSION=2.16
|
||||
if [[ -n "$IS_MACOS" ]]; then
|
||||
GIFLIB_VERSION=5.2.2
|
||||
else
|
||||
GIFLIB_VERSION=5.2.1
|
||||
fi
|
||||
if [[ -n "$IS_MACOS" ]] || [[ "$MB_ML_VER" != 2014 ]]; then
|
||||
ZLIB_VERSION=1.3.1
|
||||
else
|
||||
ZLIB_VERSION=1.2.8
|
||||
fi
|
||||
LIBWEBP_VERSION=1.4.0
|
||||
BZIP2_VERSION=1.0.8
|
||||
LIBXCB_VERSION=1.17.0
|
||||
BROTLI_VERSION=1.1.0
|
||||
|
||||
if [[ -n "$IS_MACOS" ]] && [[ "$CIBW_ARCHS" == "x86_64" ]]; then
|
||||
function build_openjpeg {
|
||||
local out_dir=$(fetch_unpack https://github.com/uclouvain/openjpeg/archive/v${OPENJPEG_VERSION}.tar.gz openjpeg-${OPENJPEG_VERSION}.tar.gz)
|
||||
(cd $out_dir \
|
||||
&& cmake -DCMAKE_INSTALL_PREFIX=$BUILD_PREFIX -DCMAKE_INSTALL_NAME_DIR=$BUILD_PREFIX/lib . \
|
||||
&& make install)
|
||||
touch openjpeg-stamp
|
||||
}
|
||||
fi
|
||||
|
||||
function build_brotli {
|
||||
local cmake=$(get_modern_cmake)
|
||||
local out_dir=$(fetch_unpack https://github.com/google/brotli/archive/v$BROTLI_VERSION.tar.gz brotli-1.1.0.tar.gz)
|
||||
(cd $out_dir \
|
||||
&& $cmake -DCMAKE_INSTALL_PREFIX=$BUILD_PREFIX -DCMAKE_INSTALL_NAME_DIR=$BUILD_PREFIX/lib . \
|
||||
&& make install)
|
||||
if [[ "$MB_ML_LIBC" == "manylinux" ]]; then
|
||||
cp /usr/local/lib64/libbrotli* /usr/local/lib
|
||||
cp /usr/local/lib64/pkgconfig/libbrotli* /usr/local/lib/pkgconfig
|
||||
fi
|
||||
}
|
||||
|
||||
function build {
|
||||
if [[ -n "$IS_MACOS" ]] && [[ "$CIBW_ARCHS" == "arm64" ]]; then
|
||||
sudo chown -R runner /usr/local
|
||||
fi
|
||||
build_xz
|
||||
if [ -z "$IS_ALPINE" ] && [ -z "$IS_MACOS" ]; then
|
||||
yum remove -y zlib-devel
|
||||
fi
|
||||
build_new_zlib
|
||||
|
||||
build_simple xcb-proto 1.17.0 https://xorg.freedesktop.org/archive/individual/proto
|
||||
if [ -n "$IS_MACOS" ]; then
|
||||
build_simple xorgproto 2024.1 https://www.x.org/pub/individual/proto
|
||||
build_simple libXau 1.0.11 https://www.x.org/pub/individual/lib
|
||||
build_simple libpthread-stubs 0.5 https://xcb.freedesktop.org/dist
|
||||
if [[ "$CIBW_ARCHS" == "arm64" ]]; then
|
||||
cp /usr/local/share/pkgconfig/xcb-proto.pc /usr/local/lib/pkgconfig
|
||||
fi
|
||||
else
|
||||
sed s/\${pc_sysrootdir\}// /usr/local/share/pkgconfig/xcb-proto.pc > /usr/local/lib/pkgconfig/xcb-proto.pc
|
||||
fi
|
||||
build_simple libxcb $LIBXCB_VERSION https://www.x.org/releases/individual/lib
|
||||
|
||||
build_libjpeg_turbo
|
||||
build_tiff
|
||||
build_libpng
|
||||
build_lcms2
|
||||
build_openjpeg
|
||||
if [ -f /usr/local/lib64/libopenjp2.so ]; then
|
||||
cp /usr/local/lib64/libopenjp2.so /usr/local/lib
|
||||
fi
|
||||
|
||||
ORIGINAL_CFLAGS=$CFLAGS
|
||||
CFLAGS="$CFLAGS -O3 -DNDEBUG"
|
||||
if [[ -n "$IS_MACOS" ]]; then
|
||||
CFLAGS="$CFLAGS -Wl,-headerpad_max_install_names"
|
||||
fi
|
||||
build_libwebp
|
||||
CFLAGS=$ORIGINAL_CFLAGS
|
||||
|
||||
build_brotli
|
||||
|
||||
if [ -n "$IS_MACOS" ]; then
|
||||
# Custom freetype build
|
||||
build_simple freetype $FREETYPE_VERSION https://download.savannah.gnu.org/releases/freetype tar.gz --with-harfbuzz=no
|
||||
else
|
||||
build_freetype
|
||||
fi
|
||||
|
||||
if [ -z "$IS_MACOS" ]; then
|
||||
export FREETYPE_LIBS=-lfreetype
|
||||
export FREETYPE_CFLAGS=-I/usr/local/include/freetype2/
|
||||
fi
|
||||
build_simple harfbuzz $HARFBUZZ_VERSION https://github.com/harfbuzz/harfbuzz/releases/download/$HARFBUZZ_VERSION tar.xz --with-freetype=yes --with-glib=no
|
||||
if [ -z "$IS_MACOS" ]; then
|
||||
export FREETYPE_LIBS=""
|
||||
export FREETYPE_CFLAGS=""
|
||||
fi
|
||||
}
|
||||
|
||||
# Any stuff that you need to do before you start building the wheels
|
||||
# Runs in the root directory of this repository.
|
||||
curl -fsSL -o pillow-depends-main.zip https://github.com/python-pillow/pillow-depends/archive/main.zip
|
||||
untar pillow-depends-main.zip
|
||||
|
||||
if [[ -n "$IS_MACOS" ]]; then
|
||||
# libtiff and libxcb cause a conflict with building libtiff and libxcb
|
||||
# libxau and libxdmcp cause an issue on macOS < 11
|
||||
# remove cairo to fix building harfbuzz on arm64
|
||||
# remove lcms2 and libpng to fix building openjpeg on arm64
|
||||
# remove jpeg-turbo to avoid inclusion on arm64
|
||||
# remove webp and zstd to avoid inclusion on x86_64
|
||||
# curl from brew requires zstd, use system curl
|
||||
brew remove --ignore-dependencies libpng libtiff libxcb libxau libxdmcp curl cairo lcms2 zstd
|
||||
if [[ "$CIBW_ARCHS" == "arm64" ]]; then
|
||||
brew remove --ignore-dependencies jpeg-turbo
|
||||
else
|
||||
brew remove --ignore-dependencies webp
|
||||
fi
|
||||
|
||||
brew install pkg-config
|
||||
fi
|
||||
|
||||
wrap_wheel_builder build
|
||||
|
||||
# Append licenses
|
||||
for filename in wheels/dependency_licenses/*; do
|
||||
echo -e "\n\n----\n\n$(basename $filename | cut -f 1 -d '.')\n" | cat >> LICENSE
|
||||
cat $filename >> LICENSE
|
||||
done
|
||||
|
|
44
.github/workflows/wheels-test.ps1
vendored
44
.github/workflows/wheels-test.ps1
vendored
|
@ -1,22 +1,22 @@
|
|||
param ([string]$venv, [string]$pillow="C:\pillow")
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
Set-PSDebug -Trace 1
|
||||
if ("$venv" -like "*\cibw-run-*\pp*-win_amd64\*") {
|
||||
# unlike CPython, PyPy requires Visual C++ Redistributable to be installed
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
Invoke-WebRequest -Uri 'https://aka.ms/vs/15/release/vc_redist.x64.exe' -OutFile 'vc_redist.x64.exe'
|
||||
C:\vc_redist.x64.exe /install /quiet /norestart | Out-Null
|
||||
}
|
||||
$env:path += ";$pillow\winbuild\build\bin\"
|
||||
& "$venv\Scripts\activate.ps1"
|
||||
& reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\python.exe" /v "GlobalFlag" /t REG_SZ /d "0x02000000" /f
|
||||
cd $pillow
|
||||
& python -VV
|
||||
if (!$?) { exit $LASTEXITCODE }
|
||||
& python selftest.py
|
||||
if (!$?) { exit $LASTEXITCODE }
|
||||
& python -m pytest -vx Tests\check_wheel.py
|
||||
if (!$?) { exit $LASTEXITCODE }
|
||||
& python -m pytest -vx Tests
|
||||
if (!$?) { exit $LASTEXITCODE }
|
||||
param ([string]$venv, [string]$pillow="C:\pillow")
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
Set-PSDebug -Trace 1
|
||||
if ("$venv" -like "*\cibw-run-*\pp*-win_amd64\*") {
|
||||
# unlike CPython, PyPy requires Visual C++ Redistributable to be installed
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
Invoke-WebRequest -Uri 'https://aka.ms/vs/15/release/vc_redist.x64.exe' -OutFile 'vc_redist.x64.exe'
|
||||
C:\vc_redist.x64.exe /install /quiet /norestart | Out-Null
|
||||
}
|
||||
$env:path += ";$pillow\winbuild\build\bin\"
|
||||
& "$venv\Scripts\activate.ps1"
|
||||
& reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\python.exe" /v "GlobalFlag" /t REG_SZ /d "0x02000000" /f
|
||||
cd $pillow
|
||||
& python -VV
|
||||
if (!$?) { exit $LASTEXITCODE }
|
||||
& python selftest.py
|
||||
if (!$?) { exit $LASTEXITCODE }
|
||||
& python -m pytest -vx Tests\check_wheel.py
|
||||
if (!$?) { exit $LASTEXITCODE }
|
||||
& python -m pytest -vx Tests
|
||||
if (!$?) { exit $LASTEXITCODE }
|
||||
|
|
56
.github/workflows/wheels-test.sh
vendored
56
.github/workflows/wheels-test.sh
vendored
|
@ -1,28 +1,28 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
brew install fribidi
|
||||
export PKG_CONFIG_PATH="/usr/local/opt/openblas/lib/pkgconfig"
|
||||
if [ -f /opt/homebrew/lib/libfribidi.dylib ]; then
|
||||
sudo cp /opt/homebrew/lib/libfribidi.dylib /usr/local/lib
|
||||
fi
|
||||
elif [ "${AUDITWHEEL_POLICY::9}" == "musllinux" ]; then
|
||||
apk add curl fribidi
|
||||
else
|
||||
yum install -y fribidi
|
||||
fi
|
||||
if [ "${AUDITWHEEL_POLICY::9}" != "musllinux" ] && !([[ "$OSTYPE" == "darwin"* ]] && [[ $(python3 --version) == *"3.13."* ]]); then
|
||||
python3 -m pip install numpy
|
||||
fi
|
||||
|
||||
if [ ! -d "test-images-main" ]; then
|
||||
curl -fsSL -o pillow-test-images.zip https://github.com/python-pillow/test-images/archive/main.zip
|
||||
unzip pillow-test-images.zip
|
||||
mv test-images-main/* Tests/images
|
||||
fi
|
||||
|
||||
# Runs tests
|
||||
python3 selftest.py
|
||||
python3 -m pytest Tests/check_wheel.py
|
||||
python3 -m pytest
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
brew install fribidi
|
||||
export PKG_CONFIG_PATH="/usr/local/opt/openblas/lib/pkgconfig"
|
||||
if [ -f /opt/homebrew/lib/libfribidi.dylib ]; then
|
||||
sudo cp /opt/homebrew/lib/libfribidi.dylib /usr/local/lib
|
||||
fi
|
||||
elif [ "${AUDITWHEEL_POLICY::9}" == "musllinux" ]; then
|
||||
apk add curl fribidi
|
||||
else
|
||||
yum install -y fribidi
|
||||
fi
|
||||
if [ "${AUDITWHEEL_POLICY::9}" != "musllinux" ] && !([[ "$OSTYPE" == "darwin"* ]] && [[ $(python3 --version) == *"3.13."* ]]); then
|
||||
python3 -m pip install numpy
|
||||
fi
|
||||
|
||||
if [ ! -d "test-images-main" ]; then
|
||||
curl -fsSL -o pillow-test-images.zip https://github.com/python-pillow/test-images/archive/main.zip
|
||||
unzip pillow-test-images.zip
|
||||
mv test-images-main/* Tests/images
|
||||
fi
|
||||
|
||||
# Runs tests
|
||||
python3 selftest.py
|
||||
python3 -m pytest Tests/check_wheel.py
|
||||
python3 -m pytest
|
||||
|
|
540
.github/workflows/wheels.yml
vendored
540
.github/workflows/wheels.yml
vendored
|
@ -1,270 +1,270 @@
|
|||
name: Wheels
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".ci/requirements-cibw.txt"
|
||||
- ".github/workflows/wheel*"
|
||||
- "setup.py"
|
||||
- "wheels/*"
|
||||
- "winbuild/build_prepare.py"
|
||||
- "winbuild/fribidi.cmake"
|
||||
tags:
|
||||
- "*"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".ci/requirements-cibw.txt"
|
||||
- ".github/workflows/wheel*"
|
||||
- "setup.py"
|
||||
- "wheels/*"
|
||||
- "winbuild/build_prepare.py"
|
||||
- "winbuild/fribidi.cmake"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
||||
jobs:
|
||||
build-1-QEMU-emulated-wheels:
|
||||
name: aarch64 ${{ matrix.python-version }} ${{ matrix.spec }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version:
|
||||
- pp39
|
||||
- pp310
|
||||
- cp38
|
||||
- cp39
|
||||
- cp310
|
||||
- cp311
|
||||
- cp312
|
||||
- cp313
|
||||
spec:
|
||||
- manylinux2014
|
||||
- manylinux_2_28
|
||||
- musllinux
|
||||
exclude:
|
||||
- { python-version: pp39, spec: musllinux }
|
||||
- { python-version: pp310, spec: musllinux }
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.x"
|
||||
|
||||
# https://github.com/docker/setup-qemu-action
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Install cibuildwheel
|
||||
run: |
|
||||
python3 -m pip install -r .ci/requirements-cibw.txt
|
||||
|
||||
- name: Build wheels
|
||||
run: |
|
||||
python3 -m cibuildwheel --output-dir wheelhouse
|
||||
env:
|
||||
# Build only the currently selected Linux architecture (so we can
|
||||
# parallelise for speed).
|
||||
CIBW_ARCHS: "aarch64"
|
||||
# Likewise, select only one Python version per job to speed this up.
|
||||
CIBW_BUILD: "${{ matrix.python-version }}-${{ matrix.spec == 'musllinux' && 'musllinux' || 'manylinux' }}*"
|
||||
CIBW_PRERELEASE_PYTHONS: True
|
||||
# Extra options for manylinux.
|
||||
CIBW_MANYLINUX_AARCH64_IMAGE: ${{ matrix.spec }}
|
||||
CIBW_MANYLINUX_PYPY_AARCH64_IMAGE: ${{ matrix.spec }}
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dist-qemu-${{ matrix.python-version }}-${{ matrix.spec }}
|
||||
path: ./wheelhouse/*.whl
|
||||
|
||||
build-2-native-wheels:
|
||||
name: ${{ matrix.name }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: "macOS x86_64"
|
||||
os: macos-13
|
||||
cibw_arch: x86_64
|
||||
macosx_deployment_target: "10.10"
|
||||
- name: "macOS arm64"
|
||||
os: macos-14
|
||||
cibw_arch: arm64
|
||||
macosx_deployment_target: "11.0"
|
||||
- name: "manylinux2014 and musllinux x86_64"
|
||||
os: ubuntu-latest
|
||||
cibw_arch: x86_64
|
||||
- name: "manylinux_2_28 x86_64"
|
||||
os: ubuntu-latest
|
||||
cibw_arch: x86_64
|
||||
build: "*manylinux*"
|
||||
manylinux: "manylinux_2_28"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.x"
|
||||
|
||||
- name: Install cibuildwheel
|
||||
run: |
|
||||
python3 -m pip install -r .ci/requirements-cibw.txt
|
||||
|
||||
- name: Build wheels
|
||||
run: |
|
||||
python3 -m cibuildwheel --output-dir wheelhouse
|
||||
env:
|
||||
CIBW_ARCHS: ${{ matrix.cibw_arch }}
|
||||
CIBW_BUILD: ${{ matrix.build }}
|
||||
CIBW_MANYLINUX_PYPY_X86_64_IMAGE: ${{ matrix.manylinux }}
|
||||
CIBW_MANYLINUX_X86_64_IMAGE: ${{ matrix.manylinux }}
|
||||
CIBW_PRERELEASE_PYTHONS: True
|
||||
CIBW_SKIP: pp38-*
|
||||
CIBW_TEST_SKIP: cp38-macosx_arm64
|
||||
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macosx_deployment_target }}
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dist-${{ matrix.os }}-${{ matrix.cibw_arch }}${{ matrix.manylinux && format('-{0}', matrix.manylinux) }}
|
||||
path: ./wheelhouse/*.whl
|
||||
|
||||
windows:
|
||||
name: Windows ${{ matrix.cibw_arch }}
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- cibw_arch: x86
|
||||
- cibw_arch: AMD64
|
||||
- cibw_arch: ARM64
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Checkout extra test images
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: python-pillow/test-images
|
||||
path: Tests\test-images
|
||||
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.x"
|
||||
|
||||
- name: Install cibuildwheel
|
||||
run: |
|
||||
python.exe -m pip install -r .ci/requirements-cibw.txt
|
||||
|
||||
- name: Prepare for build
|
||||
run: |
|
||||
choco install nasm --no-progress
|
||||
echo "C:\Program Files\NASM" >> $env:GITHUB_PATH
|
||||
|
||||
# Install extra test images
|
||||
xcopy /S /Y Tests\test-images\* Tests\images
|
||||
|
||||
& python.exe winbuild\build_prepare.py -v --no-imagequant --architecture=${{ matrix.cibw_arch }}
|
||||
shell: pwsh
|
||||
|
||||
- name: Build wheels
|
||||
run: |
|
||||
setlocal EnableDelayedExpansion
|
||||
for %%f in (winbuild\build\license\*) do (
|
||||
set x=%%~nf
|
||||
rem Skip FriBiDi license, it is not included in the wheel.
|
||||
set fribidi=!x:~0,7!
|
||||
if NOT !fribidi!==fribidi (
|
||||
rem Skip imagequant license, it is not included in the wheel.
|
||||
set libimagequant=!x:~0,13!
|
||||
if NOT !libimagequant!==libimagequant (
|
||||
echo. >> LICENSE
|
||||
echo ===== %%~nf ===== >> LICENSE
|
||||
echo. >> LICENSE
|
||||
type %%f >> LICENSE
|
||||
)
|
||||
)
|
||||
)
|
||||
call winbuild\\build\\build_env.cmd
|
||||
%pythonLocation%\python.exe -m cibuildwheel . --output-dir wheelhouse
|
||||
env:
|
||||
CIBW_ARCHS: ${{ matrix.cibw_arch }}
|
||||
CIBW_BEFORE_ALL: "{package}\\winbuild\\build\\build_dep_all.cmd"
|
||||
CIBW_CACHE_PATH: "C:\\cibw"
|
||||
CIBW_PRERELEASE_PYTHONS: True
|
||||
CIBW_SKIP: pp38-*
|
||||
CIBW_TEST_SKIP: "*-win_arm64"
|
||||
CIBW_TEST_COMMAND: 'docker run --rm
|
||||
-v {project}:C:\pillow
|
||||
-v C:\cibw:C:\cibw
|
||||
-v %CD%\..\venv-test:%CD%\..\venv-test
|
||||
-e CI -e GITHUB_ACTIONS
|
||||
mcr.microsoft.com/windows/servercore:ltsc2022
|
||||
powershell C:\pillow\.github\workflows\wheels-test.ps1 %CD%\..\venv-test'
|
||||
shell: cmd
|
||||
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dist-windows-${{ matrix.cibw_arch }}
|
||||
path: ./wheelhouse/*.whl
|
||||
|
||||
- name: Upload fribidi.dll
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fribidi-windows-${{ matrix.cibw_arch }}
|
||||
path: winbuild\build\bin\fribidi*
|
||||
|
||||
sdist:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.x"
|
||||
cache: pip
|
||||
cache-dependency-path: "Makefile"
|
||||
|
||||
- run: make sdist
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dist-sdist
|
||||
path: dist/*.tar.gz
|
||||
|
||||
pypi-publish:
|
||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
|
||||
needs: [build-1-QEMU-emulated-wheels, build-2-native-wheels, windows, sdist]
|
||||
runs-on: ubuntu-latest
|
||||
name: Upload release to PyPI
|
||||
environment:
|
||||
name: release-pypi
|
||||
url: https://pypi.org/p/Pillow
|
||||
permissions:
|
||||
id-token: write
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: dist-*
|
||||
path: dist
|
||||
merge-multiple: true
|
||||
- name: Publish to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
name: Wheels
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".ci/requirements-cibw.txt"
|
||||
- ".github/workflows/wheel*"
|
||||
- "setup.py"
|
||||
- "wheels/*"
|
||||
- "winbuild/build_prepare.py"
|
||||
- "winbuild/fribidi.cmake"
|
||||
tags:
|
||||
- "*"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".ci/requirements-cibw.txt"
|
||||
- ".github/workflows/wheel*"
|
||||
- "setup.py"
|
||||
- "wheels/*"
|
||||
- "winbuild/build_prepare.py"
|
||||
- "winbuild/fribidi.cmake"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
||||
jobs:
|
||||
build-1-QEMU-emulated-wheels:
|
||||
name: aarch64 ${{ matrix.python-version }} ${{ matrix.spec }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version:
|
||||
- pp39
|
||||
- pp310
|
||||
- cp38
|
||||
- cp39
|
||||
- cp310
|
||||
- cp311
|
||||
- cp312
|
||||
- cp313
|
||||
spec:
|
||||
- manylinux2014
|
||||
- manylinux_2_28
|
||||
- musllinux
|
||||
exclude:
|
||||
- { python-version: pp39, spec: musllinux }
|
||||
- { python-version: pp310, spec: musllinux }
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.x"
|
||||
|
||||
# https://github.com/docker/setup-qemu-action
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Install cibuildwheel
|
||||
run: |
|
||||
python3 -m pip install -r .ci/requirements-cibw.txt
|
||||
|
||||
- name: Build wheels
|
||||
run: |
|
||||
python3 -m cibuildwheel --output-dir wheelhouse
|
||||
env:
|
||||
# Build only the currently selected Linux architecture (so we can
|
||||
# parallelise for speed).
|
||||
CIBW_ARCHS: "aarch64"
|
||||
# Likewise, select only one Python version per job to speed this up.
|
||||
CIBW_BUILD: "${{ matrix.python-version }}-${{ matrix.spec == 'musllinux' && 'musllinux' || 'manylinux' }}*"
|
||||
CIBW_PRERELEASE_PYTHONS: True
|
||||
# Extra options for manylinux.
|
||||
CIBW_MANYLINUX_AARCH64_IMAGE: ${{ matrix.spec }}
|
||||
CIBW_MANYLINUX_PYPY_AARCH64_IMAGE: ${{ matrix.spec }}
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dist-qemu-${{ matrix.python-version }}-${{ matrix.spec }}
|
||||
path: ./wheelhouse/*.whl
|
||||
|
||||
build-2-native-wheels:
|
||||
name: ${{ matrix.name }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: "macOS x86_64"
|
||||
os: macos-13
|
||||
cibw_arch: x86_64
|
||||
macosx_deployment_target: "10.10"
|
||||
- name: "macOS arm64"
|
||||
os: macos-14
|
||||
cibw_arch: arm64
|
||||
macosx_deployment_target: "11.0"
|
||||
- name: "manylinux2014 and musllinux x86_64"
|
||||
os: ubuntu-latest
|
||||
cibw_arch: x86_64
|
||||
- name: "manylinux_2_28 x86_64"
|
||||
os: ubuntu-latest
|
||||
cibw_arch: x86_64
|
||||
build: "*manylinux*"
|
||||
manylinux: "manylinux_2_28"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.x"
|
||||
|
||||
- name: Install cibuildwheel
|
||||
run: |
|
||||
python3 -m pip install -r .ci/requirements-cibw.txt
|
||||
|
||||
- name: Build wheels
|
||||
run: |
|
||||
python3 -m cibuildwheel --output-dir wheelhouse
|
||||
env:
|
||||
CIBW_ARCHS: ${{ matrix.cibw_arch }}
|
||||
CIBW_BUILD: ${{ matrix.build }}
|
||||
CIBW_MANYLINUX_PYPY_X86_64_IMAGE: ${{ matrix.manylinux }}
|
||||
CIBW_MANYLINUX_X86_64_IMAGE: ${{ matrix.manylinux }}
|
||||
CIBW_PRERELEASE_PYTHONS: True
|
||||
CIBW_SKIP: pp38-*
|
||||
CIBW_TEST_SKIP: cp38-macosx_arm64
|
||||
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macosx_deployment_target }}
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dist-${{ matrix.os }}-${{ matrix.cibw_arch }}${{ matrix.manylinux && format('-{0}', matrix.manylinux) }}
|
||||
path: ./wheelhouse/*.whl
|
||||
|
||||
windows:
|
||||
name: Windows ${{ matrix.cibw_arch }}
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- cibw_arch: x86
|
||||
- cibw_arch: AMD64
|
||||
- cibw_arch: ARM64
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Checkout extra test images
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: python-pillow/test-images
|
||||
path: Tests\test-images
|
||||
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.x"
|
||||
|
||||
- name: Install cibuildwheel
|
||||
run: |
|
||||
python.exe -m pip install -r .ci/requirements-cibw.txt
|
||||
|
||||
- name: Prepare for build
|
||||
run: |
|
||||
choco install nasm --no-progress
|
||||
echo "C:\Program Files\NASM" >> $env:GITHUB_PATH
|
||||
|
||||
# Install extra test images
|
||||
xcopy /S /Y Tests\test-images\* Tests\images
|
||||
|
||||
& python.exe winbuild\build_prepare.py -v --no-imagequant --architecture=${{ matrix.cibw_arch }}
|
||||
shell: pwsh
|
||||
|
||||
- name: Build wheels
|
||||
run: |
|
||||
setlocal EnableDelayedExpansion
|
||||
for %%f in (winbuild\build\license\*) do (
|
||||
set x=%%~nf
|
||||
rem Skip FriBiDi license, it is not included in the wheel.
|
||||
set fribidi=!x:~0,7!
|
||||
if NOT !fribidi!==fribidi (
|
||||
rem Skip imagequant license, it is not included in the wheel.
|
||||
set libimagequant=!x:~0,13!
|
||||
if NOT !libimagequant!==libimagequant (
|
||||
echo. >> LICENSE
|
||||
echo ===== %%~nf ===== >> LICENSE
|
||||
echo. >> LICENSE
|
||||
type %%f >> LICENSE
|
||||
)
|
||||
)
|
||||
)
|
||||
call winbuild\\build\\build_env.cmd
|
||||
%pythonLocation%\python.exe -m cibuildwheel . --output-dir wheelhouse
|
||||
env:
|
||||
CIBW_ARCHS: ${{ matrix.cibw_arch }}
|
||||
CIBW_BEFORE_ALL: "{package}\\winbuild\\build\\build_dep_all.cmd"
|
||||
CIBW_CACHE_PATH: "C:\\cibw"
|
||||
CIBW_PRERELEASE_PYTHONS: True
|
||||
CIBW_SKIP: pp38-*
|
||||
CIBW_TEST_SKIP: "*-win_arm64"
|
||||
CIBW_TEST_COMMAND: 'docker run --rm
|
||||
-v {project}:C:\pillow
|
||||
-v C:\cibw:C:\cibw
|
||||
-v %CD%\..\venv-test:%CD%\..\venv-test
|
||||
-e CI -e GITHUB_ACTIONS
|
||||
mcr.microsoft.com/windows/servercore:ltsc2022
|
||||
powershell C:\pillow\.github\workflows\wheels-test.ps1 %CD%\..\venv-test'
|
||||
shell: cmd
|
||||
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dist-windows-${{ matrix.cibw_arch }}
|
||||
path: ./wheelhouse/*.whl
|
||||
|
||||
- name: Upload fribidi.dll
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fribidi-windows-${{ matrix.cibw_arch }}
|
||||
path: winbuild\build\bin\fribidi*
|
||||
|
||||
sdist:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.x"
|
||||
cache: pip
|
||||
cache-dependency-path: "Makefile"
|
||||
|
||||
- run: make sdist
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dist-sdist
|
||||
path: dist/*.tar.gz
|
||||
|
||||
pypi-publish:
|
||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
|
||||
needs: [build-1-QEMU-emulated-wheels, build-2-native-wheels, windows, sdist]
|
||||
runs-on: ubuntu-latest
|
||||
name: Upload release to PyPI
|
||||
environment:
|
||||
name: release-pypi
|
||||
url: https://pypi.org/p/Pillow
|
||||
permissions:
|
||||
id-token: write
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: dist-*
|
||||
path: dist
|
||||
merge-multiple: true
|
||||
- name: Publish to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
|
|
188
.gitignore
vendored
188
.gitignore
vendored
|
@ -1,94 +1,94 @@
|
|||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.eggs/
|
||||
.Python
|
||||
env/
|
||||
bin/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.cache
|
||||
.pytest_cache
|
||||
coverage.xml
|
||||
|
||||
# Test files
|
||||
test_images
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
|
||||
# Mr Developer
|
||||
.mr.developer.cfg
|
||||
.project
|
||||
.pydevproject
|
||||
|
||||
# Rope
|
||||
.ropeproject
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
*.pot
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# viewdoc output
|
||||
.long-description.html
|
||||
|
||||
# Vim cruft
|
||||
.*.swp
|
||||
|
||||
#emacs
|
||||
*~
|
||||
\#*#
|
||||
.#*
|
||||
|
||||
#VS Code
|
||||
.vscode
|
||||
|
||||
#Komodo
|
||||
*.komodoproject
|
||||
|
||||
#OS
|
||||
.DS_Store
|
||||
|
||||
# JetBrains
|
||||
.idea
|
||||
|
||||
# Extra test images installed from python-pillow/test-images
|
||||
Tests/images/README.md
|
||||
Tests/images/crash_1.tif
|
||||
Tests/images/crash_2.tif
|
||||
Tests/images/crash-81154a65438ba5aaeca73fd502fa4850fbde60f8.tif
|
||||
Tests/images/string_dimension.tiff
|
||||
Tests/images/jpeg2000
|
||||
Tests/images/msp
|
||||
Tests/images/picins
|
||||
Tests/images/sunraster
|
||||
|
||||
# pyinstaller
|
||||
*.spec
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.eggs/
|
||||
.Python
|
||||
env/
|
||||
bin/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.cache
|
||||
.pytest_cache
|
||||
coverage.xml
|
||||
|
||||
# Test files
|
||||
test_images
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
|
||||
# Mr Developer
|
||||
.mr.developer.cfg
|
||||
.project
|
||||
.pydevproject
|
||||
|
||||
# Rope
|
||||
.ropeproject
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
*.pot
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# viewdoc output
|
||||
.long-description.html
|
||||
|
||||
# Vim cruft
|
||||
.*.swp
|
||||
|
||||
#emacs
|
||||
*~
|
||||
\#*#
|
||||
.#*
|
||||
|
||||
#VS Code
|
||||
.vscode
|
||||
|
||||
#Komodo
|
||||
*.komodoproject
|
||||
|
||||
#OS
|
||||
.DS_Store
|
||||
|
||||
# JetBrains
|
||||
.idea
|
||||
|
||||
# Extra test images installed from python-pillow/test-images
|
||||
Tests/images/README.md
|
||||
Tests/images/crash_1.tif
|
||||
Tests/images/crash_2.tif
|
||||
Tests/images/crash-81154a65438ba5aaeca73fd502fa4850fbde60f8.tif
|
||||
Tests/images/string_dimension.tiff
|
||||
Tests/images/jpeg2000
|
||||
Tests/images/msp
|
||||
Tests/images/picins
|
||||
Tests/images/sunraster
|
||||
|
||||
# pyinstaller
|
||||
*.spec
|
||||
|
|
6
.gitmodules
vendored
6
.gitmodules
vendored
|
@ -1,3 +1,3 @@
|
|||
[submodule "multibuild"]
|
||||
path = wheels/multibuild
|
||||
url = https://github.com/multi-build/multibuild.git
|
||||
[submodule "multibuild"]
|
||||
path = wheels/multibuild
|
||||
url = https://github.com/multi-build/multibuild.git
|
||||
|
|
|
@ -1,85 +1,85 @@
|
|||
repos:
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.4.7
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: [--exit-non-zero-on-fix]
|
||||
|
||||
- repo: https://github.com/psf/black-pre-commit-mirror
|
||||
rev: 24.4.2
|
||||
hooks:
|
||||
- id: black
|
||||
|
||||
- repo: https://github.com/PyCQA/bandit
|
||||
rev: 1.7.8
|
||||
hooks:
|
||||
- id: bandit
|
||||
args: [--severity-level=high]
|
||||
files: ^src/
|
||||
|
||||
- repo: https://github.com/Lucas-C/pre-commit-hooks
|
||||
rev: v1.5.5
|
||||
hooks:
|
||||
- id: remove-tabs
|
||||
exclude: (Makefile$|\.bat$|\.cmake$|\.eps$|\.fits$|\.gd$|\.opt$)
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: v18.1.5
|
||||
hooks:
|
||||
- id: clang-format
|
||||
types: [c]
|
||||
exclude: ^src/thirdparty/
|
||||
|
||||
- repo: https://github.com/pre-commit/pygrep-hooks
|
||||
rev: v1.10.0
|
||||
hooks:
|
||||
- id: rst-backticks
|
||||
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.6.0
|
||||
hooks:
|
||||
- id: check-executables-have-shebangs
|
||||
- id: check-shebang-scripts-are-executable
|
||||
- id: check-merge-conflict
|
||||
- id: check-json
|
||||
- id: check-toml
|
||||
- id: check-yaml
|
||||
- id: end-of-file-fixer
|
||||
exclude: ^Tests/images/
|
||||
- id: trailing-whitespace
|
||||
exclude: ^.github/.*TEMPLATE|^Tests/(fonts|images)/
|
||||
|
||||
- repo: https://github.com/python-jsonschema/check-jsonschema
|
||||
rev: 0.28.4
|
||||
hooks:
|
||||
- id: check-github-workflows
|
||||
- id: check-readthedocs
|
||||
- id: check-renovate
|
||||
|
||||
- repo: https://github.com/sphinx-contrib/sphinx-lint
|
||||
rev: v0.9.1
|
||||
hooks:
|
||||
- id: sphinx-lint
|
||||
|
||||
- repo: https://github.com/tox-dev/pyproject-fmt
|
||||
rev: 1.8.0
|
||||
hooks:
|
||||
- id: pyproject-fmt
|
||||
|
||||
- repo: https://github.com/abravalheri/validate-pyproject
|
||||
rev: v0.18
|
||||
hooks:
|
||||
- id: validate-pyproject
|
||||
|
||||
- repo: https://github.com/tox-dev/tox-ini-fmt
|
||||
rev: 1.3.1
|
||||
hooks:
|
||||
- id: tox-ini-fmt
|
||||
|
||||
- repo: meta
|
||||
hooks:
|
||||
- id: check-hooks-apply
|
||||
- id: check-useless-excludes
|
||||
|
||||
ci:
|
||||
autoupdate_schedule: monthly
|
||||
repos:
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.4.7
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: [--exit-non-zero-on-fix]
|
||||
|
||||
- repo: https://github.com/psf/black-pre-commit-mirror
|
||||
rev: 24.4.2
|
||||
hooks:
|
||||
- id: black
|
||||
|
||||
- repo: https://github.com/PyCQA/bandit
|
||||
rev: 1.7.8
|
||||
hooks:
|
||||
- id: bandit
|
||||
args: [--severity-level=high]
|
||||
files: ^src/
|
||||
|
||||
- repo: https://github.com/Lucas-C/pre-commit-hooks
|
||||
rev: v1.5.5
|
||||
hooks:
|
||||
- id: remove-tabs
|
||||
exclude: (Makefile$|\.bat$|\.cmake$|\.eps$|\.fits$|\.gd$|\.opt$)
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: v18.1.5
|
||||
hooks:
|
||||
- id: clang-format
|
||||
types: [c]
|
||||
exclude: ^src/thirdparty/
|
||||
|
||||
- repo: https://github.com/pre-commit/pygrep-hooks
|
||||
rev: v1.10.0
|
||||
hooks:
|
||||
- id: rst-backticks
|
||||
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.6.0
|
||||
hooks:
|
||||
- id: check-executables-have-shebangs
|
||||
- id: check-shebang-scripts-are-executable
|
||||
- id: check-merge-conflict
|
||||
- id: check-json
|
||||
- id: check-toml
|
||||
- id: check-yaml
|
||||
- id: end-of-file-fixer
|
||||
exclude: ^Tests/images/
|
||||
- id: trailing-whitespace
|
||||
exclude: ^.github/.*TEMPLATE|^Tests/(fonts|images)/
|
||||
|
||||
- repo: https://github.com/python-jsonschema/check-jsonschema
|
||||
rev: 0.28.4
|
||||
hooks:
|
||||
- id: check-github-workflows
|
||||
- id: check-readthedocs
|
||||
- id: check-renovate
|
||||
|
||||
- repo: https://github.com/sphinx-contrib/sphinx-lint
|
||||
rev: v0.9.1
|
||||
hooks:
|
||||
- id: sphinx-lint
|
||||
|
||||
- repo: https://github.com/tox-dev/pyproject-fmt
|
||||
rev: 1.8.0
|
||||
hooks:
|
||||
- id: pyproject-fmt
|
||||
|
||||
- repo: https://github.com/abravalheri/validate-pyproject
|
||||
rev: v0.18
|
||||
hooks:
|
||||
- id: validate-pyproject
|
||||
|
||||
- repo: https://github.com/tox-dev/tox-ini-fmt
|
||||
rev: 1.3.1
|
||||
hooks:
|
||||
- id: tox-ini-fmt
|
||||
|
||||
- repo: meta
|
||||
hooks:
|
||||
- id: check-hooks-apply
|
||||
- id: check-useless-excludes
|
||||
|
||||
ci:
|
||||
autoupdate_schedule: monthly
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
version: 2
|
||||
|
||||
formats: [pdf]
|
||||
|
||||
build:
|
||||
os: ubuntu-lts-latest
|
||||
tools:
|
||||
python: "3"
|
||||
jobs:
|
||||
post_checkout:
|
||||
- git remote add upstream https://github.com/python-pillow/Pillow.git # For forks
|
||||
- git fetch upstream --tags
|
||||
|
||||
python:
|
||||
install:
|
||||
- method: pip
|
||||
path: .
|
||||
extra_requirements:
|
||||
- docs
|
||||
version: 2
|
||||
|
||||
formats: [pdf]
|
||||
|
||||
build:
|
||||
os: ubuntu-lts-latest
|
||||
tools:
|
||||
python: "3"
|
||||
jobs:
|
||||
post_checkout:
|
||||
- git remote add upstream https://github.com/python-pillow/Pillow.git # For forks
|
||||
- git fetch upstream --tags
|
||||
|
||||
python:
|
||||
install:
|
||||
- method: pip
|
||||
path: .
|
||||
extra_requirements:
|
||||
- docs
|
||||
|
|
15296
CHANGES.rst
15296
CHANGES.rst
File diff suppressed because it is too large
Load Diff
60
LICENSE
60
LICENSE
|
@ -1,30 +1,30 @@
|
|||
The Python Imaging Library (PIL) is
|
||||
|
||||
Copyright © 1997-2011 by Secret Labs AB
|
||||
Copyright © 1995-2011 by Fredrik Lundh and contributors
|
||||
|
||||
Pillow is the friendly PIL fork. It is
|
||||
|
||||
Copyright © 2010-2024 by Jeffrey A. Clark and contributors
|
||||
|
||||
Like PIL, Pillow is licensed under the open source HPND License:
|
||||
|
||||
By obtaining, using, and/or copying this software and/or its associated
|
||||
documentation, you agree that you have read, understood, and will comply
|
||||
with the following terms and conditions:
|
||||
|
||||
Permission to use, copy, modify and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted,
|
||||
provided that the above copyright notice appears in all copies, and that
|
||||
both that copyright notice and this permission notice appear in supporting
|
||||
documentation, and that the name of Secret Labs AB or the author not be
|
||||
used in advertising or publicity pertaining to distribution of the software
|
||||
without specific, written prior permission.
|
||||
|
||||
SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
|
||||
IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE FOR ANY SPECIAL,
|
||||
INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
The Python Imaging Library (PIL) is
|
||||
|
||||
Copyright © 1997-2011 by Secret Labs AB
|
||||
Copyright © 1995-2011 by Fredrik Lundh and contributors
|
||||
|
||||
Pillow is the friendly PIL fork. It is
|
||||
|
||||
Copyright © 2010-2024 by Jeffrey A. Clark and contributors
|
||||
|
||||
Like PIL, Pillow is licensed under the open source HPND License:
|
||||
|
||||
By obtaining, using, and/or copying this software and/or its associated
|
||||
documentation, you agree that you have read, understood, and will comply
|
||||
with the following terms and conditions:
|
||||
|
||||
Permission to use, copy, modify and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted,
|
||||
provided that the above copyright notice appears in all copies, and that
|
||||
both that copyright notice and this permission notice appear in supporting
|
||||
documentation, and that the name of Secret Labs AB or the author not be
|
||||
used in advertising or publicity pertaining to distribution of the software
|
||||
without specific, written prior permission.
|
||||
|
||||
SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
|
||||
IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE FOR ANY SPECIAL,
|
||||
INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
|
|
68
MANIFEST.in
68
MANIFEST.in
|
@ -1,34 +1,34 @@
|
|||
include *.c
|
||||
include *.h
|
||||
include *.in
|
||||
include *.md
|
||||
include *.py
|
||||
include *.rst
|
||||
include *.sh
|
||||
include *.toml
|
||||
include *.txt
|
||||
include *.yaml
|
||||
include .flake8
|
||||
include LICENSE
|
||||
include Makefile
|
||||
include tox.ini
|
||||
graft Tests
|
||||
graft src
|
||||
graft depends
|
||||
graft winbuild
|
||||
graft docs
|
||||
graft _custom_build
|
||||
|
||||
# build/src control detritus
|
||||
exclude .appveyor.yml
|
||||
exclude .clang-format
|
||||
exclude .coveragerc
|
||||
exclude .editorconfig
|
||||
exclude .readthedocs.yml
|
||||
exclude codecov.yml
|
||||
exclude renovate.json
|
||||
global-exclude .git*
|
||||
global-exclude *.pyc
|
||||
global-exclude *.so
|
||||
prune .ci
|
||||
prune wheels
|
||||
include *.c
|
||||
include *.h
|
||||
include *.in
|
||||
include *.md
|
||||
include *.py
|
||||
include *.rst
|
||||
include *.sh
|
||||
include *.toml
|
||||
include *.txt
|
||||
include *.yaml
|
||||
include .flake8
|
||||
include LICENSE
|
||||
include Makefile
|
||||
include tox.ini
|
||||
graft Tests
|
||||
graft src
|
||||
graft depends
|
||||
graft winbuild
|
||||
graft docs
|
||||
graft _custom_build
|
||||
|
||||
# build/src control detritus
|
||||
exclude .appveyor.yml
|
||||
exclude .clang-format
|
||||
exclude .coveragerc
|
||||
exclude .editorconfig
|
||||
exclude .readthedocs.yml
|
||||
exclude codecov.yml
|
||||
exclude renovate.json
|
||||
global-exclude .git*
|
||||
global-exclude *.pyc
|
||||
global-exclude *.so
|
||||
prune .ci
|
||||
prune wheels
|
||||
|
|
250
Makefile
250
Makefile
|
@ -1,125 +1,125 @@
|
|||
.DEFAULT_GOAL := help
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm src/PIL/*.so || true
|
||||
rm -r build || true
|
||||
find . -name __pycache__ | xargs rm -r || true
|
||||
|
||||
.PHONY: coverage
|
||||
coverage:
|
||||
python3 -c "import pytest" > /dev/null 2>&1 || python3 -m pip install pytest
|
||||
python3 -m pytest -qq
|
||||
rm -r htmlcov || true
|
||||
python3 -c "import coverage" > /dev/null 2>&1 || python3 -m pip install coverage
|
||||
python3 -m coverage report
|
||||
|
||||
.PHONY: doc
|
||||
.PHONY: html
|
||||
doc html:
|
||||
python3 -c "import PIL" > /dev/null 2>&1 || python3 -m pip install .
|
||||
$(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
|
||||
doccheck:
|
||||
$(MAKE) doc
|
||||
# Don't make our tests rely on the links in the docs being up every single build.
|
||||
# We don't control them. But do check, and update them to the target of their redirects.
|
||||
$(MAKE) -C docs linkcheck || true
|
||||
|
||||
.PHONY: docserve
|
||||
docserve:
|
||||
cd docs/_build/html && python3 -m http.server 2> /dev/null&
|
||||
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo "Welcome to Pillow development. Please use \`make <target>\` where <target> is one of"
|
||||
@echo " clean remove build products"
|
||||
@echo " coverage run coverage test (in progress)"
|
||||
@echo " doc make HTML docs"
|
||||
@echo " docserve run an HTTP server on the docs directory"
|
||||
@echo " html make HTML docs"
|
||||
@echo " htmlview open the index page built by the html target in your browser"
|
||||
@echo " install make and install"
|
||||
@echo " install-coverage make and install with C coverage"
|
||||
@echo " lint run the lint checks"
|
||||
@echo " lint-fix run Ruff to (mostly) fix lint issues"
|
||||
@echo " release-test run code and package tests before release"
|
||||
@echo " test run tests on installed Pillow"
|
||||
|
||||
.PHONY: install
|
||||
install:
|
||||
python3 -m pip -v install .
|
||||
python3 selftest.py
|
||||
|
||||
.PHONY: install-coverage
|
||||
install-coverage:
|
||||
CFLAGS="-coverage -Werror=implicit-function-declaration" python3 -m pip -v install .
|
||||
python3 selftest.py
|
||||
|
||||
.PHONY: debug
|
||||
debug:
|
||||
# make a debug version if we don't have a -dbg python. Leaves in symbols
|
||||
# for our stuff, kills optimization, and redirects to dev null so we
|
||||
# see any build failures.
|
||||
make clean > /dev/null
|
||||
CFLAGS='-g -O0' python3 -m pip -v install . > /dev/null
|
||||
|
||||
.PHONY: release-test
|
||||
release-test:
|
||||
python3 Tests/check_release_notes.py
|
||||
python3 -m pip install -e .[tests]
|
||||
python3 selftest.py
|
||||
python3 -m pytest Tests
|
||||
python3 -m pip install .
|
||||
python3 -m pytest -qq
|
||||
python3 -m check_manifest
|
||||
python3 -m pyroma .
|
||||
$(MAKE) readme
|
||||
|
||||
.PHONY: sdist
|
||||
sdist:
|
||||
python3 -m build --help > /dev/null 2>&1 || python3 -m pip install build
|
||||
python3 -m build --sdist
|
||||
python3 -m twine --help > /dev/null 2>&1 || python3 -m pip install twine
|
||||
python3 -m twine check --strict dist/*
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
python3 -c "import pytest" > /dev/null 2>&1 || python3 -m pip install pytest
|
||||
python3 -m pytest -qq
|
||||
|
||||
.PHONY: valgrind
|
||||
valgrind:
|
||||
python3 -c "import pytest_valgrind" > /dev/null 2>&1 || python3 -m pip install pytest-valgrind
|
||||
PYTHONMALLOC=malloc valgrind --suppressions=Tests/oss-fuzz/python.supp --leak-check=no \
|
||||
--log-file=/tmp/valgrind-output \
|
||||
python3 -m pytest --no-memcheck -vv --valgrind --valgrind-log=/tmp/valgrind-output
|
||||
|
||||
.PHONY: readme
|
||||
readme:
|
||||
python3 -c "import markdown2" > /dev/null 2>&1 || python3 -m pip install markdown2
|
||||
python3 -m markdown2 README.md > .long-description.html && open .long-description.html
|
||||
|
||||
|
||||
.PHONY: lint
|
||||
lint:
|
||||
python3 -c "import tox" > /dev/null 2>&1 || python3 -m pip install tox
|
||||
python3 -m tox -e lint
|
||||
|
||||
.PHONY: lint-fix
|
||||
lint-fix:
|
||||
python3 -c "import black" > /dev/null 2>&1 || python3 -m pip install black
|
||||
python3 -m black .
|
||||
python3 -c "import ruff" > /dev/null 2>&1 || python3 -m pip install ruff
|
||||
python3 -m ruff --fix .
|
||||
|
||||
.PHONY: mypy
|
||||
mypy:
|
||||
python3 -c "import tox" > /dev/null 2>&1 || python3 -m pip install tox
|
||||
python3 -m tox -e mypy
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm src/PIL/*.so || true
|
||||
rm -r build || true
|
||||
find . -name __pycache__ | xargs rm -r || true
|
||||
|
||||
.PHONY: coverage
|
||||
coverage:
|
||||
python3 -c "import pytest" > /dev/null 2>&1 || python3 -m pip install pytest
|
||||
python3 -m pytest -qq
|
||||
rm -r htmlcov || true
|
||||
python3 -c "import coverage" > /dev/null 2>&1 || python3 -m pip install coverage
|
||||
python3 -m coverage report
|
||||
|
||||
.PHONY: doc
|
||||
.PHONY: html
|
||||
doc html:
|
||||
python3 -c "import PIL" > /dev/null 2>&1 || python3 -m pip install .
|
||||
$(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
|
||||
doccheck:
|
||||
$(MAKE) doc
|
||||
# Don't make our tests rely on the links in the docs being up every single build.
|
||||
# We don't control them. But do check, and update them to the target of their redirects.
|
||||
$(MAKE) -C docs linkcheck || true
|
||||
|
||||
.PHONY: docserve
|
||||
docserve:
|
||||
cd docs/_build/html && python3 -m http.server 2> /dev/null&
|
||||
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo "Welcome to Pillow development. Please use \`make <target>\` where <target> is one of"
|
||||
@echo " clean remove build products"
|
||||
@echo " coverage run coverage test (in progress)"
|
||||
@echo " doc make HTML docs"
|
||||
@echo " docserve run an HTTP server on the docs directory"
|
||||
@echo " html make HTML docs"
|
||||
@echo " htmlview open the index page built by the html target in your browser"
|
||||
@echo " install make and install"
|
||||
@echo " install-coverage make and install with C coverage"
|
||||
@echo " lint run the lint checks"
|
||||
@echo " lint-fix run Ruff to (mostly) fix lint issues"
|
||||
@echo " release-test run code and package tests before release"
|
||||
@echo " test run tests on installed Pillow"
|
||||
|
||||
.PHONY: install
|
||||
install:
|
||||
python3 -m pip -v install .
|
||||
python3 selftest.py
|
||||
|
||||
.PHONY: install-coverage
|
||||
install-coverage:
|
||||
CFLAGS="-coverage -Werror=implicit-function-declaration" python3 -m pip -v install .
|
||||
python3 selftest.py
|
||||
|
||||
.PHONY: debug
|
||||
debug:
|
||||
# make a debug version if we don't have a -dbg python. Leaves in symbols
|
||||
# for our stuff, kills optimization, and redirects to dev null so we
|
||||
# see any build failures.
|
||||
make clean > /dev/null
|
||||
CFLAGS='-g -O0' python3 -m pip -v install . > /dev/null
|
||||
|
||||
.PHONY: release-test
|
||||
release-test:
|
||||
python3 Tests/check_release_notes.py
|
||||
python3 -m pip install -e .[tests]
|
||||
python3 selftest.py
|
||||
python3 -m pytest Tests
|
||||
python3 -m pip install .
|
||||
python3 -m pytest -qq
|
||||
python3 -m check_manifest
|
||||
python3 -m pyroma .
|
||||
$(MAKE) readme
|
||||
|
||||
.PHONY: sdist
|
||||
sdist:
|
||||
python3 -m build --help > /dev/null 2>&1 || python3 -m pip install build
|
||||
python3 -m build --sdist
|
||||
python3 -m twine --help > /dev/null 2>&1 || python3 -m pip install twine
|
||||
python3 -m twine check --strict dist/*
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
python3 -c "import pytest" > /dev/null 2>&1 || python3 -m pip install pytest
|
||||
python3 -m pytest -qq
|
||||
|
||||
.PHONY: valgrind
|
||||
valgrind:
|
||||
python3 -c "import pytest_valgrind" > /dev/null 2>&1 || python3 -m pip install pytest-valgrind
|
||||
PYTHONMALLOC=malloc valgrind --suppressions=Tests/oss-fuzz/python.supp --leak-check=no \
|
||||
--log-file=/tmp/valgrind-output \
|
||||
python3 -m pytest --no-memcheck -vv --valgrind --valgrind-log=/tmp/valgrind-output
|
||||
|
||||
.PHONY: readme
|
||||
readme:
|
||||
python3 -c "import markdown2" > /dev/null 2>&1 || python3 -m pip install markdown2
|
||||
python3 -m markdown2 README.md > .long-description.html && open .long-description.html
|
||||
|
||||
|
||||
.PHONY: lint
|
||||
lint:
|
||||
python3 -c "import tox" > /dev/null 2>&1 || python3 -m pip install tox
|
||||
python3 -m tox -e lint
|
||||
|
||||
.PHONY: lint-fix
|
||||
lint-fix:
|
||||
python3 -c "import black" > /dev/null 2>&1 || python3 -m pip install black
|
||||
python3 -m black .
|
||||
python3 -c "import ruff" > /dev/null 2>&1 || python3 -m pip install ruff
|
||||
python3 -m ruff --fix .
|
||||
|
||||
.PHONY: mypy
|
||||
mypy:
|
||||
python3 -c "import tox" > /dev/null 2>&1 || python3 -m pip install tox
|
||||
python3 -m tox -e mypy
|
||||
|
|
230
README.md
230
README.md
|
@ -1,115 +1,115 @@
|
|||
<p align="center">
|
||||
<img width="248" height="250" src="https://raw.githubusercontent.com/python-pillow/pillow-logo/main/pillow-logo-248x250.png" alt="Pillow logo">
|
||||
</p>
|
||||
|
||||
# Pillow
|
||||
|
||||
## Python Imaging Library (Fork)
|
||||
|
||||
Pillow is the friendly PIL fork by [Jeffrey A. Clark and
|
||||
contributors](https://github.com/python-pillow/Pillow/graphs/contributors).
|
||||
PIL is the Python Imaging Library by Fredrik Lundh and contributors.
|
||||
As of 2019, Pillow development is
|
||||
[supported by Tidelift](https://tidelift.com/subscription/pkg/pypi-pillow?utm_source=pypi-pillow&utm_medium=readme&utm_campaign=enterprise).
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>docs</th>
|
||||
<td>
|
||||
<a href="https://pillow.readthedocs.io/?badge=latest"><img
|
||||
alt="Documentation Status"
|
||||
src="https://readthedocs.org/projects/pillow/badge/?version=latest"></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>tests</th>
|
||||
<td>
|
||||
<a href="https://github.com/python-pillow/Pillow/actions/workflows/lint.yml"><img
|
||||
alt="GitHub Actions build status (Lint)"
|
||||
src="https://github.com/python-pillow/Pillow/workflows/Lint/badge.svg"></a>
|
||||
<a href="https://github.com/python-pillow/Pillow/actions/workflows/test.yml"><img
|
||||
alt="GitHub Actions build status (Test Linux and macOS)"
|
||||
src="https://github.com/python-pillow/Pillow/workflows/Test/badge.svg"></a>
|
||||
<a href="https://github.com/python-pillow/Pillow/actions/workflows/test-windows.yml"><img
|
||||
alt="GitHub Actions build status (Test Windows)"
|
||||
src="https://github.com/python-pillow/Pillow/workflows/Test%20Windows/badge.svg"></a>
|
||||
<a href="https://github.com/python-pillow/Pillow/actions/workflows/test-mingw.yml"><img
|
||||
alt="GitHub Actions build status (Test MinGW)"
|
||||
src="https://github.com/python-pillow/Pillow/workflows/Test%20MinGW/badge.svg"></a>
|
||||
<a href="https://github.com/python-pillow/Pillow/actions/workflows/test-cygwin.yml"><img
|
||||
alt="GitHub Actions build status (Test Cygwin)"
|
||||
src="https://github.com/python-pillow/Pillow/workflows/Test%20Cygwin/badge.svg"></a>
|
||||
<a href="https://github.com/python-pillow/Pillow/actions/workflows/test-docker.yml"><img
|
||||
alt="GitHub Actions build status (Test Docker)"
|
||||
src="https://github.com/python-pillow/Pillow/workflows/Test%20Docker/badge.svg"></a>
|
||||
<a href="https://ci.appveyor.com/project/python-pillow/Pillow"><img
|
||||
alt="AppVeyor CI build status (Windows)"
|
||||
src="https://img.shields.io/appveyor/build/python-pillow/Pillow/main.svg?label=Windows%20build"></a>
|
||||
<a href="https://github.com/python-pillow/Pillow/actions/workflows/wheels.yml"><img
|
||||
alt="GitHub Actions build status (Wheels)"
|
||||
src="https://github.com/python-pillow/Pillow/workflows/Wheels/badge.svg"></a>
|
||||
<a href="https://app.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://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:pillow"><img
|
||||
alt="Fuzzing Status"
|
||||
src="https://oss-fuzz-build-logs.storage.googleapis.com/badges/pillow.svg"></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>package</th>
|
||||
<td>
|
||||
<a href="https://zenodo.org/badge/latestdoi/17549/python-pillow/Pillow"><img
|
||||
alt="Zenodo"
|
||||
src="https://zenodo.org/badge/17549/python-pillow/Pillow.svg"></a>
|
||||
<a href="https://tidelift.com/subscription/pkg/pypi-pillow?utm_source=pypi-pillow&utm_medium=badge"><img
|
||||
alt="Tidelift"
|
||||
src="https://tidelift.com/badges/package/pypi/pillow?style=flat"></a>
|
||||
<a href="https://pypi.org/project/pillow/"><img
|
||||
alt="Newest PyPI version"
|
||||
src="https://img.shields.io/pypi/v/pillow.svg"></a>
|
||||
<a href="https://pypi.org/project/pillow/"><img
|
||||
alt="Number of PyPI downloads"
|
||||
src="https://img.shields.io/pypi/dm/pillow.svg"></a>
|
||||
<a href="https://www.bestpractices.dev/projects/6331"><img
|
||||
alt="OpenSSF Best Practices"
|
||||
src="https://www.bestpractices.dev/projects/6331/badge"></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>social</th>
|
||||
<td>
|
||||
<a href="https://gitter.im/python-pillow/Pillow?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"><img
|
||||
alt="Join the chat at https://gitter.im/python-pillow/Pillow"
|
||||
src="https://badges.gitter.im/python-pillow/Pillow.svg"></a>
|
||||
<a href="https://fosstodon.org/@pillow"><img
|
||||
alt="Follow on https://fosstodon.org/@pillow"
|
||||
src="https://img.shields.io/badge/publish-on%20Mastodon-595aff.svg"
|
||||
rel="me"></a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## Overview
|
||||
|
||||
The Python Imaging Library adds image processing capabilities to your Python interpreter.
|
||||
|
||||
This library provides extensive file format support, an efficient internal representation, and fairly powerful image processing capabilities.
|
||||
|
||||
The core image library is designed for fast access to data stored in a few basic pixel formats. It should provide a solid foundation for a general image processing tool.
|
||||
|
||||
## More Information
|
||||
|
||||
- [Documentation](https://pillow.readthedocs.io/)
|
||||
- [Installation](https://pillow.readthedocs.io/en/latest/installation/basic-installation.html)
|
||||
- [Handbook](https://pillow.readthedocs.io/en/latest/handbook/index.html)
|
||||
- [Contribute](https://github.com/python-pillow/Pillow/blob/main/.github/CONTRIBUTING.md)
|
||||
- [Issues](https://github.com/python-pillow/Pillow/issues)
|
||||
- [Pull requests](https://github.com/python-pillow/Pillow/pulls)
|
||||
- [Release notes](https://pillow.readthedocs.io/en/stable/releasenotes/index.html)
|
||||
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
|
||||
- [Pre-fork](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst#pre-fork)
|
||||
|
||||
## Report a Vulnerability
|
||||
|
||||
To report a security vulnerability, please follow the procedure described in the [Tidelift security policy](https://tidelift.com/docs/security).
|
||||
<p align="center">
|
||||
<img width="248" height="250" src="https://raw.githubusercontent.com/python-pillow/pillow-logo/main/pillow-logo-248x250.png" alt="Pillow logo">
|
||||
</p>
|
||||
|
||||
# Pillow
|
||||
|
||||
## Python Imaging Library (Fork)
|
||||
|
||||
Pillow is the friendly PIL fork by [Jeffrey A. Clark and
|
||||
contributors](https://github.com/python-pillow/Pillow/graphs/contributors).
|
||||
PIL is the Python Imaging Library by Fredrik Lundh and contributors.
|
||||
As of 2019, Pillow development is
|
||||
[supported by Tidelift](https://tidelift.com/subscription/pkg/pypi-pillow?utm_source=pypi-pillow&utm_medium=readme&utm_campaign=enterprise).
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>docs</th>
|
||||
<td>
|
||||
<a href="https://pillow.readthedocs.io/?badge=latest"><img
|
||||
alt="Documentation Status"
|
||||
src="https://readthedocs.org/projects/pillow/badge/?version=latest"></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>tests</th>
|
||||
<td>
|
||||
<a href="https://github.com/python-pillow/Pillow/actions/workflows/lint.yml"><img
|
||||
alt="GitHub Actions build status (Lint)"
|
||||
src="https://github.com/python-pillow/Pillow/workflows/Lint/badge.svg"></a>
|
||||
<a href="https://github.com/python-pillow/Pillow/actions/workflows/test.yml"><img
|
||||
alt="GitHub Actions build status (Test Linux and macOS)"
|
||||
src="https://github.com/python-pillow/Pillow/workflows/Test/badge.svg"></a>
|
||||
<a href="https://github.com/python-pillow/Pillow/actions/workflows/test-windows.yml"><img
|
||||
alt="GitHub Actions build status (Test Windows)"
|
||||
src="https://github.com/python-pillow/Pillow/workflows/Test%20Windows/badge.svg"></a>
|
||||
<a href="https://github.com/python-pillow/Pillow/actions/workflows/test-mingw.yml"><img
|
||||
alt="GitHub Actions build status (Test MinGW)"
|
||||
src="https://github.com/python-pillow/Pillow/workflows/Test%20MinGW/badge.svg"></a>
|
||||
<a href="https://github.com/python-pillow/Pillow/actions/workflows/test-cygwin.yml"><img
|
||||
alt="GitHub Actions build status (Test Cygwin)"
|
||||
src="https://github.com/python-pillow/Pillow/workflows/Test%20Cygwin/badge.svg"></a>
|
||||
<a href="https://github.com/python-pillow/Pillow/actions/workflows/test-docker.yml"><img
|
||||
alt="GitHub Actions build status (Test Docker)"
|
||||
src="https://github.com/python-pillow/Pillow/workflows/Test%20Docker/badge.svg"></a>
|
||||
<a href="https://ci.appveyor.com/project/python-pillow/Pillow"><img
|
||||
alt="AppVeyor CI build status (Windows)"
|
||||
src="https://img.shields.io/appveyor/build/python-pillow/Pillow/main.svg?label=Windows%20build"></a>
|
||||
<a href="https://github.com/python-pillow/Pillow/actions/workflows/wheels.yml"><img
|
||||
alt="GitHub Actions build status (Wheels)"
|
||||
src="https://github.com/python-pillow/Pillow/workflows/Wheels/badge.svg"></a>
|
||||
<a href="https://app.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://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:pillow"><img
|
||||
alt="Fuzzing Status"
|
||||
src="https://oss-fuzz-build-logs.storage.googleapis.com/badges/pillow.svg"></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>package</th>
|
||||
<td>
|
||||
<a href="https://zenodo.org/badge/latestdoi/17549/python-pillow/Pillow"><img
|
||||
alt="Zenodo"
|
||||
src="https://zenodo.org/badge/17549/python-pillow/Pillow.svg"></a>
|
||||
<a href="https://tidelift.com/subscription/pkg/pypi-pillow?utm_source=pypi-pillow&utm_medium=badge"><img
|
||||
alt="Tidelift"
|
||||
src="https://tidelift.com/badges/package/pypi/pillow?style=flat"></a>
|
||||
<a href="https://pypi.org/project/pillow/"><img
|
||||
alt="Newest PyPI version"
|
||||
src="https://img.shields.io/pypi/v/pillow.svg"></a>
|
||||
<a href="https://pypi.org/project/pillow/"><img
|
||||
alt="Number of PyPI downloads"
|
||||
src="https://img.shields.io/pypi/dm/pillow.svg"></a>
|
||||
<a href="https://www.bestpractices.dev/projects/6331"><img
|
||||
alt="OpenSSF Best Practices"
|
||||
src="https://www.bestpractices.dev/projects/6331/badge"></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>social</th>
|
||||
<td>
|
||||
<a href="https://gitter.im/python-pillow/Pillow?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"><img
|
||||
alt="Join the chat at https://gitter.im/python-pillow/Pillow"
|
||||
src="https://badges.gitter.im/python-pillow/Pillow.svg"></a>
|
||||
<a href="https://fosstodon.org/@pillow"><img
|
||||
alt="Follow on https://fosstodon.org/@pillow"
|
||||
src="https://img.shields.io/badge/publish-on%20Mastodon-595aff.svg"
|
||||
rel="me"></a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## Overview
|
||||
|
||||
The Python Imaging Library adds image processing capabilities to your Python interpreter.
|
||||
|
||||
This library provides extensive file format support, an efficient internal representation, and fairly powerful image processing capabilities.
|
||||
|
||||
The core image library is designed for fast access to data stored in a few basic pixel formats. It should provide a solid foundation for a general image processing tool.
|
||||
|
||||
## More Information
|
||||
|
||||
- [Documentation](https://pillow.readthedocs.io/)
|
||||
- [Installation](https://pillow.readthedocs.io/en/latest/installation/basic-installation.html)
|
||||
- [Handbook](https://pillow.readthedocs.io/en/latest/handbook/index.html)
|
||||
- [Contribute](https://github.com/python-pillow/Pillow/blob/main/.github/CONTRIBUTING.md)
|
||||
- [Issues](https://github.com/python-pillow/Pillow/issues)
|
||||
- [Pull requests](https://github.com/python-pillow/Pillow/pulls)
|
||||
- [Release notes](https://pillow.readthedocs.io/en/stable/releasenotes/index.html)
|
||||
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
|
||||
- [Pre-fork](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst#pre-fork)
|
||||
|
||||
## Report a Vulnerability
|
||||
|
||||
To report a security vulnerability, please follow the procedure described in the [Tidelift security policy](https://tidelift.com/docs/security).
|
||||
|
|
204
RELEASING.md
204
RELEASING.md
|
@ -1,102 +1,102 @@
|
|||
# Release Checklist
|
||||
|
||||
See https://pillow.readthedocs.io/en/stable/releasenotes/versioning.html for
|
||||
information about how the version numbers line up with releases.
|
||||
|
||||
## Main Release
|
||||
|
||||
Released quarterly on January 2nd, April 1st, July 1st and October 15th.
|
||||
|
||||
* [ ] Open a release ticket e.g. https://github.com/python-pillow/Pillow/issues/3154
|
||||
* [ ] Develop and prepare release in `main` branch.
|
||||
* [ ] Check [GitHub Actions](https://github.com/python-pillow/Pillow/actions) and [AppVeyor](https://ci.appveyor.com/project/python-pillow/Pillow) to confirm passing tests in `main` branch.
|
||||
* [ ] Check that all the wheel builds pass the tests in the [GitHub Actions "Wheels" workflow](https://github.com/python-pillow/Pillow/actions/workflows/wheels.yml) jobs by manually triggering them.
|
||||
* [ ] In compliance with [PEP 440](https://peps.python.org/pep-0440/), update version identifier in `src/PIL/_version.py`
|
||||
* [ ] Update `CHANGES.rst`.
|
||||
* [ ] Run pre-release check via `make release-test` in a freshly cloned repo.
|
||||
* [ ] Create branch and tag for release e.g.:
|
||||
```bash
|
||||
git branch 5.2.x
|
||||
git tag 5.2.0
|
||||
git push --tags
|
||||
```
|
||||
* [ ] Check the [GitHub Actions "Wheels" workflow](https://github.com/python-pillow/Pillow/actions/workflows/wheels.yml)
|
||||
has passed, including the "Upload release to PyPI" job. This will have been triggered
|
||||
by the new tag.
|
||||
* [ ] Publish the [release on GitHub](https://github.com/python-pillow/Pillow/releases).
|
||||
* [ ] In compliance with [PEP 440](https://peps.python.org/pep-0440/),
|
||||
increment and append `.dev0` to version identifier in `src/PIL/_version.py` and then:
|
||||
```bash
|
||||
git push --all
|
||||
```
|
||||
## Point Release
|
||||
|
||||
Released as needed for security, installation or critical bug fixes.
|
||||
|
||||
* [ ] Make necessary changes in `main` branch.
|
||||
* [ ] Update `CHANGES.rst`.
|
||||
* [ ] Check out release branch e.g.:
|
||||
```bash
|
||||
git checkout -t remotes/origin/5.2.x
|
||||
```
|
||||
* [ ] Cherry pick individual commits from `main` branch to release branch e.g. `5.2.x`, then `git push`.
|
||||
* [ ] Check [GitHub Actions](https://github.com/python-pillow/Pillow/actions) and [AppVeyor](https://ci.appveyor.com/project/python-pillow/Pillow) to confirm passing tests in release branch e.g. `5.2.x`.
|
||||
* [ ] In compliance with [PEP 440](https://peps.python.org/pep-0440/), update version identifier in `src/PIL/_version.py`
|
||||
* [ ] Run pre-release check via `make release-test`.
|
||||
* [ ] Create tag for release e.g.:
|
||||
```bash
|
||||
git tag 5.2.1
|
||||
git push --tags
|
||||
```
|
||||
* [ ] Create and check source distribution:
|
||||
```bash
|
||||
make sdist
|
||||
```
|
||||
* [ ] Check the [GitHub Actions "Wheels" workflow](https://github.com/python-pillow/Pillow/actions/workflows/wheels.yml)
|
||||
has passed, including the "Upload release to PyPI" job. This will have been triggered
|
||||
by the new tag.
|
||||
* [ ] Publish the [release on GitHub](https://github.com/python-pillow/Pillow/releases) and then:
|
||||
```bash
|
||||
git push
|
||||
```
|
||||
|
||||
## Embargoed Release
|
||||
|
||||
Released as needed privately to individual vendors for critical security-related bug fixes.
|
||||
|
||||
* [ ] Prepare patch for all versions that will get a fix. Test against local installations.
|
||||
* [ ] Commit against `main`, cherry pick to affected release branches.
|
||||
* [ ] Run local test matrix on each release & Python version.
|
||||
* [ ] Privately send to distros.
|
||||
* [ ] Run pre-release check via `make release-test`
|
||||
* [ ] Amend any commits with the CVE #
|
||||
* [ ] On release date, tag and push to GitHub.
|
||||
```bash
|
||||
git checkout 2.5.x
|
||||
git tag 2.5.3
|
||||
git push origin --tags
|
||||
```
|
||||
* [ ] Check the [GitHub Actions "Wheels" workflow](https://github.com/python-pillow/Pillow/actions/workflows/wheels.yml)
|
||||
has passed, including the "Upload release to PyPI" job. This will have been triggered
|
||||
by the new tag.
|
||||
* [ ] Publish the [release on GitHub](https://github.com/python-pillow/Pillow/releases) and then:
|
||||
```bash
|
||||
git push origin 2.5.x
|
||||
```
|
||||
|
||||
## Publicize Release
|
||||
|
||||
* [ ] Announce release availability via [Mastodon](https://fosstodon.org/@pillow) e.g. https://fosstodon.org/@pillow/110639450470725321
|
||||
|
||||
## Documentation
|
||||
|
||||
* [ ] Make sure the [default version for Read the Docs](https://pillow.readthedocs.io/en/stable/) is up-to-date with the release changes
|
||||
|
||||
## Docker Images
|
||||
|
||||
* [ ] Update Pillow in the Docker Images repository
|
||||
```bash
|
||||
git clone https://github.com/python-pillow/docker-images
|
||||
cd docker-images
|
||||
./update-pillow-tag.sh [[release tag]]
|
||||
```
|
||||
# Release Checklist
|
||||
|
||||
See https://pillow.readthedocs.io/en/stable/releasenotes/versioning.html for
|
||||
information about how the version numbers line up with releases.
|
||||
|
||||
## Main Release
|
||||
|
||||
Released quarterly on January 2nd, April 1st, July 1st and October 15th.
|
||||
|
||||
* [ ] Open a release ticket e.g. https://github.com/python-pillow/Pillow/issues/3154
|
||||
* [ ] Develop and prepare release in `main` branch.
|
||||
* [ ] Check [GitHub Actions](https://github.com/python-pillow/Pillow/actions) and [AppVeyor](https://ci.appveyor.com/project/python-pillow/Pillow) to confirm passing tests in `main` branch.
|
||||
* [ ] Check that all the wheel builds pass the tests in the [GitHub Actions "Wheels" workflow](https://github.com/python-pillow/Pillow/actions/workflows/wheels.yml) jobs by manually triggering them.
|
||||
* [ ] In compliance with [PEP 440](https://peps.python.org/pep-0440/), update version identifier in `src/PIL/_version.py`
|
||||
* [ ] Update `CHANGES.rst`.
|
||||
* [ ] Run pre-release check via `make release-test` in a freshly cloned repo.
|
||||
* [ ] Create branch and tag for release e.g.:
|
||||
```bash
|
||||
git branch 5.2.x
|
||||
git tag 5.2.0
|
||||
git push --tags
|
||||
```
|
||||
* [ ] Check the [GitHub Actions "Wheels" workflow](https://github.com/python-pillow/Pillow/actions/workflows/wheels.yml)
|
||||
has passed, including the "Upload release to PyPI" job. This will have been triggered
|
||||
by the new tag.
|
||||
* [ ] Publish the [release on GitHub](https://github.com/python-pillow/Pillow/releases).
|
||||
* [ ] In compliance with [PEP 440](https://peps.python.org/pep-0440/),
|
||||
increment and append `.dev0` to version identifier in `src/PIL/_version.py` and then:
|
||||
```bash
|
||||
git push --all
|
||||
```
|
||||
## Point Release
|
||||
|
||||
Released as needed for security, installation or critical bug fixes.
|
||||
|
||||
* [ ] Make necessary changes in `main` branch.
|
||||
* [ ] Update `CHANGES.rst`.
|
||||
* [ ] Check out release branch e.g.:
|
||||
```bash
|
||||
git checkout -t remotes/origin/5.2.x
|
||||
```
|
||||
* [ ] Cherry pick individual commits from `main` branch to release branch e.g. `5.2.x`, then `git push`.
|
||||
* [ ] Check [GitHub Actions](https://github.com/python-pillow/Pillow/actions) and [AppVeyor](https://ci.appveyor.com/project/python-pillow/Pillow) to confirm passing tests in release branch e.g. `5.2.x`.
|
||||
* [ ] In compliance with [PEP 440](https://peps.python.org/pep-0440/), update version identifier in `src/PIL/_version.py`
|
||||
* [ ] Run pre-release check via `make release-test`.
|
||||
* [ ] Create tag for release e.g.:
|
||||
```bash
|
||||
git tag 5.2.1
|
||||
git push --tags
|
||||
```
|
||||
* [ ] Create and check source distribution:
|
||||
```bash
|
||||
make sdist
|
||||
```
|
||||
* [ ] Check the [GitHub Actions "Wheels" workflow](https://github.com/python-pillow/Pillow/actions/workflows/wheels.yml)
|
||||
has passed, including the "Upload release to PyPI" job. This will have been triggered
|
||||
by the new tag.
|
||||
* [ ] Publish the [release on GitHub](https://github.com/python-pillow/Pillow/releases) and then:
|
||||
```bash
|
||||
git push
|
||||
```
|
||||
|
||||
## Embargoed Release
|
||||
|
||||
Released as needed privately to individual vendors for critical security-related bug fixes.
|
||||
|
||||
* [ ] Prepare patch for all versions that will get a fix. Test against local installations.
|
||||
* [ ] Commit against `main`, cherry pick to affected release branches.
|
||||
* [ ] Run local test matrix on each release & Python version.
|
||||
* [ ] Privately send to distros.
|
||||
* [ ] Run pre-release check via `make release-test`
|
||||
* [ ] Amend any commits with the CVE #
|
||||
* [ ] On release date, tag and push to GitHub.
|
||||
```bash
|
||||
git checkout 2.5.x
|
||||
git tag 2.5.3
|
||||
git push origin --tags
|
||||
```
|
||||
* [ ] Check the [GitHub Actions "Wheels" workflow](https://github.com/python-pillow/Pillow/actions/workflows/wheels.yml)
|
||||
has passed, including the "Upload release to PyPI" job. This will have been triggered
|
||||
by the new tag.
|
||||
* [ ] Publish the [release on GitHub](https://github.com/python-pillow/Pillow/releases) and then:
|
||||
```bash
|
||||
git push origin 2.5.x
|
||||
```
|
||||
|
||||
## Publicize Release
|
||||
|
||||
* [ ] Announce release availability via [Mastodon](https://fosstodon.org/@pillow) e.g. https://fosstodon.org/@pillow/110639450470725321
|
||||
|
||||
## Documentation
|
||||
|
||||
* [ ] Make sure the [default version for Read the Docs](https://pillow.readthedocs.io/en/stable/) is up-to-date with the release changes
|
||||
|
||||
## Docker Images
|
||||
|
||||
* [ ] Update Pillow in the Docker Images repository
|
||||
```bash
|
||||
git clone https://github.com/python-pillow/docker-images
|
||||
cd docker-images
|
||||
./update-pillow-tag.sh [[release tag]]
|
||||
```
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
|
||||
from PIL import Image
|
||||
|
||||
if sys.maxsize < 2**32:
|
||||
im = Image.new("L", (999999, 999999), 0)
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
|
||||
from PIL import Image
|
||||
|
||||
if sys.maxsize < 2**32:
|
||||
im = Image.new("L", (999999, 999999), 0)
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
Pillow Tests
|
||||
============
|
||||
|
||||
Test scripts are named ``test_xxx.py``. Helper classes and functions can be found in ``helper.py``.
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
Install::
|
||||
|
||||
python3 -m pip install pytest pytest-cov pytest-timeout
|
||||
|
||||
Execution
|
||||
---------
|
||||
|
||||
To run an individual test::
|
||||
|
||||
pytest Tests/test_image.py
|
||||
|
||||
Or::
|
||||
|
||||
pytest -k test_image.py
|
||||
|
||||
Run all the tests from the root of the Pillow source distribution::
|
||||
|
||||
pytest
|
||||
|
||||
Or with coverage::
|
||||
|
||||
pytest --cov PIL --cov Tests --cov-report term
|
||||
coverage html
|
||||
open htmlcov/index.html
|
||||
Pillow Tests
|
||||
============
|
||||
|
||||
Test scripts are named ``test_xxx.py``. Helper classes and functions can be found in ``helper.py``.
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
Install::
|
||||
|
||||
python3 -m pip install pytest pytest-cov pytest-timeout
|
||||
|
||||
Execution
|
||||
---------
|
||||
|
||||
To run an individual test::
|
||||
|
||||
pytest Tests/test_image.py
|
||||
|
||||
Or::
|
||||
|
||||
pytest -k test_image.py
|
||||
|
||||
Run all the tests from the root of the Pillow source distribution::
|
||||
|
||||
pytest
|
||||
|
||||
Or with coverage::
|
||||
|
||||
pytest --cov PIL --cov Tests --cov-report term
|
||||
coverage html
|
||||
open htmlcov/index.html
|
||||
|
|
|
@ -1,54 +1,54 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
|
||||
from PIL import PyAccess
|
||||
|
||||
from .helper import hopper
|
||||
|
||||
# Not running this test by default. No DOS against CI.
|
||||
|
||||
|
||||
def iterate_get(size, access) -> None:
|
||||
(w, h) = size
|
||||
for x in range(w):
|
||||
for y in range(h):
|
||||
access[(x, y)]
|
||||
|
||||
|
||||
def iterate_set(size, access) -> None:
|
||||
(w, h) = size
|
||||
for x in range(w):
|
||||
for y in range(h):
|
||||
access[(x, y)] = (x % 256, y % 256, 0)
|
||||
|
||||
|
||||
def timer(func, label, *args) -> None:
|
||||
iterations = 5000
|
||||
starttime = time.time()
|
||||
for x in range(iterations):
|
||||
func(*args)
|
||||
if time.time() - starttime > 10:
|
||||
break
|
||||
endtime = time.time()
|
||||
print(
|
||||
f"{label}: completed {x + 1} iterations in {endtime - starttime:.4f}s, "
|
||||
f"{(endtime - starttime) / (x + 1.0):.6f}s per iteration"
|
||||
)
|
||||
|
||||
|
||||
def test_direct() -> None:
|
||||
im = hopper()
|
||||
im.load()
|
||||
# im = Image.new("RGB", (2000, 2000), (1, 3, 2))
|
||||
caccess = im.im.pixel_access(False)
|
||||
access = PyAccess.new(im, False)
|
||||
|
||||
assert access is not None
|
||||
assert caccess[(0, 0)] == access[(0, 0)]
|
||||
|
||||
print(f"Size: {im.width}x{im.height}")
|
||||
timer(iterate_get, "PyAccess - get", im.size, access)
|
||||
timer(iterate_set, "PyAccess - set", im.size, access)
|
||||
timer(iterate_get, "C-api - get", im.size, caccess)
|
||||
timer(iterate_set, "C-api - set", im.size, caccess)
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
|
||||
from PIL import PyAccess
|
||||
|
||||
from .helper import hopper
|
||||
|
||||
# Not running this test by default. No DOS against CI.
|
||||
|
||||
|
||||
def iterate_get(size, access) -> None:
|
||||
(w, h) = size
|
||||
for x in range(w):
|
||||
for y in range(h):
|
||||
access[(x, y)]
|
||||
|
||||
|
||||
def iterate_set(size, access) -> None:
|
||||
(w, h) = size
|
||||
for x in range(w):
|
||||
for y in range(h):
|
||||
access[(x, y)] = (x % 256, y % 256, 0)
|
||||
|
||||
|
||||
def timer(func, label, *args) -> None:
|
||||
iterations = 5000
|
||||
starttime = time.time()
|
||||
for x in range(iterations):
|
||||
func(*args)
|
||||
if time.time() - starttime > 10:
|
||||
break
|
||||
endtime = time.time()
|
||||
print(
|
||||
f"{label}: completed {x + 1} iterations in {endtime - starttime:.4f}s, "
|
||||
f"{(endtime - starttime) / (x + 1.0):.6f}s per iteration"
|
||||
)
|
||||
|
||||
|
||||
def test_direct() -> None:
|
||||
im = hopper()
|
||||
im.load()
|
||||
# im = Image.new("RGB", (2000, 2000), (1, 3, 2))
|
||||
caccess = im.im.pixel_access(False)
|
||||
access = PyAccess.new(im, False)
|
||||
|
||||
assert access is not None
|
||||
assert caccess[(0, 0)] == access[(0, 0)]
|
||||
|
||||
print(f"Size: {im.width}x{im.height}")
|
||||
timer(iterate_get, "PyAccess - get", im.size, access)
|
||||
timer(iterate_set, "PyAccess - set", im.size, access)
|
||||
timer(iterate_get, "C-api - get", im.size, caccess)
|
||||
timer(iterate_set, "C-api - set", im.size, caccess)
|
||||
|
|
|
@ -1,68 +1,68 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from PIL import Image
|
||||
|
||||
repro_ss2 = (
|
||||
"images/fli_oob/06r/06r00.fli",
|
||||
"images/fli_oob/06r/others/06r01.fli",
|
||||
"images/fli_oob/06r/others/06r02.fli",
|
||||
"images/fli_oob/06r/others/06r03.fli",
|
||||
"images/fli_oob/06r/others/06r04.fli",
|
||||
)
|
||||
|
||||
repro_lc = (
|
||||
"images/fli_oob/05r/05r00.fli",
|
||||
"images/fli_oob/05r/others/05r03.fli",
|
||||
"images/fli_oob/05r/others/05r06.fli",
|
||||
"images/fli_oob/05r/others/05r05.fli",
|
||||
"images/fli_oob/05r/others/05r01.fli",
|
||||
"images/fli_oob/05r/others/05r04.fli",
|
||||
"images/fli_oob/05r/others/05r02.fli",
|
||||
"images/fli_oob/05r/others/05r07.fli",
|
||||
"images/fli_oob/patch0/000000",
|
||||
"images/fli_oob/patch0/000001",
|
||||
"images/fli_oob/patch0/000002",
|
||||
"images/fli_oob/patch0/000003",
|
||||
)
|
||||
|
||||
|
||||
repro_advance = (
|
||||
"images/fli_oob/03r/03r00.fli",
|
||||
"images/fli_oob/03r/others/03r01.fli",
|
||||
"images/fli_oob/03r/others/03r09.fli",
|
||||
"images/fli_oob/03r/others/03r11.fli",
|
||||
"images/fli_oob/03r/others/03r05.fli",
|
||||
"images/fli_oob/03r/others/03r10.fli",
|
||||
"images/fli_oob/03r/others/03r06.fli",
|
||||
"images/fli_oob/03r/others/03r08.fli",
|
||||
"images/fli_oob/03r/others/03r03.fli",
|
||||
"images/fli_oob/03r/others/03r07.fli",
|
||||
"images/fli_oob/03r/others/03r02.fli",
|
||||
"images/fli_oob/03r/others/03r04.fli",
|
||||
)
|
||||
|
||||
repro_brun = (
|
||||
"images/fli_oob/04r/initial.fli",
|
||||
"images/fli_oob/04r/others/04r02.fli",
|
||||
"images/fli_oob/04r/others/04r05.fli",
|
||||
"images/fli_oob/04r/others/04r04.fli",
|
||||
"images/fli_oob/04r/others/04r03.fli",
|
||||
"images/fli_oob/04r/others/04r01.fli",
|
||||
"images/fli_oob/04r/04r00.fli",
|
||||
)
|
||||
|
||||
repro_copy = (
|
||||
"images/fli_oob/02r/others/02r02.fli",
|
||||
"images/fli_oob/02r/others/02r04.fli",
|
||||
"images/fli_oob/02r/others/02r03.fli",
|
||||
"images/fli_oob/02r/others/02r01.fli",
|
||||
"images/fli_oob/02r/02r00.fli",
|
||||
)
|
||||
|
||||
|
||||
for path in repro_ss2 + repro_lc + repro_advance + repro_brun + repro_copy:
|
||||
with Image.open(path) as im:
|
||||
try:
|
||||
im.load()
|
||||
except Exception as msg:
|
||||
print(msg)
|
||||
from __future__ import annotations
|
||||
|
||||
from PIL import Image
|
||||
|
||||
repro_ss2 = (
|
||||
"images/fli_oob/06r/06r00.fli",
|
||||
"images/fli_oob/06r/others/06r01.fli",
|
||||
"images/fli_oob/06r/others/06r02.fli",
|
||||
"images/fli_oob/06r/others/06r03.fli",
|
||||
"images/fli_oob/06r/others/06r04.fli",
|
||||
)
|
||||
|
||||
repro_lc = (
|
||||
"images/fli_oob/05r/05r00.fli",
|
||||
"images/fli_oob/05r/others/05r03.fli",
|
||||
"images/fli_oob/05r/others/05r06.fli",
|
||||
"images/fli_oob/05r/others/05r05.fli",
|
||||
"images/fli_oob/05r/others/05r01.fli",
|
||||
"images/fli_oob/05r/others/05r04.fli",
|
||||
"images/fli_oob/05r/others/05r02.fli",
|
||||
"images/fli_oob/05r/others/05r07.fli",
|
||||
"images/fli_oob/patch0/000000",
|
||||
"images/fli_oob/patch0/000001",
|
||||
"images/fli_oob/patch0/000002",
|
||||
"images/fli_oob/patch0/000003",
|
||||
)
|
||||
|
||||
|
||||
repro_advance = (
|
||||
"images/fli_oob/03r/03r00.fli",
|
||||
"images/fli_oob/03r/others/03r01.fli",
|
||||
"images/fli_oob/03r/others/03r09.fli",
|
||||
"images/fli_oob/03r/others/03r11.fli",
|
||||
"images/fli_oob/03r/others/03r05.fli",
|
||||
"images/fli_oob/03r/others/03r10.fli",
|
||||
"images/fli_oob/03r/others/03r06.fli",
|
||||
"images/fli_oob/03r/others/03r08.fli",
|
||||
"images/fli_oob/03r/others/03r03.fli",
|
||||
"images/fli_oob/03r/others/03r07.fli",
|
||||
"images/fli_oob/03r/others/03r02.fli",
|
||||
"images/fli_oob/03r/others/03r04.fli",
|
||||
)
|
||||
|
||||
repro_brun = (
|
||||
"images/fli_oob/04r/initial.fli",
|
||||
"images/fli_oob/04r/others/04r02.fli",
|
||||
"images/fli_oob/04r/others/04r05.fli",
|
||||
"images/fli_oob/04r/others/04r04.fli",
|
||||
"images/fli_oob/04r/others/04r03.fli",
|
||||
"images/fli_oob/04r/others/04r01.fli",
|
||||
"images/fli_oob/04r/04r00.fli",
|
||||
)
|
||||
|
||||
repro_copy = (
|
||||
"images/fli_oob/02r/others/02r02.fli",
|
||||
"images/fli_oob/02r/others/02r04.fli",
|
||||
"images/fli_oob/02r/others/02r03.fli",
|
||||
"images/fli_oob/02r/others/02r01.fli",
|
||||
"images/fli_oob/02r/02r00.fli",
|
||||
)
|
||||
|
||||
|
||||
for path in repro_ss2 + repro_lc + repro_advance + repro_brun + repro_copy:
|
||||
with Image.open(path) as im:
|
||||
try:
|
||||
im.load()
|
||||
except Exception as msg:
|
||||
print(msg)
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from PIL import Image
|
||||
|
||||
TEST_FILE = "Tests/images/fli_overflow.fli"
|
||||
|
||||
|
||||
def test_fli_overflow() -> None:
|
||||
# this should not crash with a malloc error or access violation
|
||||
with Image.open(TEST_FILE) as im:
|
||||
im.load()
|
||||
from __future__ import annotations
|
||||
|
||||
from PIL import Image
|
||||
|
||||
TEST_FILE = "Tests/images/fli_overflow.fli"
|
||||
|
||||
|
||||
def test_fli_overflow() -> None:
|
||||
# this should not crash with a malloc error or access violation
|
||||
with Image.open(TEST_FILE) as im:
|
||||
im.load()
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
# Tests potential DOS of IcnsImagePlugin with 0 length block.
|
||||
# Run from anywhere that PIL is importable.
|
||||
from __future__ import annotations
|
||||
|
||||
from io import BytesIO
|
||||
|
||||
from PIL import Image
|
||||
|
||||
with Image.open(BytesIO(b"icns\x00\x00\x00\x10hang\x00\x00\x00\x00")):
|
||||
pass
|
||||
# Tests potential DOS of IcnsImagePlugin with 0 length block.
|
||||
# Run from anywhere that PIL is importable.
|
||||
from __future__ import annotations
|
||||
|
||||
from io import BytesIO
|
||||
|
||||
from PIL import Image
|
||||
|
||||
with Image.open(BytesIO(b"icns\x00\x00\x00\x10hang\x00\x00\x00\x00")):
|
||||
pass
|
||||
|
|
|
@ -1,55 +1,55 @@
|
|||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Callable
|
||||
|
||||
import pytest
|
||||
|
||||
from PIL import Image
|
||||
|
||||
from .helper import is_win32
|
||||
|
||||
min_iterations = 100
|
||||
max_iterations = 10000
|
||||
|
||||
pytestmark = pytest.mark.skipif(is_win32(), reason="requires Unix or macOS")
|
||||
|
||||
|
||||
def _get_mem_usage() -> float:
|
||||
from resource import RUSAGE_SELF, getpagesize, getrusage
|
||||
|
||||
mem = getrusage(RUSAGE_SELF).ru_maxrss
|
||||
return mem * getpagesize() / 1024 / 1024
|
||||
|
||||
|
||||
def _test_leak(
|
||||
min_iterations: int,
|
||||
max_iterations: int,
|
||||
fn: Callable[..., Image.Image | None],
|
||||
*args: Any,
|
||||
) -> None:
|
||||
mem_limit = None
|
||||
for i in range(max_iterations):
|
||||
fn(*args)
|
||||
mem = _get_mem_usage()
|
||||
if i < min_iterations:
|
||||
mem_limit = mem + 1
|
||||
continue
|
||||
msg = f"memory usage limit exceeded after {i + 1} iterations"
|
||||
assert mem_limit is not None
|
||||
assert mem <= mem_limit, msg
|
||||
|
||||
|
||||
def test_leak_putdata() -> None:
|
||||
im = Image.new("RGB", (25, 25))
|
||||
_test_leak(min_iterations, max_iterations, im.putdata, im.getdata())
|
||||
|
||||
|
||||
def test_leak_getlist() -> None:
|
||||
im = Image.new("P", (25, 25))
|
||||
_test_leak(
|
||||
min_iterations,
|
||||
max_iterations,
|
||||
# Pass a new list at each iteration.
|
||||
lambda: im.point(range(256)),
|
||||
)
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Callable
|
||||
|
||||
import pytest
|
||||
|
||||
from PIL import Image
|
||||
|
||||
from .helper import is_win32
|
||||
|
||||
min_iterations = 100
|
||||
max_iterations = 10000
|
||||
|
||||
pytestmark = pytest.mark.skipif(is_win32(), reason="requires Unix or macOS")
|
||||
|
||||
|
||||
def _get_mem_usage() -> float:
|
||||
from resource import RUSAGE_SELF, getpagesize, getrusage
|
||||
|
||||
mem = getrusage(RUSAGE_SELF).ru_maxrss
|
||||
return mem * getpagesize() / 1024 / 1024
|
||||
|
||||
|
||||
def _test_leak(
|
||||
min_iterations: int,
|
||||
max_iterations: int,
|
||||
fn: Callable[..., Image.Image | None],
|
||||
*args: Any,
|
||||
) -> None:
|
||||
mem_limit = None
|
||||
for i in range(max_iterations):
|
||||
fn(*args)
|
||||
mem = _get_mem_usage()
|
||||
if i < min_iterations:
|
||||
mem_limit = mem + 1
|
||||
continue
|
||||
msg = f"memory usage limit exceeded after {i + 1} iterations"
|
||||
assert mem_limit is not None
|
||||
assert mem <= mem_limit, msg
|
||||
|
||||
|
||||
def test_leak_putdata() -> None:
|
||||
im = Image.new("RGB", (25, 25))
|
||||
_test_leak(min_iterations, max_iterations, im.putdata, im.getdata())
|
||||
|
||||
|
||||
def test_leak_getlist() -> None:
|
||||
im = Image.new("P", (25, 25))
|
||||
_test_leak(
|
||||
min_iterations,
|
||||
max_iterations,
|
||||
# Pass a new list at each iteration.
|
||||
lambda: im.point(range(256)),
|
||||
)
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
# Tests potential DOS of Jpeg2kImagePlugin with 0 length block.
|
||||
# Run from anywhere that PIL is importable.
|
||||
from __future__ import annotations
|
||||
|
||||
from io import BytesIO
|
||||
|
||||
from PIL import Image
|
||||
|
||||
with Image.open(
|
||||
BytesIO(b"\x00\x00\x00\x0cjP\x20\x20\x0d\x0a\x87\x0a\x00\x00\x00\x00hang")
|
||||
):
|
||||
pass
|
||||
# Tests potential DOS of Jpeg2kImagePlugin with 0 length block.
|
||||
# Run from anywhere that PIL is importable.
|
||||
from __future__ import annotations
|
||||
|
||||
from io import BytesIO
|
||||
|
||||
from PIL import Image
|
||||
|
||||
with Image.open(
|
||||
BytesIO(b"\x00\x00\x00\x0cjP\x20\x20\x0d\x0a\x87\x0a\x00\x00\x00\x00hang")
|
||||
):
|
||||
pass
|
||||
|
|
|
@ -1,44 +1,44 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from io import BytesIO
|
||||
|
||||
import pytest
|
||||
|
||||
from PIL import Image
|
||||
|
||||
from .helper import is_win32, skip_unless_feature
|
||||
|
||||
# Limits for testing the leak
|
||||
mem_limit = 1024 * 1048576
|
||||
stack_size = 8 * 1048576
|
||||
iterations = int((mem_limit / stack_size) * 2)
|
||||
test_file = "Tests/images/rgb_trns_ycbc.jp2"
|
||||
|
||||
pytestmark = [
|
||||
pytest.mark.skipif(is_win32(), reason="requires Unix or macOS"),
|
||||
skip_unless_feature("jpg_2000"),
|
||||
]
|
||||
|
||||
|
||||
def test_leak_load() -> None:
|
||||
from resource import RLIMIT_AS, RLIMIT_STACK, setrlimit
|
||||
|
||||
setrlimit(RLIMIT_STACK, (stack_size, stack_size))
|
||||
setrlimit(RLIMIT_AS, (mem_limit, mem_limit))
|
||||
for _ in range(iterations):
|
||||
with Image.open(test_file) as im:
|
||||
im.load()
|
||||
|
||||
|
||||
def test_leak_save() -> None:
|
||||
from resource import RLIMIT_AS, RLIMIT_STACK, setrlimit
|
||||
|
||||
setrlimit(RLIMIT_STACK, (stack_size, stack_size))
|
||||
setrlimit(RLIMIT_AS, (mem_limit, mem_limit))
|
||||
for _ in range(iterations):
|
||||
with Image.open(test_file) as im:
|
||||
im.load()
|
||||
test_output = BytesIO()
|
||||
im.save(test_output, "JPEG2000")
|
||||
test_output.seek(0)
|
||||
test_output.read()
|
||||
from __future__ import annotations
|
||||
|
||||
from io import BytesIO
|
||||
|
||||
import pytest
|
||||
|
||||
from PIL import Image
|
||||
|
||||
from .helper import is_win32, skip_unless_feature
|
||||
|
||||
# Limits for testing the leak
|
||||
mem_limit = 1024 * 1048576
|
||||
stack_size = 8 * 1048576
|
||||
iterations = int((mem_limit / stack_size) * 2)
|
||||
test_file = "Tests/images/rgb_trns_ycbc.jp2"
|
||||
|
||||
pytestmark = [
|
||||
pytest.mark.skipif(is_win32(), reason="requires Unix or macOS"),
|
||||
skip_unless_feature("jpg_2000"),
|
||||
]
|
||||
|
||||
|
||||
def test_leak_load() -> None:
|
||||
from resource import RLIMIT_AS, RLIMIT_STACK, setrlimit
|
||||
|
||||
setrlimit(RLIMIT_STACK, (stack_size, stack_size))
|
||||
setrlimit(RLIMIT_AS, (mem_limit, mem_limit))
|
||||
for _ in range(iterations):
|
||||
with Image.open(test_file) as im:
|
||||
im.load()
|
||||
|
||||
|
||||
def test_leak_save() -> None:
|
||||
from resource import RLIMIT_AS, RLIMIT_STACK, setrlimit
|
||||
|
||||
setrlimit(RLIMIT_STACK, (stack_size, stack_size))
|
||||
setrlimit(RLIMIT_AS, (mem_limit, mem_limit))
|
||||
for _ in range(iterations):
|
||||
with Image.open(test_file) as im:
|
||||
im.load()
|
||||
test_output = BytesIO()
|
||||
im.save(test_output, "JPEG2000")
|
||||
test_output.seek(0)
|
||||
test_output.read()
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from PIL import Image
|
||||
|
||||
|
||||
def test_j2k_overflow(tmp_path: Path) -> None:
|
||||
im = Image.new("RGBA", (1024, 131584))
|
||||
target = str(tmp_path / "temp.jpc")
|
||||
with pytest.raises(OSError):
|
||||
im.save(target)
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from PIL import Image
|
||||
|
||||
|
||||
def test_j2k_overflow(tmp_path: Path) -> None:
|
||||
im = Image.new("RGBA", (1024, 131584))
|
||||
target = str(tmp_path / "temp.jpc")
|
||||
with pytest.raises(OSError):
|
||||
im.save(target)
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
# Reproductions/tests for OOB read errors in FliDecode.c
|
||||
|
||||
# When run in python, all of these images should fail for
|
||||
# one reason or another, either as a buffer overrun,
|
||||
# unrecognized datastream, or truncated image file.
|
||||
# There shouldn't be any segfaults.
|
||||
#
|
||||
# if run like
|
||||
# `valgrind --tool=memcheck python check_jp2_overflow.py 2>&1 | grep Decode.c`
|
||||
# the output should be empty. There may be python issues
|
||||
# in the valgrind especially if run in a debug python
|
||||
# version.
|
||||
from __future__ import annotations
|
||||
|
||||
from PIL import Image
|
||||
|
||||
repro = ("00r0_gray_l.jp2", "00r1_graya_la.jp2")
|
||||
|
||||
for path in repro:
|
||||
with Image.open(path) as im:
|
||||
try:
|
||||
im.load()
|
||||
except Exception as msg:
|
||||
print(msg)
|
||||
# Reproductions/tests for OOB read errors in FliDecode.c
|
||||
|
||||
# When run in python, all of these images should fail for
|
||||
# one reason or another, either as a buffer overrun,
|
||||
# unrecognized datastream, or truncated image file.
|
||||
# There shouldn't be any segfaults.
|
||||
#
|
||||
# if run like
|
||||
# `valgrind --tool=memcheck python check_jp2_overflow.py 2>&1 | grep Decode.c`
|
||||
# the output should be empty. There may be python issues
|
||||
# in the valgrind especially if run in a debug python
|
||||
# version.
|
||||
from __future__ import annotations
|
||||
|
||||
from PIL import Image
|
||||
|
||||
repro = ("00r0_gray_l.jp2", "00r1_graya_la.jp2")
|
||||
|
||||
for path in repro:
|
||||
with Image.open(path) as im:
|
||||
try:
|
||||
im.load()
|
||||
except Exception as msg:
|
||||
print(msg)
|
||||
|
|
|
@ -1,214 +1,214 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from io import BytesIO
|
||||
|
||||
import pytest
|
||||
|
||||
from .helper import hopper, is_win32
|
||||
|
||||
iterations = 5000
|
||||
|
||||
|
||||
"""
|
||||
When run on a system without the jpeg leak fixes,
|
||||
the valgrind runs look like this.
|
||||
|
||||
valgrind --tool=massif python test-installed.py -s -v Tests/check_jpeg_leaks.py
|
||||
|
||||
"""
|
||||
|
||||
|
||||
pytestmark = pytest.mark.skipif(is_win32(), reason="requires Unix or macOS")
|
||||
|
||||
"""
|
||||
pre patch:
|
||||
|
||||
MB
|
||||
31.62^ :
|
||||
| @:@:@:@#::
|
||||
| @:@:@@:@:@:@:@:@#::
|
||||
| ::::::::@:@:@@:@:@:@:@:@#::
|
||||
| :::::@::::::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| ::::::@::::@:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| ::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| :::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| ::::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| : ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| @: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| @@: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| :@@: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| :@@: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| :@:@@: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| :@:@@: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| :@:@@: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
0 +----------------------------------------------------------------------->Gi
|
||||
0 8.535
|
||||
|
||||
|
||||
post-patch:
|
||||
|
||||
MB
|
||||
21.03^ :::@@:::@::::@@:::::::@@::::::::@::::::::::::@:::@:::::::@::::
|
||||
| #:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| #:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| :::#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| : :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| : :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| @: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| @@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| @@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| @@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| :@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| :@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| :@:@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| :@:@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| :@:@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| :@:@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| :@:@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
0 +----------------------------------------------------------------------->Gi
|
||||
0 8.421
|
||||
|
||||
"""
|
||||
|
||||
|
||||
standard_l_qtable = (
|
||||
# fmt: off
|
||||
16, 11, 10, 16, 24, 40, 51, 61,
|
||||
12, 12, 14, 19, 26, 58, 60, 55,
|
||||
14, 13, 16, 24, 40, 57, 69, 56,
|
||||
14, 17, 22, 29, 51, 87, 80, 62,
|
||||
18, 22, 37, 56, 68, 109, 103, 77,
|
||||
24, 35, 55, 64, 81, 104, 113, 92,
|
||||
49, 64, 78, 87, 103, 121, 120, 101,
|
||||
72, 92, 95, 98, 112, 100, 103, 99,
|
||||
# fmt: on
|
||||
)
|
||||
|
||||
standard_chrominance_qtable = (
|
||||
# fmt: off
|
||||
17, 18, 24, 47, 99, 99, 99, 99,
|
||||
18, 21, 26, 66, 99, 99, 99, 99,
|
||||
24, 26, 56, 99, 99, 99, 99, 99,
|
||||
47, 66, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
# fmt: on
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"qtables",
|
||||
(
|
||||
(standard_l_qtable, standard_chrominance_qtable),
|
||||
[standard_l_qtable, standard_chrominance_qtable],
|
||||
),
|
||||
)
|
||||
def test_qtables_leak(qtables: tuple[tuple[int, ...]] | list[tuple[int, ...]]) -> None:
|
||||
im = hopper("RGB")
|
||||
for _ in range(iterations):
|
||||
test_output = BytesIO()
|
||||
im.save(test_output, "JPEG", qtables=qtables)
|
||||
|
||||
|
||||
def test_exif_leak() -> None:
|
||||
"""
|
||||
pre patch:
|
||||
|
||||
MB
|
||||
177.1^ #
|
||||
| @@@#
|
||||
| :@@@@@@#
|
||||
| ::::@@@@@@#
|
||||
| ::::::::@@@@@@#
|
||||
| @@::::: ::::@@@@@@#
|
||||
| @@@@ ::::: ::::@@@@@@#
|
||||
| @@@@@@@ ::::: ::::@@@@@@#
|
||||
| @@::@@@@@@@ ::::: ::::@@@@@@#
|
||||
| @@@@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||
| @@@@@@ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||
| @@@@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||
| @::@@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||
| ::::@: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||
| :@@: : @: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||
| ::@@::@@: : @: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||
| @@::: @ ::@@: : @: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||
| @::@ : : @ ::@@: : @: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||
| :::@: @ : : @ ::@@: : @: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||
| @@@:: @: @ : : @ ::@@: : @: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||
0 +----------------------------------------------------------------------->Gi
|
||||
0 11.37
|
||||
|
||||
|
||||
post patch:
|
||||
|
||||
MB
|
||||
21.06^ ::::::::::::::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| ##::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| # ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| # ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| # ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @@@@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @ @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @ @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @ @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @ @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
0 +----------------------------------------------------------------------->Gi
|
||||
0 11.33
|
||||
"""
|
||||
im = hopper("RGB")
|
||||
exif = b"12345678" * 4096
|
||||
|
||||
for _ in range(iterations):
|
||||
test_output = BytesIO()
|
||||
im.save(test_output, "JPEG", exif=exif)
|
||||
|
||||
|
||||
def test_base_save() -> None:
|
||||
"""
|
||||
base case:
|
||||
MB
|
||||
20.99^ ::::: :::::::::::::::::::::::::::::::::::::::::::@:::
|
||||
| ##: : ::::::@::::::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| @@# : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| @@@ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| @ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| :@@@@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| :@ @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| :@ @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| :@ @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| :@ @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
0 +----------------------------------------------------------------------->Gi
|
||||
0 7.882"""
|
||||
im = hopper("RGB")
|
||||
|
||||
for _ in range(iterations):
|
||||
test_output = BytesIO()
|
||||
im.save(test_output, "JPEG")
|
||||
from __future__ import annotations
|
||||
|
||||
from io import BytesIO
|
||||
|
||||
import pytest
|
||||
|
||||
from .helper import hopper, is_win32
|
||||
|
||||
iterations = 5000
|
||||
|
||||
|
||||
"""
|
||||
When run on a system without the jpeg leak fixes,
|
||||
the valgrind runs look like this.
|
||||
|
||||
valgrind --tool=massif python test-installed.py -s -v Tests/check_jpeg_leaks.py
|
||||
|
||||
"""
|
||||
|
||||
|
||||
pytestmark = pytest.mark.skipif(is_win32(), reason="requires Unix or macOS")
|
||||
|
||||
"""
|
||||
pre patch:
|
||||
|
||||
MB
|
||||
31.62^ :
|
||||
| @:@:@:@#::
|
||||
| @:@:@@:@:@:@:@:@#::
|
||||
| ::::::::@:@:@@:@:@:@:@:@#::
|
||||
| :::::@::::::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| ::::::@::::@:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| ::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| :::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| ::::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| : ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| @: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| @@: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| :@@: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| :@@: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| :@:@@: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| :@:@@: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
| :@:@@: ::::::::: : :@: : @:::::::::::::@: : ::: ::::@:@:@@:@:@:@:@:@#::
|
||||
0 +----------------------------------------------------------------------->Gi
|
||||
0 8.535
|
||||
|
||||
|
||||
post-patch:
|
||||
|
||||
MB
|
||||
21.03^ :::@@:::@::::@@:::::::@@::::::::@::::::::::::@:::@:::::::@::::
|
||||
| #:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| #:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| :::#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| : :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| : :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| @: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| @@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| @@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| @@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| :@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| :@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| :@:@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| :@:@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| :@:@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| :@:@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
| :@:@@: :#:::@ :::@::::@ : :: : @ :::::: :@:: ::: :::: @:: @:::::::@::::
|
||||
0 +----------------------------------------------------------------------->Gi
|
||||
0 8.421
|
||||
|
||||
"""
|
||||
|
||||
|
||||
standard_l_qtable = (
|
||||
# fmt: off
|
||||
16, 11, 10, 16, 24, 40, 51, 61,
|
||||
12, 12, 14, 19, 26, 58, 60, 55,
|
||||
14, 13, 16, 24, 40, 57, 69, 56,
|
||||
14, 17, 22, 29, 51, 87, 80, 62,
|
||||
18, 22, 37, 56, 68, 109, 103, 77,
|
||||
24, 35, 55, 64, 81, 104, 113, 92,
|
||||
49, 64, 78, 87, 103, 121, 120, 101,
|
||||
72, 92, 95, 98, 112, 100, 103, 99,
|
||||
# fmt: on
|
||||
)
|
||||
|
||||
standard_chrominance_qtable = (
|
||||
# fmt: off
|
||||
17, 18, 24, 47, 99, 99, 99, 99,
|
||||
18, 21, 26, 66, 99, 99, 99, 99,
|
||||
24, 26, 56, 99, 99, 99, 99, 99,
|
||||
47, 66, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
# fmt: on
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"qtables",
|
||||
(
|
||||
(standard_l_qtable, standard_chrominance_qtable),
|
||||
[standard_l_qtable, standard_chrominance_qtable],
|
||||
),
|
||||
)
|
||||
def test_qtables_leak(qtables: tuple[tuple[int, ...]] | list[tuple[int, ...]]) -> None:
|
||||
im = hopper("RGB")
|
||||
for _ in range(iterations):
|
||||
test_output = BytesIO()
|
||||
im.save(test_output, "JPEG", qtables=qtables)
|
||||
|
||||
|
||||
def test_exif_leak() -> None:
|
||||
"""
|
||||
pre patch:
|
||||
|
||||
MB
|
||||
177.1^ #
|
||||
| @@@#
|
||||
| :@@@@@@#
|
||||
| ::::@@@@@@#
|
||||
| ::::::::@@@@@@#
|
||||
| @@::::: ::::@@@@@@#
|
||||
| @@@@ ::::: ::::@@@@@@#
|
||||
| @@@@@@@ ::::: ::::@@@@@@#
|
||||
| @@::@@@@@@@ ::::: ::::@@@@@@#
|
||||
| @@@@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||
| @@@@@@ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||
| @@@@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||
| @::@@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||
| ::::@: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||
| :@@: : @: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||
| ::@@::@@: : @: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||
| @@::: @ ::@@: : @: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||
| @::@ : : @ ::@@: : @: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||
| :::@: @ : : @ ::@@: : @: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||
| @@@:: @: @ : : @ ::@@: : @: @@ @@ @@ @ @@ : @@@@@@@ ::::: ::::@@@@@@#
|
||||
0 +----------------------------------------------------------------------->Gi
|
||||
0 11.37
|
||||
|
||||
|
||||
post patch:
|
||||
|
||||
MB
|
||||
21.06^ ::::::::::::::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| ##::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| # ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| # ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| # ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @@@@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @ @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @ @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @ @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
| @ @@@# ::: ::::: : ::::::::::@::::@::::@::::@::::@::::@:::::::::@::::::
|
||||
0 +----------------------------------------------------------------------->Gi
|
||||
0 11.33
|
||||
"""
|
||||
im = hopper("RGB")
|
||||
exif = b"12345678" * 4096
|
||||
|
||||
for _ in range(iterations):
|
||||
test_output = BytesIO()
|
||||
im.save(test_output, "JPEG", exif=exif)
|
||||
|
||||
|
||||
def test_base_save() -> None:
|
||||
"""
|
||||
base case:
|
||||
MB
|
||||
20.99^ ::::: :::::::::::::::::::::::::::::::::::::::::::@:::
|
||||
| ##: : ::::::@::::::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| @@# : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| @@@ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| @ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| :@@@@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| :@ @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| :@ @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| :@ @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
| :@ @@ @ # : : :: :: @:: :::: :::: :::: : : : : : : :::::::::::: :::@:::
|
||||
0 +----------------------------------------------------------------------->Gi
|
||||
0 7.882"""
|
||||
im = hopper("RGB")
|
||||
|
||||
for _ in range(iterations):
|
||||
test_output = BytesIO()
|
||||
im.save(test_output, "JPEG")
|
||||
|
|
|
@ -1,54 +1,54 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from types import ModuleType
|
||||
|
||||
import pytest
|
||||
|
||||
from PIL import Image
|
||||
|
||||
# This test is not run automatically.
|
||||
#
|
||||
# It requires > 2gb memory for the >2 gigapixel image generated in the
|
||||
# second test. Running this automatically would amount to a denial of
|
||||
# service on our testing infrastructure. I expect this test to fail
|
||||
# on any 32-bit machine, as well as any smallish things (like
|
||||
# Raspberry Pis). It does succeed on a 3gb Ubuntu 12.04x64 VM on Python
|
||||
# 2.7 and 3.2.
|
||||
|
||||
|
||||
numpy: ModuleType | None
|
||||
try:
|
||||
import numpy
|
||||
except ImportError:
|
||||
numpy = None
|
||||
|
||||
YDIM = 32769
|
||||
XDIM = 48000
|
||||
|
||||
|
||||
pytestmark = pytest.mark.skipif(sys.maxsize <= 2**32, reason="requires 64-bit system")
|
||||
|
||||
|
||||
def _write_png(tmp_path: Path, xdim: int, ydim: int) -> None:
|
||||
f = str(tmp_path / "temp.png")
|
||||
im = Image.new("L", (xdim, ydim), 0)
|
||||
im.save(f)
|
||||
|
||||
|
||||
def test_large(tmp_path: Path) -> None:
|
||||
"""succeeded prepatch"""
|
||||
_write_png(tmp_path, XDIM, YDIM)
|
||||
|
||||
|
||||
def test_2gpx(tmp_path: Path) -> None:
|
||||
"""failed prepatch"""
|
||||
_write_png(tmp_path, XDIM, XDIM)
|
||||
|
||||
|
||||
@pytest.mark.skipif(numpy is None, reason="Numpy is not installed")
|
||||
def test_size_greater_than_int() -> None:
|
||||
assert numpy is not None
|
||||
arr = numpy.ndarray(shape=(16394, 16394))
|
||||
Image.fromarray(arr)
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from types import ModuleType
|
||||
|
||||
import pytest
|
||||
|
||||
from PIL import Image
|
||||
|
||||
# This test is not run automatically.
|
||||
#
|
||||
# It requires > 2gb memory for the >2 gigapixel image generated in the
|
||||
# second test. Running this automatically would amount to a denial of
|
||||
# service on our testing infrastructure. I expect this test to fail
|
||||
# on any 32-bit machine, as well as any smallish things (like
|
||||
# Raspberry Pis). It does succeed on a 3gb Ubuntu 12.04x64 VM on Python
|
||||
# 2.7 and 3.2.
|
||||
|
||||
|
||||
numpy: ModuleType | None
|
||||
try:
|
||||
import numpy
|
||||
except ImportError:
|
||||
numpy = None
|
||||
|
||||
YDIM = 32769
|
||||
XDIM = 48000
|
||||
|
||||
|
||||
pytestmark = pytest.mark.skipif(sys.maxsize <= 2**32, reason="requires 64-bit system")
|
||||
|
||||
|
||||
def _write_png(tmp_path: Path, xdim: int, ydim: int) -> None:
|
||||
f = str(tmp_path / "temp.png")
|
||||
im = Image.new("L", (xdim, ydim), 0)
|
||||
im.save(f)
|
||||
|
||||
|
||||
def test_large(tmp_path: Path) -> None:
|
||||
"""succeeded prepatch"""
|
||||
_write_png(tmp_path, XDIM, YDIM)
|
||||
|
||||
|
||||
def test_2gpx(tmp_path: Path) -> None:
|
||||
"""failed prepatch"""
|
||||
_write_png(tmp_path, XDIM, XDIM)
|
||||
|
||||
|
||||
@pytest.mark.skipif(numpy is None, reason="Numpy is not installed")
|
||||
def test_size_greater_than_int() -> None:
|
||||
assert numpy is not None
|
||||
arr = numpy.ndarray(shape=(16394, 16394))
|
||||
Image.fromarray(arr)
|
||||
|
|
|
@ -1,43 +1,43 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from PIL import Image
|
||||
|
||||
# This test is not run automatically.
|
||||
#
|
||||
# It requires > 2gb memory for the >2 gigapixel image generated in the
|
||||
# second test. Running this automatically would amount to a denial of
|
||||
# service on our testing infrastructure. I expect this test to fail
|
||||
# on any 32-bit machine, as well as any smallish things (like
|
||||
# Raspberry Pis).
|
||||
|
||||
|
||||
np = pytest.importorskip("numpy", reason="NumPy not installed")
|
||||
|
||||
YDIM = 32769
|
||||
XDIM = 48000
|
||||
|
||||
|
||||
pytestmark = pytest.mark.skipif(sys.maxsize <= 2**32, reason="requires 64-bit system")
|
||||
|
||||
|
||||
def _write_png(tmp_path: Path, xdim: int, ydim: int) -> None:
|
||||
dtype = np.uint8
|
||||
a = np.zeros((xdim, ydim), dtype=dtype)
|
||||
f = str(tmp_path / "temp.png")
|
||||
im = Image.fromarray(a, "L")
|
||||
im.save(f)
|
||||
|
||||
|
||||
def test_large(tmp_path: Path) -> None:
|
||||
"""succeeded prepatch"""
|
||||
_write_png(tmp_path, XDIM, YDIM)
|
||||
|
||||
|
||||
def test_2gpx(tmp_path: Path) -> None:
|
||||
"""failed prepatch"""
|
||||
_write_png(tmp_path, XDIM, XDIM)
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from PIL import Image
|
||||
|
||||
# This test is not run automatically.
|
||||
#
|
||||
# It requires > 2gb memory for the >2 gigapixel image generated in the
|
||||
# second test. Running this automatically would amount to a denial of
|
||||
# service on our testing infrastructure. I expect this test to fail
|
||||
# on any 32-bit machine, as well as any smallish things (like
|
||||
# Raspberry Pis).
|
||||
|
||||
|
||||
np = pytest.importorskip("numpy", reason="NumPy not installed")
|
||||
|
||||
YDIM = 32769
|
||||
XDIM = 48000
|
||||
|
||||
|
||||
pytestmark = pytest.mark.skipif(sys.maxsize <= 2**32, reason="requires 64-bit system")
|
||||
|
||||
|
||||
def _write_png(tmp_path: Path, xdim: int, ydim: int) -> None:
|
||||
dtype = np.uint8
|
||||
a = np.zeros((xdim, ydim), dtype=dtype)
|
||||
f = str(tmp_path / "temp.png")
|
||||
im = Image.fromarray(a, "L")
|
||||
im.save(f)
|
||||
|
||||
|
||||
def test_large(tmp_path: Path) -> None:
|
||||
"""succeeded prepatch"""
|
||||
_write_png(tmp_path, XDIM, YDIM)
|
||||
|
||||
|
||||
def test_2gpx(tmp_path: Path) -> None:
|
||||
"""failed prepatch"""
|
||||
_write_png(tmp_path, XDIM, XDIM)
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from PIL import Image
|
||||
|
||||
TEST_FILE = "Tests/images/libtiff_segfault.tif"
|
||||
|
||||
|
||||
def test_libtiff_segfault() -> None:
|
||||
"""This test should not segfault. It will on Pillow <= 3.1.0 and
|
||||
libtiff >= 4.0.0
|
||||
"""
|
||||
|
||||
with pytest.raises(OSError):
|
||||
with Image.open(TEST_FILE) as im:
|
||||
im.load()
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from PIL import Image
|
||||
|
||||
TEST_FILE = "Tests/images/libtiff_segfault.tif"
|
||||
|
||||
|
||||
def test_libtiff_segfault() -> None:
|
||||
"""This test should not segfault. It will on Pillow <= 3.1.0 and
|
||||
libtiff >= 4.0.0
|
||||
"""
|
||||
|
||||
with pytest.raises(OSError):
|
||||
with Image.open(TEST_FILE) as im:
|
||||
im.load()
|
||||
|
|
|
@ -1,65 +1,65 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import zlib
|
||||
from io import BytesIO
|
||||
|
||||
from PIL import Image, ImageFile, PngImagePlugin
|
||||
|
||||
TEST_FILE = "Tests/images/png_decompression_dos.png"
|
||||
|
||||
|
||||
def test_ignore_dos_text() -> None:
|
||||
ImageFile.LOAD_TRUNCATED_IMAGES = True
|
||||
|
||||
try:
|
||||
im = Image.open(TEST_FILE)
|
||||
im.load()
|
||||
finally:
|
||||
ImageFile.LOAD_TRUNCATED_IMAGES = False
|
||||
|
||||
assert isinstance(im, PngImagePlugin.PngImageFile)
|
||||
for s in im.text.values():
|
||||
assert len(s) < 1024 * 1024, "Text chunk larger than 1M"
|
||||
|
||||
for s in im.info.values():
|
||||
assert len(s) < 1024 * 1024, "Text chunk larger than 1M"
|
||||
|
||||
|
||||
def test_dos_text() -> None:
|
||||
try:
|
||||
im = Image.open(TEST_FILE)
|
||||
im.load()
|
||||
except ValueError as msg:
|
||||
assert msg, "Decompressed Data Too Large"
|
||||
return
|
||||
|
||||
assert isinstance(im, PngImagePlugin.PngImageFile)
|
||||
for s in im.text.values():
|
||||
assert len(s) < 1024 * 1024, "Text chunk larger than 1M"
|
||||
|
||||
|
||||
def test_dos_total_memory() -> None:
|
||||
im = Image.new("L", (1, 1))
|
||||
compressed_data = zlib.compress(b"a" * 1024 * 1023)
|
||||
|
||||
info = PngImagePlugin.PngInfo()
|
||||
|
||||
for x in range(64):
|
||||
info.add_text(f"t{x}", compressed_data, zip=True)
|
||||
info.add_itxt(f"i{x}", compressed_data, zip=True)
|
||||
|
||||
b = BytesIO()
|
||||
im.save(b, "PNG", pnginfo=info)
|
||||
b.seek(0)
|
||||
|
||||
try:
|
||||
im2 = Image.open(b)
|
||||
except ValueError as msg:
|
||||
assert "Too much memory" in str(msg)
|
||||
return
|
||||
|
||||
total_len = 0
|
||||
assert isinstance(im2, PngImagePlugin.PngImageFile)
|
||||
for txt in im2.text.values():
|
||||
total_len += len(txt)
|
||||
assert total_len < 64 * 1024 * 1024, "Total text chunks greater than 64M"
|
||||
from __future__ import annotations
|
||||
|
||||
import zlib
|
||||
from io import BytesIO
|
||||
|
||||
from PIL import Image, ImageFile, PngImagePlugin
|
||||
|
||||
TEST_FILE = "Tests/images/png_decompression_dos.png"
|
||||
|
||||
|
||||
def test_ignore_dos_text() -> None:
|
||||
ImageFile.LOAD_TRUNCATED_IMAGES = True
|
||||
|
||||
try:
|
||||
im = Image.open(TEST_FILE)
|
||||
im.load()
|
||||
finally:
|
||||
ImageFile.LOAD_TRUNCATED_IMAGES = False
|
||||
|
||||
assert isinstance(im, PngImagePlugin.PngImageFile)
|
||||
for s in im.text.values():
|
||||
assert len(s) < 1024 * 1024, "Text chunk larger than 1M"
|
||||
|
||||
for s in im.info.values():
|
||||
assert len(s) < 1024 * 1024, "Text chunk larger than 1M"
|
||||
|
||||
|
||||
def test_dos_text() -> None:
|
||||
try:
|
||||
im = Image.open(TEST_FILE)
|
||||
im.load()
|
||||
except ValueError as msg:
|
||||
assert msg, "Decompressed Data Too Large"
|
||||
return
|
||||
|
||||
assert isinstance(im, PngImagePlugin.PngImageFile)
|
||||
for s in im.text.values():
|
||||
assert len(s) < 1024 * 1024, "Text chunk larger than 1M"
|
||||
|
||||
|
||||
def test_dos_total_memory() -> None:
|
||||
im = Image.new("L", (1, 1))
|
||||
compressed_data = zlib.compress(b"a" * 1024 * 1023)
|
||||
|
||||
info = PngImagePlugin.PngInfo()
|
||||
|
||||
for x in range(64):
|
||||
info.add_text(f"t{x}", compressed_data, zip=True)
|
||||
info.add_itxt(f"i{x}", compressed_data, zip=True)
|
||||
|
||||
b = BytesIO()
|
||||
im.save(b, "PNG", pnginfo=info)
|
||||
b.seek(0)
|
||||
|
||||
try:
|
||||
im2 = Image.open(b)
|
||||
except ValueError as msg:
|
||||
assert "Too much memory" in str(msg)
|
||||
return
|
||||
|
||||
total_len = 0
|
||||
assert isinstance(im2, PngImagePlugin.PngImageFile)
|
||||
for txt in im2.text.values():
|
||||
total_len += len(txt)
|
||||
assert total_len < 64 * 1024 * 1024, "Total text chunks greater than 64M"
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
for rst in Path("docs/releasenotes").glob("[1-9]*.rst"):
|
||||
if "TODO" in open(rst).read():
|
||||
sys.exit(f"Error: remove TODO from {rst}")
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
for rst in Path("docs/releasenotes").glob("[1-9]*.rst"):
|
||||
if "TODO" in open(rst).read():
|
||||
sys.exit(f"Error: remove TODO from {rst}")
|
||||
|
|
|
@ -1,43 +1,43 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
|
||||
from PIL import features
|
||||
|
||||
|
||||
def test_wheel_modules() -> None:
|
||||
expected_modules = {"pil", "tkinter", "freetype2", "littlecms2", "webp"}
|
||||
|
||||
# tkinter is not available in cibuildwheel installed CPython on Windows
|
||||
try:
|
||||
import tkinter
|
||||
|
||||
assert tkinter
|
||||
except ImportError:
|
||||
expected_modules.remove("tkinter")
|
||||
|
||||
assert set(features.get_supported_modules()) == expected_modules
|
||||
|
||||
|
||||
def test_wheel_codecs() -> None:
|
||||
expected_codecs = {"jpg", "jpg_2000", "zlib", "libtiff"}
|
||||
|
||||
assert set(features.get_supported_codecs()) == expected_codecs
|
||||
|
||||
|
||||
def test_wheel_features() -> None:
|
||||
expected_features = {
|
||||
"webp_anim",
|
||||
"webp_mux",
|
||||
"transp_webp",
|
||||
"raqm",
|
||||
"fribidi",
|
||||
"harfbuzz",
|
||||
"libjpeg_turbo",
|
||||
"xcb",
|
||||
}
|
||||
|
||||
if sys.platform == "win32":
|
||||
expected_features.remove("xcb")
|
||||
|
||||
assert set(features.get_supported_features()) == expected_features
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
|
||||
from PIL import features
|
||||
|
||||
|
||||
def test_wheel_modules() -> None:
|
||||
expected_modules = {"pil", "tkinter", "freetype2", "littlecms2", "webp"}
|
||||
|
||||
# tkinter is not available in cibuildwheel installed CPython on Windows
|
||||
try:
|
||||
import tkinter
|
||||
|
||||
assert tkinter
|
||||
except ImportError:
|
||||
expected_modules.remove("tkinter")
|
||||
|
||||
assert set(features.get_supported_modules()) == expected_modules
|
||||
|
||||
|
||||
def test_wheel_codecs() -> None:
|
||||
expected_codecs = {"jpg", "jpg_2000", "zlib", "libtiff"}
|
||||
|
||||
assert set(features.get_supported_codecs()) == expected_codecs
|
||||
|
||||
|
||||
def test_wheel_features() -> None:
|
||||
expected_features = {
|
||||
"webp_anim",
|
||||
"webp_mux",
|
||||
"transp_webp",
|
||||
"raqm",
|
||||
"fribidi",
|
||||
"harfbuzz",
|
||||
"libjpeg_turbo",
|
||||
"xcb",
|
||||
}
|
||||
|
||||
if sys.platform == "win32":
|
||||
expected_features.remove("xcb")
|
||||
|
||||
assert set(features.get_supported_features()) == expected_features
|
||||
|
|
|
@ -1,35 +1,35 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import io
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def pytest_report_header(config: pytest.Config) -> str:
|
||||
try:
|
||||
from PIL import features
|
||||
|
||||
with io.StringIO() as out:
|
||||
features.pilinfo(out=out, supported_formats=False)
|
||||
return out.getvalue()
|
||||
except Exception as e:
|
||||
return f"pytest_report_header failed: {e}"
|
||||
|
||||
|
||||
def pytest_configure(config: pytest.Config) -> None:
|
||||
config.addinivalue_line(
|
||||
"markers",
|
||||
"pil_noop_mark: A conditional mark where nothing special happens",
|
||||
)
|
||||
|
||||
# We're marking some tests to ignore valgrind errors and XFAIL them.
|
||||
# Ensure that the mark is defined
|
||||
# even in cases where pytest-valgrind isn't installed
|
||||
try:
|
||||
config.addinivalue_line(
|
||||
"markers",
|
||||
"valgrind_known_error: Tests that have known issues with valgrind",
|
||||
)
|
||||
except Exception:
|
||||
# valgrind is already installed
|
||||
pass
|
||||
from __future__ import annotations
|
||||
|
||||
import io
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def pytest_report_header(config: pytest.Config) -> str:
|
||||
try:
|
||||
from PIL import features
|
||||
|
||||
with io.StringIO() as out:
|
||||
features.pilinfo(out=out, supported_formats=False)
|
||||
return out.getvalue()
|
||||
except Exception as e:
|
||||
return f"pytest_report_header failed: {e}"
|
||||
|
||||
|
||||
def pytest_configure(config: pytest.Config) -> None:
|
||||
config.addinivalue_line(
|
||||
"markers",
|
||||
"pil_noop_mark: A conditional mark where nothing special happens",
|
||||
)
|
||||
|
||||
# We're marking some tests to ignore valgrind errors and XFAIL them.
|
||||
# Ensure that the mark is defined
|
||||
# even in cases where pytest-valgrind isn't installed
|
||||
try:
|
||||
config.addinivalue_line(
|
||||
"markers",
|
||||
"valgrind_known_error: Tests that have known issues with valgrind",
|
||||
)
|
||||
except Exception:
|
||||
# valgrind is already installed
|
||||
pass
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
import os
|
||||
|
||||
if __name__ == "__main__":
|
||||
# create font data chunk for embedding
|
||||
font = "Tests/images/courB08"
|
||||
print(" f._load_pilfont_data(")
|
||||
print(f" # {os.path.basename(font)}")
|
||||
print(" BytesIO(base64.decodestring(b'''")
|
||||
with open(font + ".pil", "rb") as fp:
|
||||
print(base64.b64encode(fp.read()).decode())
|
||||
print("''')), Image.open(BytesIO(base64.decodestring(b'''")
|
||||
with open(font + ".pbm", "rb") as fp:
|
||||
print(base64.b64encode(fp.read()).decode())
|
||||
print("'''))))")
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
import os
|
||||
|
||||
if __name__ == "__main__":
|
||||
# create font data chunk for embedding
|
||||
font = "Tests/images/courB08"
|
||||
print(" f._load_pilfont_data(")
|
||||
print(f" # {os.path.basename(font)}")
|
||||
print(" BytesIO(base64.decodestring(b'''")
|
||||
with open(font + ".pil", "rb") as fp:
|
||||
print(base64.b64encode(fp.read()).decode())
|
||||
print("''')), Image.open(BytesIO(base64.decodestring(b'''")
|
||||
with open(font + ".pbm", "rb") as fp:
|
||||
print(base64.b64encode(fp.read()).decode())
|
||||
print("'''))))")
|
||||
|
|
|
@ -1,40 +1,40 @@
|
|||
DejaVuSans-24-{1,2,4,8}-stripped.ttf are based on DejaVuSans.ttf converted using FontForge to add bitmap strikes and keep only the ASCII range.
|
||||
|
||||
DejaVu Fonts — License
|
||||
Fonts are © Bitstream (see below). DejaVu changes are in public domain. Explanation of copyright is on Gnome page on Bitstream Vera fonts. Glyphs imported from Arev fonts are © Tavmjung Bah (see below)
|
||||
|
||||
Bitstream Vera Fonts Copyright
|
||||
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces.
|
||||
|
||||
The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Bitstream" or the word "Vera".
|
||||
|
||||
This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Bitstream Vera" names.
|
||||
|
||||
The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself.
|
||||
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org.
|
||||
|
||||
Arev Fonts Copyright
|
||||
Original text
|
||||
|
||||
Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the modifications to the Bitstream Vera Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces.
|
||||
|
||||
The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Tavmjong Bah" or the word "Arev".
|
||||
|
||||
This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Tavmjong Bah Arev" names.
|
||||
|
||||
The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself.
|
||||
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Tavmjong Bah shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from Tavmjong Bah. For further information, contact: tavmjong @ free . fr.
|
||||
DejaVuSans-24-{1,2,4,8}-stripped.ttf are based on DejaVuSans.ttf converted using FontForge to add bitmap strikes and keep only the ASCII range.
|
||||
|
||||
DejaVu Fonts — License
|
||||
Fonts are © Bitstream (see below). DejaVu changes are in public domain. Explanation of copyright is on Gnome page on Bitstream Vera fonts. Glyphs imported from Arev fonts are © Tavmjung Bah (see below)
|
||||
|
||||
Bitstream Vera Fonts Copyright
|
||||
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces.
|
||||
|
||||
The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Bitstream" or the word "Vera".
|
||||
|
||||
This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Bitstream Vera" names.
|
||||
|
||||
The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself.
|
||||
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org.
|
||||
|
||||
Arev Fonts Copyright
|
||||
Original text
|
||||
|
||||
Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the modifications to the Bitstream Vera Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces.
|
||||
|
||||
The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Tavmjong Bah" or the word "Arev".
|
||||
|
||||
This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Tavmjong Bah Arev" names.
|
||||
|
||||
The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself.
|
||||
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Tavmjong Bah shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from Tavmjong Bah. For further information, contact: tavmjong @ free . fr.
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
|
||||
NotoNastaliqUrdu-Regular.ttf and NotoSansSymbols-Regular.ttf, from https://github.com/googlei18n/noto-fonts
|
||||
NotoSans-Regular.ttf, from https://www.google.com/get/noto/
|
||||
NotoSansJP-Thin.otf, from https://www.google.com/get/noto/help/cjk/
|
||||
AdobeVFPrototype.ttf, from https://github.com/adobe-fonts/adobe-variable-font-prototype
|
||||
TINY5x3GX.ttf, from http://velvetyne.fr/fonts/tiny
|
||||
ArefRuqaa-Regular.ttf, from https://github.com/google/fonts/tree/master/ofl/arefruqaa
|
||||
ter-x20b.pcf, from http://terminus-font.sourceforge.net/
|
||||
BungeeColor-Regular_colr_Windows.ttf, from https://github.com/djrrb/bungee
|
||||
OpenSans.woff2, from https://fonts.googleapis.com/css?family=Open+Sans
|
||||
|
||||
All of the above fonts are published under the SIL Open Font License (OFL) v1.1 (http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL), which allows you to copy, modify, and redistribute them if you need to.
|
||||
|
||||
FreeMono.ttf is licensed under GPLv3, with the GPL font exception.
|
||||
|
||||
OpenSansCondensed-LightItalic.tt, from https://fonts.google.com/specimen/Open+Sans, under Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
chromacheck-sbix.woff, from https://github.com/RoelN/ChromaCheck, under The MIT License (MIT), Copyright (c) 2018 Roel Nieskens, https://pixelambacht.nl Copyright (c) 2018 Google LLC
|
||||
|
||||
KhmerOSBattambang-Regular.ttf is licensed under LGPL-2.1 or later.
|
||||
|
||||
FreeMono.ttf is licensed under GPLv3.
|
||||
|
||||
10x20-ISO8859-1.pcf, from https://packages.ubuntu.com/xenial/xfonts-base
|
||||
|
||||
"Public domain font. Share and enjoy."
|
||||
|
||||
CBDTTestFont.ttf and EBDTTestFont.ttf from https://github.com/nulano/font-tests are public domain.
|
||||
|
||||
NotoNastaliqUrdu-Regular.ttf and NotoSansSymbols-Regular.ttf, from https://github.com/googlei18n/noto-fonts
|
||||
NotoSans-Regular.ttf, from https://www.google.com/get/noto/
|
||||
NotoSansJP-Thin.otf, from https://www.google.com/get/noto/help/cjk/
|
||||
AdobeVFPrototype.ttf, from https://github.com/adobe-fonts/adobe-variable-font-prototype
|
||||
TINY5x3GX.ttf, from http://velvetyne.fr/fonts/tiny
|
||||
ArefRuqaa-Regular.ttf, from https://github.com/google/fonts/tree/master/ofl/arefruqaa
|
||||
ter-x20b.pcf, from http://terminus-font.sourceforge.net/
|
||||
BungeeColor-Regular_colr_Windows.ttf, from https://github.com/djrrb/bungee
|
||||
OpenSans.woff2, from https://fonts.googleapis.com/css?family=Open+Sans
|
||||
|
||||
All of the above fonts are published under the SIL Open Font License (OFL) v1.1 (http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL), which allows you to copy, modify, and redistribute them if you need to.
|
||||
|
||||
FreeMono.ttf is licensed under GPLv3, with the GPL font exception.
|
||||
|
||||
OpenSansCondensed-LightItalic.tt, from https://fonts.google.com/specimen/Open+Sans, under Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
chromacheck-sbix.woff, from https://github.com/RoelN/ChromaCheck, under The MIT License (MIT), Copyright (c) 2018 Roel Nieskens, https://pixelambacht.nl Copyright (c) 2018 Google LLC
|
||||
|
||||
KhmerOSBattambang-Regular.ttf is licensed under LGPL-2.1 or later.
|
||||
|
||||
FreeMono.ttf is licensed under GPLv3.
|
||||
|
||||
10x20-ISO8859-1.pcf, from https://packages.ubuntu.com/xenial/xfonts-base
|
||||
|
||||
"Public domain font. Share and enjoy."
|
||||
|
||||
CBDTTestFont.ttf and EBDTTestFont.ttf from https://github.com/nulano/font-tests are public domain.
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
STARTFONT
|
||||
FONT ÿ
|
||||
SIZE 10
|
||||
FONTBOUNDINGBOX
|
||||
CHARS
|
||||
STARTCHAR
|
||||
ENCODING
|
||||
BBX 2 5
|
||||
ENDCHAR
|
||||
ENDFONT
|
||||
STARTFONT
|
||||
FONT ÿ
|
||||
SIZE 10
|
||||
FONTBOUNDINGBOX
|
||||
CHARS
|
||||
STARTCHAR
|
||||
ENCODING
|
||||
BBX 2 5
|
||||
ENDCHAR
|
||||
ENDFONT
|
||||
|
|
744
Tests/helper.py
744
Tests/helper.py
|
@ -1,372 +1,372 @@
|
|||
"""
|
||||
Helper functions.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import sysconfig
|
||||
import tempfile
|
||||
from functools import lru_cache
|
||||
from io import BytesIO
|
||||
from typing import Any, Callable, Sequence
|
||||
|
||||
import pytest
|
||||
from packaging.version import parse as parse_version
|
||||
|
||||
from PIL import Image, ImageMath, features
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
uploader = None
|
||||
if os.environ.get("SHOW_ERRORS"):
|
||||
uploader = "show"
|
||||
elif "GITHUB_ACTIONS" in os.environ:
|
||||
uploader = "github_actions"
|
||||
|
||||
|
||||
def upload(a: Image.Image, b: Image.Image) -> str | None:
|
||||
if uploader == "show":
|
||||
# local img.show for errors.
|
||||
a.show()
|
||||
b.show()
|
||||
elif uploader == "github_actions":
|
||||
dir_errors = os.path.join(os.path.dirname(__file__), "errors")
|
||||
os.makedirs(dir_errors, exist_ok=True)
|
||||
tmpdir = tempfile.mkdtemp(dir=dir_errors)
|
||||
a.save(os.path.join(tmpdir, "a.png"))
|
||||
b.save(os.path.join(tmpdir, "b.png"))
|
||||
return tmpdir
|
||||
return None
|
||||
|
||||
|
||||
def convert_to_comparable(
|
||||
a: Image.Image, b: Image.Image
|
||||
) -> tuple[Image.Image, Image.Image]:
|
||||
new_a, new_b = a, b
|
||||
if a.mode == "P":
|
||||
new_a = Image.new("L", a.size)
|
||||
new_b = Image.new("L", b.size)
|
||||
new_a.putdata(a.getdata())
|
||||
new_b.putdata(b.getdata())
|
||||
elif a.mode == "I;16":
|
||||
new_a = a.convert("I")
|
||||
new_b = b.convert("I")
|
||||
return new_a, new_b
|
||||
|
||||
|
||||
def assert_deep_equal(
|
||||
a: Sequence[Any], b: Sequence[Any], msg: str | None = None
|
||||
) -> None:
|
||||
try:
|
||||
assert len(a) == len(b), msg or f"got length {len(a)}, expected {len(b)}"
|
||||
except Exception:
|
||||
assert a == b, msg
|
||||
|
||||
|
||||
def assert_image(
|
||||
im: Image.Image, mode: str, size: tuple[int, int], msg: str | None = None
|
||||
) -> None:
|
||||
if mode is not None:
|
||||
assert im.mode == mode, (
|
||||
msg or f"got mode {repr(im.mode)}, expected {repr(mode)}"
|
||||
)
|
||||
|
||||
if size is not None:
|
||||
assert im.size == size, (
|
||||
msg or f"got size {repr(im.size)}, expected {repr(size)}"
|
||||
)
|
||||
|
||||
|
||||
def assert_image_equal(a: Image.Image, b: Image.Image, msg: str | None = None) -> None:
|
||||
assert a.mode == b.mode, msg or f"got mode {repr(a.mode)}, expected {repr(b.mode)}"
|
||||
assert a.size == b.size, msg or f"got size {repr(a.size)}, expected {repr(b.size)}"
|
||||
if a.tobytes() != b.tobytes():
|
||||
try:
|
||||
url = upload(a, b)
|
||||
if url:
|
||||
logger.error("URL for test images: %s", url)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
pytest.fail(msg or "got different content")
|
||||
|
||||
|
||||
def assert_image_equal_tofile(
|
||||
a: Image.Image, filename: str, msg: str | None = None, mode: str | None = None
|
||||
) -> None:
|
||||
with Image.open(filename) as img:
|
||||
if mode:
|
||||
img = img.convert(mode)
|
||||
assert_image_equal(a, img, msg)
|
||||
|
||||
|
||||
def assert_image_similar(
|
||||
a: Image.Image, b: Image.Image, epsilon: float, msg: str | None = None
|
||||
) -> None:
|
||||
assert a.mode == b.mode, msg or f"got mode {repr(a.mode)}, expected {repr(b.mode)}"
|
||||
assert a.size == b.size, msg or f"got size {repr(a.size)}, expected {repr(b.size)}"
|
||||
|
||||
a, b = convert_to_comparable(a, b)
|
||||
|
||||
diff = 0
|
||||
for ach, bch in zip(a.split(), b.split()):
|
||||
chdiff = ImageMath.lambda_eval(
|
||||
lambda args: abs(args["a"] - args["b"]), a=ach, b=bch
|
||||
).convert("L")
|
||||
diff += sum(i * num for i, num in enumerate(chdiff.histogram()))
|
||||
|
||||
ave_diff = diff / (a.size[0] * a.size[1])
|
||||
try:
|
||||
assert epsilon >= ave_diff, (
|
||||
(msg or "")
|
||||
+ f" average pixel value difference {ave_diff:.4f} > epsilon {epsilon:.4f}"
|
||||
)
|
||||
except Exception as e:
|
||||
try:
|
||||
url = upload(a, b)
|
||||
if url:
|
||||
logger.exception("URL for test images: %s", url)
|
||||
except Exception:
|
||||
pass
|
||||
raise e
|
||||
|
||||
|
||||
def assert_image_similar_tofile(
|
||||
a: Image.Image,
|
||||
filename: str,
|
||||
epsilon: float,
|
||||
msg: str | None = None,
|
||||
mode: str | None = None,
|
||||
) -> None:
|
||||
with Image.open(filename) as img:
|
||||
if mode:
|
||||
img = img.convert(mode)
|
||||
assert_image_similar(a, img, epsilon, msg)
|
||||
|
||||
|
||||
def assert_all_same(items: Sequence[Any], msg: str | None = None) -> None:
|
||||
assert items.count(items[0]) == len(items), msg
|
||||
|
||||
|
||||
def assert_not_all_same(items: Sequence[Any], msg: str | None = None) -> None:
|
||||
assert items.count(items[0]) != len(items), msg
|
||||
|
||||
|
||||
def assert_tuple_approx_equal(
|
||||
actuals: Sequence[int], targets: tuple[int, ...], threshold: int, msg: str
|
||||
) -> None:
|
||||
"""Tests if actuals has values within threshold from targets"""
|
||||
for i, target in enumerate(targets):
|
||||
if not (target - threshold <= actuals[i] <= target + threshold):
|
||||
pytest.fail(msg + ": " + repr(actuals) + " != " + repr(targets))
|
||||
|
||||
|
||||
def skip_unless_feature(feature: str) -> pytest.MarkDecorator:
|
||||
reason = f"{feature} not available"
|
||||
return pytest.mark.skipif(not features.check(feature), reason=reason)
|
||||
|
||||
|
||||
def skip_unless_feature_version(
|
||||
feature: str, required: str, reason: str | None = None
|
||||
) -> pytest.MarkDecorator:
|
||||
version = features.version(feature)
|
||||
if version is None:
|
||||
return pytest.mark.skip(f"{feature} not available")
|
||||
if reason is None:
|
||||
reason = f"{feature} is older than {required}"
|
||||
version_required = parse_version(required)
|
||||
version_available = parse_version(version)
|
||||
return pytest.mark.skipif(version_available < version_required, reason=reason)
|
||||
|
||||
|
||||
def mark_if_feature_version(
|
||||
mark: pytest.MarkDecorator,
|
||||
feature: str,
|
||||
version_blacklist: str,
|
||||
reason: str | None = None,
|
||||
) -> pytest.MarkDecorator:
|
||||
version = features.version(feature)
|
||||
if version is None:
|
||||
return pytest.mark.pil_noop_mark()
|
||||
if reason is None:
|
||||
reason = f"{feature} is {version_blacklist}"
|
||||
version_required = parse_version(version_blacklist)
|
||||
version_available = parse_version(version)
|
||||
if (
|
||||
version_available.major == version_required.major
|
||||
and version_available.minor == version_required.minor
|
||||
):
|
||||
return mark(reason=reason)
|
||||
return pytest.mark.pil_noop_mark()
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform.startswith("win32"), reason="Requires Unix or macOS")
|
||||
class PillowLeakTestCase:
|
||||
# requires unix/macOS
|
||||
iterations = 100 # count
|
||||
mem_limit = 512 # k
|
||||
|
||||
def _get_mem_usage(self) -> float:
|
||||
"""
|
||||
Gets the RUSAGE memory usage, returns in K. Encapsulates the difference
|
||||
between macOS and Linux rss reporting
|
||||
|
||||
:returns: memory usage in kilobytes
|
||||
"""
|
||||
|
||||
from resource import RUSAGE_SELF, getrusage
|
||||
|
||||
mem = getrusage(RUSAGE_SELF).ru_maxrss
|
||||
# man 2 getrusage:
|
||||
# ru_maxrss
|
||||
# This is the maximum resident set size utilized
|
||||
# in bytes on macOS, in kilobytes on Linux
|
||||
return mem / 1024 if sys.platform == "darwin" else mem
|
||||
|
||||
def _test_leak(self, core: Callable[[], None]) -> None:
|
||||
start_mem = self._get_mem_usage()
|
||||
for cycle in range(self.iterations):
|
||||
core()
|
||||
mem = self._get_mem_usage() - start_mem
|
||||
msg = f"memory usage limit exceeded in iteration {cycle}"
|
||||
assert mem < self.mem_limit, msg
|
||||
|
||||
|
||||
# helpers
|
||||
|
||||
|
||||
def fromstring(data: bytes) -> Image.Image:
|
||||
return Image.open(BytesIO(data))
|
||||
|
||||
|
||||
def tostring(im: Image.Image, string_format: str, **options: Any) -> bytes:
|
||||
out = BytesIO()
|
||||
im.save(out, string_format, **options)
|
||||
return out.getvalue()
|
||||
|
||||
|
||||
def hopper(mode: str | None = None) -> Image.Image:
|
||||
# Use caching to reduce reading from disk, but return a copy
|
||||
# so that the cached image isn't modified by the tests
|
||||
# (for fast, isolated, repeatable tests).
|
||||
|
||||
if mode is None:
|
||||
# Always return fresh not-yet-loaded version of image.
|
||||
# Operations on not-yet-loaded images are a separate class of errors
|
||||
# that we should catch.
|
||||
return Image.open("Tests/images/hopper.ppm")
|
||||
|
||||
return _cached_hopper(mode).copy()
|
||||
|
||||
|
||||
@lru_cache
|
||||
def _cached_hopper(mode: str) -> Image.Image:
|
||||
if mode == "F":
|
||||
im = hopper("L")
|
||||
else:
|
||||
im = hopper()
|
||||
if mode.startswith("BGR;"):
|
||||
with pytest.warns(DeprecationWarning):
|
||||
im = im.convert(mode)
|
||||
else:
|
||||
try:
|
||||
im = im.convert(mode)
|
||||
except ImportError:
|
||||
if mode == "LAB":
|
||||
im = Image.open("Tests/images/hopper.Lab.tif")
|
||||
else:
|
||||
raise
|
||||
return im
|
||||
|
||||
|
||||
def djpeg_available() -> bool:
|
||||
if shutil.which("djpeg"):
|
||||
try:
|
||||
subprocess.check_call(["djpeg", "-version"])
|
||||
return True
|
||||
except subprocess.CalledProcessError: # pragma: no cover
|
||||
return False
|
||||
return False
|
||||
|
||||
|
||||
def cjpeg_available() -> bool:
|
||||
if shutil.which("cjpeg"):
|
||||
try:
|
||||
subprocess.check_call(["cjpeg", "-version"])
|
||||
return True
|
||||
except subprocess.CalledProcessError: # pragma: no cover
|
||||
return False
|
||||
return False
|
||||
|
||||
|
||||
def netpbm_available() -> bool:
|
||||
return bool(shutil.which("ppmquant") and shutil.which("ppmtogif"))
|
||||
|
||||
|
||||
def magick_command() -> list[str] | None:
|
||||
if sys.platform == "win32":
|
||||
magickhome = os.environ.get("MAGICK_HOME")
|
||||
if magickhome:
|
||||
imagemagick = [os.path.join(magickhome, "convert.exe")]
|
||||
graphicsmagick = [os.path.join(magickhome, "gm.exe"), "convert"]
|
||||
else:
|
||||
imagemagick = None
|
||||
graphicsmagick = None
|
||||
else:
|
||||
imagemagick = ["convert"]
|
||||
graphicsmagick = ["gm", "convert"]
|
||||
|
||||
if imagemagick and shutil.which(imagemagick[0]):
|
||||
return imagemagick
|
||||
if graphicsmagick and shutil.which(graphicsmagick[0]):
|
||||
return graphicsmagick
|
||||
return None
|
||||
|
||||
|
||||
def on_appveyor() -> bool:
|
||||
return "APPVEYOR" in os.environ
|
||||
|
||||
|
||||
def on_github_actions() -> bool:
|
||||
return "GITHUB_ACTIONS" in os.environ
|
||||
|
||||
|
||||
def on_ci() -> bool:
|
||||
# GitHub Actions and AppVeyor have "CI"
|
||||
return "CI" in os.environ
|
||||
|
||||
|
||||
def is_big_endian() -> bool:
|
||||
return sys.byteorder == "big"
|
||||
|
||||
|
||||
def is_ppc64le() -> bool:
|
||||
import platform
|
||||
|
||||
return platform.machine() == "ppc64le"
|
||||
|
||||
|
||||
def is_win32() -> bool:
|
||||
return sys.platform.startswith("win32")
|
||||
|
||||
|
||||
def is_pypy() -> bool:
|
||||
return hasattr(sys, "pypy_translation_info")
|
||||
|
||||
|
||||
def is_mingw() -> bool:
|
||||
return sysconfig.get_platform() == "mingw"
|
||||
|
||||
|
||||
class CachedProperty:
|
||||
def __init__(self, func: Callable[[Any], Any]) -> None:
|
||||
self.func = func
|
||||
|
||||
def __get__(self, instance: Any, cls: type[Any] | None = None) -> Any:
|
||||
result = instance.__dict__[self.func.__name__] = self.func(instance)
|
||||
return result
|
||||
"""
|
||||
Helper functions.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import sysconfig
|
||||
import tempfile
|
||||
from functools import lru_cache
|
||||
from io import BytesIO
|
||||
from typing import Any, Callable, Sequence
|
||||
|
||||
import pytest
|
||||
from packaging.version import parse as parse_version
|
||||
|
||||
from PIL import Image, ImageMath, features
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
uploader = None
|
||||
if os.environ.get("SHOW_ERRORS"):
|
||||
uploader = "show"
|
||||
elif "GITHUB_ACTIONS" in os.environ:
|
||||
uploader = "github_actions"
|
||||
|
||||
|
||||
def upload(a: Image.Image, b: Image.Image) -> str | None:
|
||||
if uploader == "show":
|
||||
# local img.show for errors.
|
||||
a.show()
|
||||
b.show()
|
||||
elif uploader == "github_actions":
|
||||
dir_errors = os.path.join(os.path.dirname(__file__), "errors")
|
||||
os.makedirs(dir_errors, exist_ok=True)
|
||||
tmpdir = tempfile.mkdtemp(dir=dir_errors)
|
||||
a.save(os.path.join(tmpdir, "a.png"))
|
||||
b.save(os.path.join(tmpdir, "b.png"))
|
||||
return tmpdir
|
||||
return None
|
||||
|
||||
|
||||
def convert_to_comparable(
|
||||
a: Image.Image, b: Image.Image
|
||||
) -> tuple[Image.Image, Image.Image]:
|
||||
new_a, new_b = a, b
|
||||
if a.mode == "P":
|
||||
new_a = Image.new("L", a.size)
|
||||
new_b = Image.new("L", b.size)
|
||||
new_a.putdata(a.getdata())
|
||||
new_b.putdata(b.getdata())
|
||||
elif a.mode == "I;16":
|
||||
new_a = a.convert("I")
|
||||
new_b = b.convert("I")
|
||||
return new_a, new_b
|
||||
|
||||
|
||||
def assert_deep_equal(
|
||||
a: Sequence[Any], b: Sequence[Any], msg: str | None = None
|
||||
) -> None:
|
||||
try:
|
||||
assert len(a) == len(b), msg or f"got length {len(a)}, expected {len(b)}"
|
||||
except Exception:
|
||||
assert a == b, msg
|
||||
|
||||
|
||||
def assert_image(
|
||||
im: Image.Image, mode: str, size: tuple[int, int], msg: str | None = None
|
||||
) -> None:
|
||||
if mode is not None:
|
||||
assert im.mode == mode, (
|
||||
msg or f"got mode {repr(im.mode)}, expected {repr(mode)}"
|
||||
)
|
||||
|
||||
if size is not None:
|
||||
assert im.size == size, (
|
||||
msg or f"got size {repr(im.size)}, expected {repr(size)}"
|
||||
)
|
||||
|
||||
|
||||
def assert_image_equal(a: Image.Image, b: Image.Image, msg: str | None = None) -> None:
|
||||
assert a.mode == b.mode, msg or f"got mode {repr(a.mode)}, expected {repr(b.mode)}"
|
||||
assert a.size == b.size, msg or f"got size {repr(a.size)}, expected {repr(b.size)}"
|
||||
if a.tobytes() != b.tobytes():
|
||||
try:
|
||||
url = upload(a, b)
|
||||
if url:
|
||||
logger.error("URL for test images: %s", url)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
pytest.fail(msg or "got different content")
|
||||
|
||||
|
||||
def assert_image_equal_tofile(
|
||||
a: Image.Image, filename: str, msg: str | None = None, mode: str | None = None
|
||||
) -> None:
|
||||
with Image.open(filename) as img:
|
||||
if mode:
|
||||
img = img.convert(mode)
|
||||
assert_image_equal(a, img, msg)
|
||||
|
||||
|
||||
def assert_image_similar(
|
||||
a: Image.Image, b: Image.Image, epsilon: float, msg: str | None = None
|
||||
) -> None:
|
||||
assert a.mode == b.mode, msg or f"got mode {repr(a.mode)}, expected {repr(b.mode)}"
|
||||
assert a.size == b.size, msg or f"got size {repr(a.size)}, expected {repr(b.size)}"
|
||||
|
||||
a, b = convert_to_comparable(a, b)
|
||||
|
||||
diff = 0
|
||||
for ach, bch in zip(a.split(), b.split()):
|
||||
chdiff = ImageMath.lambda_eval(
|
||||
lambda args: abs(args["a"] - args["b"]), a=ach, b=bch
|
||||
).convert("L")
|
||||
diff += sum(i * num for i, num in enumerate(chdiff.histogram()))
|
||||
|
||||
ave_diff = diff / (a.size[0] * a.size[1])
|
||||
try:
|
||||
assert epsilon >= ave_diff, (
|
||||
(msg or "")
|
||||
+ f" average pixel value difference {ave_diff:.4f} > epsilon {epsilon:.4f}"
|
||||
)
|
||||
except Exception as e:
|
||||
try:
|
||||
url = upload(a, b)
|
||||
if url:
|
||||
logger.exception("URL for test images: %s", url)
|
||||
except Exception:
|
||||
pass
|
||||
raise e
|
||||
|
||||
|
||||
def assert_image_similar_tofile(
|
||||
a: Image.Image,
|
||||
filename: str,
|
||||
epsilon: float,
|
||||
msg: str | None = None,
|
||||
mode: str | None = None,
|
||||
) -> None:
|
||||
with Image.open(filename) as img:
|
||||
if mode:
|
||||
img = img.convert(mode)
|
||||
assert_image_similar(a, img, epsilon, msg)
|
||||
|
||||
|
||||
def assert_all_same(items: Sequence[Any], msg: str | None = None) -> None:
|
||||
assert items.count(items[0]) == len(items), msg
|
||||
|
||||
|
||||
def assert_not_all_same(items: Sequence[Any], msg: str | None = None) -> None:
|
||||
assert items.count(items[0]) != len(items), msg
|
||||
|
||||
|
||||
def assert_tuple_approx_equal(
|
||||
actuals: Sequence[int], targets: tuple[int, ...], threshold: int, msg: str
|
||||
) -> None:
|
||||
"""Tests if actuals has values within threshold from targets"""
|
||||
for i, target in enumerate(targets):
|
||||
if not (target - threshold <= actuals[i] <= target + threshold):
|
||||
pytest.fail(msg + ": " + repr(actuals) + " != " + repr(targets))
|
||||
|
||||
|
||||
def skip_unless_feature(feature: str) -> pytest.MarkDecorator:
|
||||
reason = f"{feature} not available"
|
||||
return pytest.mark.skipif(not features.check(feature), reason=reason)
|
||||
|
||||
|
||||
def skip_unless_feature_version(
|
||||
feature: str, required: str, reason: str | None = None
|
||||
) -> pytest.MarkDecorator:
|
||||
version = features.version(feature)
|
||||
if version is None:
|
||||
return pytest.mark.skip(f"{feature} not available")
|
||||
if reason is None:
|
||||
reason = f"{feature} is older than {required}"
|
||||
version_required = parse_version(required)
|
||||
version_available = parse_version(version)
|
||||
return pytest.mark.skipif(version_available < version_required, reason=reason)
|
||||
|
||||
|
||||
def mark_if_feature_version(
|
||||
mark: pytest.MarkDecorator,
|
||||
feature: str,
|
||||
version_blacklist: str,
|
||||
reason: str | None = None,
|
||||
) -> pytest.MarkDecorator:
|
||||
version = features.version(feature)
|
||||
if version is None:
|
||||
return pytest.mark.pil_noop_mark()
|
||||
if reason is None:
|
||||
reason = f"{feature} is {version_blacklist}"
|
||||
version_required = parse_version(version_blacklist)
|
||||
version_available = parse_version(version)
|
||||
if (
|
||||
version_available.major == version_required.major
|
||||
and version_available.minor == version_required.minor
|
||||
):
|
||||
return mark(reason=reason)
|
||||
return pytest.mark.pil_noop_mark()
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform.startswith("win32"), reason="Requires Unix or macOS")
|
||||
class PillowLeakTestCase:
|
||||
# requires unix/macOS
|
||||
iterations = 100 # count
|
||||
mem_limit = 512 # k
|
||||
|
||||
def _get_mem_usage(self) -> float:
|
||||
"""
|
||||
Gets the RUSAGE memory usage, returns in K. Encapsulates the difference
|
||||
between macOS and Linux rss reporting
|
||||
|
||||
:returns: memory usage in kilobytes
|
||||
"""
|
||||
|
||||
from resource import RUSAGE_SELF, getrusage
|
||||
|
||||
mem = getrusage(RUSAGE_SELF).ru_maxrss
|
||||
# man 2 getrusage:
|
||||
# ru_maxrss
|
||||
# This is the maximum resident set size utilized
|
||||
# in bytes on macOS, in kilobytes on Linux
|
||||
return mem / 1024 if sys.platform == "darwin" else mem
|
||||
|
||||
def _test_leak(self, core: Callable[[], None]) -> None:
|
||||
start_mem = self._get_mem_usage()
|
||||
for cycle in range(self.iterations):
|
||||
core()
|
||||
mem = self._get_mem_usage() - start_mem
|
||||
msg = f"memory usage limit exceeded in iteration {cycle}"
|
||||
assert mem < self.mem_limit, msg
|
||||
|
||||
|
||||
# helpers
|
||||
|
||||
|
||||
def fromstring(data: bytes) -> Image.Image:
|
||||
return Image.open(BytesIO(data))
|
||||
|
||||
|
||||
def tostring(im: Image.Image, string_format: str, **options: Any) -> bytes:
|
||||
out = BytesIO()
|
||||
im.save(out, string_format, **options)
|
||||
return out.getvalue()
|
||||
|
||||
|
||||
def hopper(mode: str | None = None) -> Image.Image:
|
||||
# Use caching to reduce reading from disk, but return a copy
|
||||
# so that the cached image isn't modified by the tests
|
||||
# (for fast, isolated, repeatable tests).
|
||||
|
||||
if mode is None:
|
||||
# Always return fresh not-yet-loaded version of image.
|
||||
# Operations on not-yet-loaded images are a separate class of errors
|
||||
# that we should catch.
|
||||
return Image.open("Tests/images/hopper.ppm")
|
||||
|
||||
return _cached_hopper(mode).copy()
|
||||
|
||||
|
||||
@lru_cache
|
||||
def _cached_hopper(mode: str) -> Image.Image:
|
||||
if mode == "F":
|
||||
im = hopper("L")
|
||||
else:
|
||||
im = hopper()
|
||||
if mode.startswith("BGR;"):
|
||||
with pytest.warns(DeprecationWarning):
|
||||
im = im.convert(mode)
|
||||
else:
|
||||
try:
|
||||
im = im.convert(mode)
|
||||
except ImportError:
|
||||
if mode == "LAB":
|
||||
im = Image.open("Tests/images/hopper.Lab.tif")
|
||||
else:
|
||||
raise
|
||||
return im
|
||||
|
||||
|
||||
def djpeg_available() -> bool:
|
||||
if shutil.which("djpeg"):
|
||||
try:
|
||||
subprocess.check_call(["djpeg", "-version"])
|
||||
return True
|
||||
except subprocess.CalledProcessError: # pragma: no cover
|
||||
return False
|
||||
return False
|
||||
|
||||
|
||||
def cjpeg_available() -> bool:
|
||||
if shutil.which("cjpeg"):
|
||||
try:
|
||||
subprocess.check_call(["cjpeg", "-version"])
|
||||
return True
|
||||
except subprocess.CalledProcessError: # pragma: no cover
|
||||
return False
|
||||
return False
|
||||
|
||||
|
||||
def netpbm_available() -> bool:
|
||||
return bool(shutil.which("ppmquant") and shutil.which("ppmtogif"))
|
||||
|
||||
|
||||
def magick_command() -> list[str] | None:
|
||||
if sys.platform == "win32":
|
||||
magickhome = os.environ.get("MAGICK_HOME")
|
||||
if magickhome:
|
||||
imagemagick = [os.path.join(magickhome, "convert.exe")]
|
||||
graphicsmagick = [os.path.join(magickhome, "gm.exe"), "convert"]
|
||||
else:
|
||||
imagemagick = None
|
||||
graphicsmagick = None
|
||||
else:
|
||||
imagemagick = ["convert"]
|
||||
graphicsmagick = ["gm", "convert"]
|
||||
|
||||
if imagemagick and shutil.which(imagemagick[0]):
|
||||
return imagemagick
|
||||
if graphicsmagick and shutil.which(graphicsmagick[0]):
|
||||
return graphicsmagick
|
||||
return None
|
||||
|
||||
|
||||
def on_appveyor() -> bool:
|
||||
return "APPVEYOR" in os.environ
|
||||
|
||||
|
||||
def on_github_actions() -> bool:
|
||||
return "GITHUB_ACTIONS" in os.environ
|
||||
|
||||
|
||||
def on_ci() -> bool:
|
||||
# GitHub Actions and AppVeyor have "CI"
|
||||
return "CI" in os.environ
|
||||
|
||||
|
||||
def is_big_endian() -> bool:
|
||||
return sys.byteorder == "big"
|
||||
|
||||
|
||||
def is_ppc64le() -> bool:
|
||||
import platform
|
||||
|
||||
return platform.machine() == "ppc64le"
|
||||
|
||||
|
||||
def is_win32() -> bool:
|
||||
return sys.platform.startswith("win32")
|
||||
|
||||
|
||||
def is_pypy() -> bool:
|
||||
return hasattr(sys, "pypy_translation_info")
|
||||
|
||||
|
||||
def is_mingw() -> bool:
|
||||
return sysconfig.get_platform() == "mingw"
|
||||
|
||||
|
||||
class CachedProperty:
|
||||
def __init__(self, func: Callable[[Any], Any]) -> None:
|
||||
self.func = func
|
||||
|
||||
def __get__(self, instance: Any, cls: type[Any] | None = None) -> Any:
|
||||
result = instance.__dict__[self.func.__name__] = self.func(instance)
|
||||
return result
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
from http://www.color.org/srgbprofiles.xalter
|
||||
|
||||
Terms of use
|
||||
|
||||
To anyone who acknowledges that the file "sRGB_v4_ICC_preference.icc"
|
||||
is provided "AS IS" WITH NO EXPRESS OR IMPLIED WARRANTY, permission
|
||||
to use, copy and distribute this file for any purpose is hereby
|
||||
granted without fee, provided that the file is not changed including
|
||||
the ICC copyright notice tag, and that the name of ICC shall not be
|
||||
used in advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission. ICC makes no
|
||||
representations about the suitability of this software for any
|
||||
purpose.
|
||||
|
||||
|
||||
To anyone who acknowledges that the file
|
||||
"sRGB_IEC61966-2-1_black_scaled.icc" is provided "AS IS" WITH NO
|
||||
EXPRESS OR IMPLIED WARRANTY, permission to use, copy and distribute
|
||||
these file for any purpose is hereby granted without fee, provided
|
||||
that the file is not changed including the ICC copyright notice tag,
|
||||
and that the name of ICC shall not be used in advertising or publicity
|
||||
pertaining to distribution of the software without specific, written
|
||||
prior permission. ICC makes no representations about the suitability
|
||||
of this software for any purpose.
|
||||
from http://www.color.org/srgbprofiles.xalter
|
||||
|
||||
Terms of use
|
||||
|
||||
To anyone who acknowledges that the file "sRGB_v4_ICC_preference.icc"
|
||||
is provided "AS IS" WITH NO EXPRESS OR IMPLIED WARRANTY, permission
|
||||
to use, copy and distribute this file for any purpose is hereby
|
||||
granted without fee, provided that the file is not changed including
|
||||
the ICC copyright notice tag, and that the name of ICC shall not be
|
||||
used in advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission. ICC makes no
|
||||
representations about the suitability of this software for any
|
||||
purpose.
|
||||
|
||||
|
||||
To anyone who acknowledges that the file
|
||||
"sRGB_IEC61966-2-1_black_scaled.icc" is provided "AS IS" WITH NO
|
||||
EXPRESS OR IMPLIED WARRANTY, permission to use, copy and distribute
|
||||
these file for any purpose is hereby granted without fee, provided
|
||||
that the file is not changed including the ICC copyright notice tag,
|
||||
and that the name of ICC shall not be used in advertising or publicity
|
||||
pertaining to distribution of the software without specific, written
|
||||
prior permission. ICC makes no representations about the suitability
|
||||
of this software for any purpose.
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
GIMP Palette
|
||||
Name: badpaletteentry
|
||||
Columns: 4
|
||||
#
|
||||
0 0 0 Index 3
|
||||
65 38
|
||||
103 62 49 Index 6
|
||||
79 73 72 Index 7
|
||||
114 101 97 Index 8
|
||||
208 127 100 Index 9
|
||||
151 144 142 Index 10
|
||||
221 207 199 Index 11
|
||||
GIMP Palette
|
||||
Name: badpaletteentry
|
||||
Columns: 4
|
||||
#
|
||||
0 0 0 Index 3
|
||||
65 38
|
||||
103 62 49 Index 6
|
||||
79 73 72 Index 7
|
||||
114 101 97 Index 8
|
||||
208 127 100 Index 9
|
||||
151 144 142 Index 10
|
||||
221 207 199 Index 11
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
GIMP Palette
|
||||
Name: badpalettefile
|
||||
Columns: 4
|
||||
#
|
||||
0 0 0 Index 3
|
||||
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
103 62 49 Index 6
|
||||
79 73 72 Index 7
|
||||
114 101 97 Index 8
|
||||
208 127 100 Index 9
|
||||
151 144 142 Index 10
|
||||
221 207 199 Index 11
|
||||
GIMP Palette
|
||||
Name: badpalettefile
|
||||
Columns: 4
|
||||
#
|
||||
0 0 0 Index 3
|
||||
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
103 62 49 Index 6
|
||||
79 73 72 Index 7
|
||||
114 101 97 Index 8
|
||||
208 127 100 Index 9
|
||||
151 144 142 Index 10
|
||||
221 207 199 Index 11
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
These images are from the bmpsuite:
|
||||
https://github.com/jsummers/bmpsuite and are in the public domain
|
||||
according to the readme in the project.
|
||||
These images are from the bmpsuite:
|
||||
https://github.com/jsummers/bmpsuite and are in the public domain
|
||||
according to the readme in the project.
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,28 +1,28 @@
|
|||
#This is the script that was used to create our sample EPS files
|
||||
#We used the following version of the gnuplot program
|
||||
#G N U P L O T
|
||||
#Version 4.6 patchlevel 3 last modified 2013-04-12
|
||||
#Build System: Darwin x86_64
|
||||
|
||||
#This file will generate the non_zero_bb.eps variant, in order to get the
|
||||
#zero_bb.eps variant you will need to edit line6 in the result file to
|
||||
#be "%%BoundingBox: 0 0 460 352" instead of "%%BoundingBox: 50 50 410 302"
|
||||
|
||||
set t postscript eps color
|
||||
set o "sample.eps"
|
||||
set dummy u,v
|
||||
set key bmargin center horizontal Right noreverse enhanced autotitles nobox
|
||||
set parametric
|
||||
set view 50, 30, 1, 1
|
||||
set isosamples 10, 10
|
||||
set hidden3d back offset 1 trianglepattern 3 undefined 1 altdiagonal bentover
|
||||
set ticslevel 0
|
||||
set title "Interlocking Tori"
|
||||
|
||||
set style line 1 lt 1 lw 1 pt 3 lc rgb "red"
|
||||
set style line 2 lt 1 lw 1 pt 3 lc rgb "blue"
|
||||
|
||||
set urange [ -3.14159 : 3.14159 ] noreverse nowriteback
|
||||
set vrange [ -3.14159 : 3.14159 ] noreverse nowriteback
|
||||
splot cos(u)+.5*cos(u)*cos(v),sin(u)+.5*sin(u)*cos(v),.5*sin(v) ls 1,\
|
||||
1+cos(u)+.5*cos(u)*cos(v),.5*sin(v),sin(u)+.5*sin(u)*cos(v) ls 2
|
||||
#This is the script that was used to create our sample EPS files
|
||||
#We used the following version of the gnuplot program
|
||||
#G N U P L O T
|
||||
#Version 4.6 patchlevel 3 last modified 2013-04-12
|
||||
#Build System: Darwin x86_64
|
||||
|
||||
#This file will generate the non_zero_bb.eps variant, in order to get the
|
||||
#zero_bb.eps variant you will need to edit line6 in the result file to
|
||||
#be "%%BoundingBox: 0 0 460 352" instead of "%%BoundingBox: 50 50 410 302"
|
||||
|
||||
set t postscript eps color
|
||||
set o "sample.eps"
|
||||
set dummy u,v
|
||||
set key bmargin center horizontal Right noreverse enhanced autotitles nobox
|
||||
set parametric
|
||||
set view 50, 30, 1, 1
|
||||
set isosamples 10, 10
|
||||
set hidden3d back offset 1 trianglepattern 3 undefined 1 altdiagonal bentover
|
||||
set ticslevel 0
|
||||
set title "Interlocking Tori"
|
||||
|
||||
set style line 1 lt 1 lw 1 pt 3 lc rgb "red"
|
||||
set style line 2 lt 1 lw 1 pt 3 lc rgb "blue"
|
||||
|
||||
set urange [ -3.14159 : 3.14159 ] noreverse nowriteback
|
||||
set vrange [ -3.14159 : 3.14159 ] noreverse nowriteback
|
||||
splot cos(u)+.5*cos(u)*cos(v),sin(u)+.5*sin(u)*cos(v),.5*sin(v) ls 1,\
|
||||
1+cos(u)+.5*cos(u)*cos(v),.5*sin(v),sin(u)+.5*sin(u)*cos(v) ls 2
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
GIMP Palette
|
||||
Name: custompalette
|
||||
Columns: 4
|
||||
#
|
||||
0 0 0 Index 3
|
||||
65 38 30 Index 4
|
||||
103 62 49 Index 6
|
||||
79 73 72 Index 7
|
||||
114 101 97 Index 8
|
||||
208 127 100 Index 9
|
||||
151 144 142 Index 10
|
||||
221 207 199 Index 11
|
||||
GIMP Palette
|
||||
Name: custompalette
|
||||
Columns: 4
|
||||
#
|
||||
0 0 0 Index 3
|
||||
65 38 30 Index 4
|
||||
103 62 49 Index 6
|
||||
79 73 72 Index 7
|
||||
114 101 97 Index 8
|
||||
208 127 100 Index 9
|
||||
151 144 142 Index 10
|
||||
221 207 199 Index 11
|
||||
|
|
|
@ -1 +1 @@
|
|||
Is this because a file-originating field is being interpreted as a *signed* int32, allowing it to provide negative values for 'advance'?
|
||||
Is this because a file-originating field is being interpreted as a *signed* int32, allowing it to provide negative values for 'advance'?
|
||||
|
|
|
@ -1 +1 @@
|
|||
Image.open(...).seek(212)
|
||||
Image.open(...).seek(212)
|
||||
|
|
|
@ -1 +1 @@
|
|||
ridiculous bytes value passed to ImagingFliDecode
|
||||
ridiculous bytes value passed to ImagingFliDecode
|
||||
|
|
|
@ -1 +1 @@
|
|||
im = Image.open(d); im.seek(0); im.getdata()
|
||||
im = Image.open(d); im.seek(0); im.getdata()
|
||||
|
|
|
@ -1 +1 @@
|
|||
failure to check input buffer (`data`) boundaries in BRUN chunk
|
||||
failure to check input buffer (`data`) boundaries in BRUN chunk
|
||||
|
|
|
@ -1 +1 @@
|
|||
im = Image.open(d); im.seek(0); im.getdata()
|
||||
im = Image.open(d); im.seek(0); im.getdata()
|
||||
|
|
|
@ -1 +1 @@
|
|||
failure to check input buffer (`data`) boundaries in LC chunk
|
||||
failure to check input buffer (`data`) boundaries in LC chunk
|
||||
|
|
|
@ -1 +1 @@
|
|||
im = Image.open(d); im.seek(0); im.getdata()
|
||||
im = Image.open(d); im.seek(0); im.getdata()
|
||||
|
|
|
@ -1 +1 @@
|
|||
failure to check input buffer (`data`) boundaries in SS2 chunk
|
||||
failure to check input buffer (`data`) boundaries in SS2 chunk
|
||||
|
|
|
@ -1 +1 @@
|
|||
im = Image.open(d); im.seek(0); im.getdata()
|
||||
im = Image.open(d); im.seek(0); im.getdata()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
GIMP Gradient
|
||||
4
|
||||
0.000000 0.351923 0.534893 1.000000 1.000000 1.000000 0.910000 0.730303 0.510606 1.000000 0.480000 1 0
|
||||
0.501504 0.611002 0.637730 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1.000000 1 0
|
||||
0.931891 0.951264 1.000000 0.531255 0.316078 1.031173 1.000000 0.000000 0.000000 0.000000 1.000000 0 0
|
||||
GIMP Gradient
|
||||
4
|
||||
0.000000 0.351923 0.534893 1.000000 1.000000 1.000000 0.910000 0.730303 0.510606 1.000000 0.480000 1 0
|
||||
0.501504 0.611002 0.637730 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1.000000 1 0
|
||||
0.931891 0.951264 1.000000 0.531255 0.316078 1.031173 1.000000 0.000000 0.000000 0.000000 1.000000 0 0
|
||||
0.810551 0.881217 0.921883 0.717576 0.441331 0.081217 1.000000 0.751576 0.410331 0.081217 1.000000 0 0
|
|
@ -1,7 +1,7 @@
|
|||
GIMP Gradient
|
||||
Name: A GIMP 1.3 gradient file
|
||||
4
|
||||
0.000000 0.351923 0.534893 1.000000 1.000000 1.000000 0.910000 0.730303 0.510606 1.000000 0.480000 1 0
|
||||
0.501504 0.611002 0.637730 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1.000000 1 0
|
||||
0.931891 0.951264 1.000000 0.531255 0.316078 1.031173 1.000000 0.000000 0.000000 0.000000 1.000000 0 0
|
||||
GIMP Gradient
|
||||
Name: A GIMP 1.3 gradient file
|
||||
4
|
||||
0.000000 0.351923 0.534893 1.000000 1.000000 1.000000 0.910000 0.730303 0.510606 1.000000 0.480000 1 0
|
||||
0.501504 0.611002 0.637730 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1.000000 1 0
|
||||
0.931891 0.951264 1.000000 0.531255 0.316078 1.031173 1.000000 0.000000 0.000000 0.000000 1.000000 0 0
|
||||
0.810551 0.881217 0.921883 0.717576 0.441331 0.081217 1.000000 0.751576 0.410331 0.081217 1.000000 0 0
|
|
@ -1,174 +1,174 @@
|
|||
#define hopper_width 128
|
||||
#define hopper_height 128
|
||||
static char hopper_bits[] = {
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0x3D, 0x80, 0x96, 0xDA, 0xB6, 0xD6, 0x2A,
|
||||
0xA9, 0x6D, 0x25, 0x29, 0xFF, 0xFF, 0xFF, 0xBF, 0xFE, 0x7D, 0xC0, 0xFB,
|
||||
0x69, 0x69, 0xA9, 0xD5, 0x96, 0x96, 0x5E, 0x9A, 0xFF, 0xFF, 0xFF, 0x9F,
|
||||
0xFE, 0xFD, 0x80, 0xFF, 0x97, 0xB6, 0x5A, 0x6A, 0x5D, 0x6D, 0x5A, 0x62,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFD, 0xC1, 0xCF, 0x5F, 0x89, 0xA5, 0xD5,
|
||||
0xAA, 0x92, 0xA5, 0x59, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFD, 0xF8, 0x00,
|
||||
0xB8, 0x59, 0xAA, 0x56, 0xDA, 0x5A, 0x56, 0x49, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFE, 0xFC, 0xF9, 0x00, 0xF0, 0xA6, 0x55, 0xA9, 0x65, 0xA5, 0xA9, 0xA2,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFD, 0x71, 0x00, 0x60, 0x70, 0xAA, 0x54,
|
||||
0xAA, 0x5A, 0x54, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0x38, 0x00,
|
||||
0xE0, 0x80, 0x55, 0xAB, 0x55, 0x75, 0xAB, 0x56, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFE, 0x1D, 0x70, 0x00, 0xF0, 0x00, 0xAE, 0xAA, 0xAA, 0xA6, 0x95, 0x55,
|
||||
0xFB, 0xFF, 0xFF, 0xFF, 0xFE, 0x1D, 0xF0, 0x00, 0xF0, 0x00, 0x50, 0x55,
|
||||
0x55, 0x59, 0x6A, 0xAA, 0xF3, 0xFF, 0xFF, 0xFF, 0xFE, 0x04, 0xF0, 0x00,
|
||||
0xF0, 0x00, 0xA4, 0xAA, 0xA9, 0xA5, 0x95, 0x55, 0x21, 0xFF, 0xFF, 0xFF,
|
||||
0xFE, 0x01, 0xF8, 0x00, 0xF0, 0x00, 0x50, 0x55, 0x56, 0x5A, 0x6A, 0xAA,
|
||||
0x83, 0x9F, 0xFF, 0xFF, 0xFE, 0x00, 0xFC, 0x00, 0xF0, 0x01, 0x50, 0xD5,
|
||||
0x95, 0x95, 0xA5, 0x5A, 0x83, 0x9F, 0xFF, 0xFF, 0xFE, 0x81, 0xFF, 0x00,
|
||||
0xE0, 0x0B, 0xA0, 0xAA, 0x7A, 0x6A, 0x5A, 0x65, 0x80, 0x1F, 0xF0, 0xFF,
|
||||
0xFE, 0xF0, 0xFF, 0x00, 0xF0, 0x3F, 0x50, 0x55, 0xA5, 0xB5, 0xA5, 0xAA,
|
||||
0x00, 0x1F, 0xF8, 0xFD, 0xFE, 0xF0, 0xF7, 0x00, 0xF0, 0x6D, 0xA0, 0xAA,
|
||||
0x5A, 0x6A, 0x5A, 0x55, 0x83, 0x0F, 0xF8, 0xC9, 0xFE, 0x79, 0x00, 0xF8,
|
||||
0x02, 0xC0, 0x81, 0x55, 0xAD, 0xD5, 0xA5, 0xA6, 0xE3, 0x03, 0xFC, 0xC0,
|
||||
0xFE, 0xFF, 0x04, 0xF0, 0x00, 0x80, 0x63, 0xAA, 0x52, 0x2A, 0x5A, 0x58,
|
||||
0xE7, 0x03, 0xFC, 0xE1, 0xFE, 0xFF, 0x2F, 0xFC, 0x03, 0x0C, 0xFE, 0x55,
|
||||
0xA9, 0x55, 0x66, 0x15, 0xF3, 0x0F, 0x7C, 0xF0, 0xFE, 0xFF, 0xFF, 0xFD,
|
||||
0xEF, 0x38, 0xFF, 0xAA, 0x56, 0xAA, 0x99, 0xAA, 0xF7, 0x1F, 0x78, 0xF0,
|
||||
0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0xFF, 0x55, 0xAA, 0x5B, 0x66, 0xA4,
|
||||
0xFF, 0x9F, 0xFD, 0xF0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB,
|
||||
0x65, 0xA4, 0x99, 0x1B, 0xFF, 0xDF, 0xFF, 0xE0, 0xFE, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x69, 0x51, 0x5A, 0x24, 0x62, 0xFF, 0xDF, 0xFF, 0xEC,
|
||||
0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x95, 0xAA, 0x24, 0x59, 0x55,
|
||||
0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x25,
|
||||
0x49, 0xAD, 0x55, 0x2A, 0xFF, 0xFF, 0xFF, 0xFC, 0xFD, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x9B, 0xA5, 0x52, 0x2A, 0x94, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x67, 0x64, 0xC1, 0x92, 0x6D,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x95,
|
||||
0x49, 0x2C, 0x55, 0x92, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF,
|
||||
0x7F, 0xFF, 0xFF, 0x15, 0xB4, 0x62, 0x44, 0x49, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFD, 0xFF, 0x51, 0x30, 0x03, 0xE0, 0xFF, 0x53, 0x03, 0x89, 0x96, 0x92,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x7F, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xCD,
|
||||
0x68, 0x19, 0x68, 0x99, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x1F, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFF, 0x13, 0x4A, 0x64, 0x23, 0x49, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x47, 0x8A, 0xA4, 0xD8, 0x30,
|
||||
0xFE, 0xFF, 0xFF, 0xFF, 0xFC, 0x07, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x39,
|
||||
0x29, 0x49, 0x06, 0x86, 0xCC, 0xFF, 0xFF, 0xFF, 0xFC, 0x03, 0x00, 0x00,
|
||||
0x80, 0x00, 0xF2, 0x81, 0x50, 0x31, 0xA2, 0x8C, 0xE4, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x0A, 0x08, 0x00, 0x00, 0x00, 0xF0, 0xA7, 0x46, 0x8C, 0x28, 0x31,
|
||||
0xC0, 0xFC, 0xFF, 0xFF, 0xFC, 0x03, 0x10, 0x00, 0xE0, 0x01, 0xE0, 0x19,
|
||||
0x41, 0x61, 0x66, 0x05, 0xE0, 0xB8, 0xFF, 0xFF, 0x7E, 0x0C, 0x44, 0x00,
|
||||
0x40, 0xBF, 0xEF, 0x41, 0x5C, 0x04, 0x00, 0xA8, 0xF0, 0xC1, 0xFF, 0xFF,
|
||||
0xFE, 0x21, 0x9E, 0x00, 0xE0, 0xFF, 0xED, 0xA5, 0x12, 0x92, 0xDB, 0xA2,
|
||||
0xE0, 0xC0, 0xFF, 0xFF, 0x7D, 0xFA, 0xFF, 0x00, 0x70, 0x00, 0xFF, 0x42,
|
||||
0x84, 0x0C, 0x00, 0x08, 0xC0, 0xC0, 0xFF, 0xFC, 0x7D, 0xFF, 0x90, 0x07,
|
||||
0xC0, 0x1F, 0xDB, 0x0A, 0x24, 0xC8, 0x68, 0x09, 0xCC, 0xC0, 0x7F, 0xFE,
|
||||
0x1E, 0x7F, 0x3E, 0x00, 0xD4, 0xFF, 0x3E, 0x60, 0x81, 0x21, 0x02, 0xA0,
|
||||
0xFC, 0xE0, 0x7F, 0xFF, 0xCE, 0x9F, 0xFF, 0x05, 0xFA, 0xFF, 0xBF, 0x04,
|
||||
0x24, 0x0A, 0x61, 0x1B, 0xFC, 0xC0, 0xBF, 0xFF, 0xAC, 0x7D, 0xFF, 0x03,
|
||||
0x40, 0x1F, 0x80, 0x91, 0xC2, 0xA0, 0x05, 0x80, 0xFF, 0x8D, 0x7F, 0xFF,
|
||||
0xEF, 0xF5, 0xDF, 0x00, 0x00, 0x94, 0x42, 0x81, 0x01, 0x10, 0x92, 0x85,
|
||||
0xFF, 0xFD, 0xFF, 0xFE, 0x2C, 0x62, 0x03, 0x00, 0x20, 0x00, 0x10, 0x2B,
|
||||
0x24, 0x82, 0x00, 0x20, 0xFF, 0xFD, 0xFF, 0xFF, 0xBD, 0x55, 0x01, 0x00,
|
||||
0x40, 0x00, 0x08, 0x19, 0x81, 0x58, 0x54, 0x14, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x3C, 0x82, 0x05, 0x08, 0x00, 0x24, 0x20, 0x81, 0x24, 0x02, 0x02, 0x82,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0x82, 0x01, 0x00, 0x00, 0x00, 0x69, 0x22,
|
||||
0x90, 0xA0, 0x49, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0x2D, 0x26, 0x00, 0x00,
|
||||
0x00, 0x00, 0x20, 0x20, 0x0A, 0x02, 0x20, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x04, 0x81, 0x01, 0x00, 0x10, 0x00, 0xA0, 0x04, 0x02, 0x0A, 0x09, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x81, 0x19, 0x02, 0x02, 0x00, 0x00, 0x02, 0x42,
|
||||
0x50, 0xA0, 0x20, 0x95, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x60, 0x00, 0x01,
|
||||
0x80, 0x02, 0x42, 0x52, 0x40, 0x20, 0xA0, 0x20, 0xFF, 0xFF, 0xFF, 0x7F,
|
||||
0x00, 0x00, 0x8C, 0x01, 0x40, 0x00, 0x00, 0x00, 0x06, 0x06, 0x09, 0x05,
|
||||
0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x50, 0x00, 0x00, 0x40, 0x00, 0x02, 0x18,
|
||||
0xA0, 0x90, 0x84, 0x64, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x10, 0x81, 0x07,
|
||||
0xD0, 0x00, 0x48, 0x82, 0x02, 0x02, 0x20, 0x00, 0xFF, 0xFF, 0xFF, 0x0F,
|
||||
0x00, 0x04, 0xC0, 0x7E, 0x9F, 0x01, 0x10, 0x04, 0x00, 0x00, 0x24, 0x25,
|
||||
0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x60, 0x48, 0xC0, 0xC1, 0x13, 0x00, 0x41,
|
||||
0x9A, 0x99, 0x81, 0x00, 0xFF, 0xFF, 0xFF, 0x03, 0x40, 0x40, 0x60, 0x00,
|
||||
0x84, 0x0B, 0x00, 0x50, 0x02, 0x40, 0x24, 0x90, 0xFF, 0xFF, 0xFF, 0x01,
|
||||
0x00, 0x00, 0x32, 0x00, 0x00, 0x57, 0x00, 0x04, 0x40, 0x02, 0x01, 0x05,
|
||||
0xF8, 0xFF, 0xFF, 0x01, 0x40, 0x00, 0x38, 0x00, 0x00, 0x0E, 0x10, 0x05,
|
||||
0x99, 0x0A, 0xA4, 0x0A, 0xFC, 0xFF, 0x7F, 0x00, 0x80, 0x30, 0x10, 0x00,
|
||||
0x00, 0x84, 0x04, 0x60, 0x00, 0x50, 0x00, 0x60, 0xFC, 0xFF, 0xFF, 0x00,
|
||||
0x00, 0x3A, 0x08, 0x00, 0x00, 0x04, 0x8E, 0x06, 0x00, 0x41, 0x56, 0x00,
|
||||
0xF8, 0xFE, 0xFF, 0x01, 0x80, 0x79, 0xA0, 0x7F, 0xFF, 0x01, 0x06, 0x20,
|
||||
0x51, 0x08, 0x00, 0x2A, 0xF8, 0xFF, 0xFF, 0x00, 0xE0, 0x3F, 0xE0, 0xAF,
|
||||
0x00, 0x00, 0x06, 0x11, 0x91, 0x52, 0x02, 0x92, 0xF8, 0xFF, 0xFF, 0x00,
|
||||
0x00, 0x7F, 0x00, 0x00, 0x80, 0x02, 0x02, 0x08, 0x00, 0x00, 0x50, 0x00,
|
||||
0x7E, 0xFF, 0xFF, 0x01, 0x40, 0x7F, 0x00, 0x00, 0x10, 0x80, 0x86, 0x00,
|
||||
0x08, 0x09, 0x06, 0x08, 0xFF, 0xFF, 0xFF, 0x01, 0x80, 0xFC, 0x20, 0x51,
|
||||
0x0D, 0x20, 0x23, 0x94, 0x91, 0x50, 0x20, 0x92, 0xFF, 0xFE, 0xFF, 0x03,
|
||||
0x20, 0x70, 0x05, 0x88, 0x01, 0x80, 0x21, 0x06, 0x84, 0x44, 0x80, 0x25,
|
||||
0xFF, 0xFF, 0xFF, 0x03, 0x40, 0xEA, 0x90, 0x00, 0x20, 0xA4, 0x05, 0x00,
|
||||
0x00, 0x10, 0x26, 0x00, 0xFF, 0xFF, 0xFF, 0x07, 0x40, 0xD8, 0x08, 0x00,
|
||||
0x00, 0xA0, 0x81, 0x92, 0x01, 0x01, 0x84, 0x40, 0xFF, 0xFF, 0xFF, 0x0F,
|
||||
0x20, 0xC3, 0x42, 0x00, 0x00, 0x0A, 0x24, 0x00, 0x44, 0x48, 0x20, 0x25,
|
||||
0xFF, 0xFF, 0xFF, 0x0F, 0x20, 0xD5, 0x05, 0x02, 0x00, 0x46, 0x12, 0x40,
|
||||
0x02, 0x22, 0x44, 0x00, 0xFF, 0xFF, 0xFF, 0x1F, 0x90, 0x50, 0x90, 0x00,
|
||||
0x00, 0x9A, 0x40, 0x02, 0x40, 0x00, 0x10, 0x64, 0xFF, 0xFF, 0xFF, 0x1F,
|
||||
0x98, 0x62, 0x7C, 0x10, 0x11, 0xDF, 0x07, 0x14, 0x28, 0x08, 0x01, 0x05,
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0x20, 0x74, 0xF8, 0xE5, 0xEA, 0x87, 0x23, 0x01,
|
||||
0x81, 0x11, 0x48, 0x20, 0xFF, 0xFF, 0xFF, 0x1F, 0x50, 0x38, 0xF2, 0xFF,
|
||||
0xFF, 0xC7, 0x8F, 0x80, 0x00, 0x84, 0x40, 0x04, 0xFF, 0xFF, 0xFF, 0xBF,
|
||||
0x68, 0x3D, 0xE9, 0xFF, 0x7F, 0xC1, 0x1F, 0x28, 0x14, 0x10, 0x06, 0x50,
|
||||
0xFF, 0xFF, 0xFF, 0x3F, 0x90, 0x3F, 0x81, 0xFE, 0x5F, 0x89, 0x3F, 0x82,
|
||||
0x00, 0x02, 0xA2, 0x01, 0xFF, 0xFF, 0xFF, 0xBF, 0xB0, 0x3F, 0xB1, 0xFF,
|
||||
0xBF, 0xC1, 0xFF, 0x00, 0x82, 0x80, 0x00, 0x24, 0xFF, 0xFB, 0xFF, 0x7F,
|
||||
0xF8, 0x3F, 0xA9, 0xFC, 0x5F, 0x81, 0xFF, 0x0F, 0x08, 0x00, 0x04, 0x48,
|
||||
0xFF, 0xF0, 0xFF, 0xBF, 0xFC, 0x3F, 0x41, 0xEB, 0xE7, 0xC0, 0xFF, 0x1F,
|
||||
0x40, 0x24, 0x40, 0x01, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0x3F, 0xB3, 0x7D,
|
||||
0xAD, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0xA0, 0x90, 0x7F, 0xC0, 0xFF, 0xFF,
|
||||
0xFF, 0x3F, 0x43, 0xFA, 0x27, 0xC0, 0xFF, 0xFF, 0x93, 0x51, 0x04, 0x04,
|
||||
0x7F, 0x80, 0xFF, 0xFF, 0xFF, 0x3F, 0x60, 0x6D, 0x56, 0xC0, 0xFF, 0xFF,
|
||||
0x1F, 0x20, 0x0A, 0x40, 0x7F, 0x80, 0xFF, 0xFF, 0xFF, 0x3F, 0x84, 0x6A,
|
||||
0x6D, 0xC0, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x02, 0x7F, 0x00, 0xFF, 0xFF,
|
||||
0xFF, 0x3F, 0x2C, 0xBA, 0x22, 0xC0, 0xFF, 0xFF, 0xFF, 0x87, 0x04, 0x98,
|
||||
0x7F, 0x80, 0xFF, 0xFF, 0xFF, 0x3F, 0x48, 0x66, 0xD5, 0xC0, 0xFF, 0xFF,
|
||||
0xFF, 0x3F, 0x90, 0x02, 0x7F, 0xC0, 0xFF, 0xFF, 0xFF, 0x7F, 0x80, 0xA6,
|
||||
0x63, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x24, 0x7F, 0xF8, 0xFF, 0xFF,
|
||||
0xFF, 0x7F, 0x90, 0x78, 0x3A, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x27, 0x00,
|
||||
0x7F, 0xFC, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xF9, 0x06, 0xF0, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x8F, 0x61, 0x7F, 0xFC, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xA4,
|
||||
0x0B, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x04, 0x7F, 0xFE, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x00, 0xD0, 0x01, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x08,
|
||||
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x00, 0xF8, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x61, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x88,
|
||||
0x01, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFE, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x48,
|
||||
0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x07, 0xFC, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x01, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xD0,
|
||||
0x0F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x69, 0xF8, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x03, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x05,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0x3F, 0xFE, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x21, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0xFF,
|
||||
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6B,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x23, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xE0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xEF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x27,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x0F, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x03, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F,
|
||||
0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2F,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xF8, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00,
|
||||
0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x3F, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F,
|
||||
0xF8, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0x03, 0x00, 0xF1, 0xFF, 0x7F, 0x80,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0x03, 0x00,
|
||||
0xF0, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x7F, 0x6F, 0xFD, 0xFF, 0xFF, 0x1F,
|
||||
0xF8, 0xFF, 0x03, 0x00, 0xE0, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0x7F, 0x7F,
|
||||
0xFD, 0xFF, 0xFF, 0x7F, 0xF0, 0xFF, 0x03, 0x00, 0xC0, 0xFF, 0xFF, 0x90,
|
||||
0xFF, 0xFF, 0x5F, 0xA2, 0xF4, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0x03, 0x00,
|
||||
0x80, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0x0F, 0xAA, 0x42, 0xF1, 0xFF, 0x3F,
|
||||
0xF8, 0xFF, 0xAF, 0x00, 0x80, 0xFF, 0xFF, 0xD9, 0xFF, 0xFF, 0x0F, 0x02,
|
||||
0x64, 0xF1, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0x3F, 0xC2, 0xFF, 0xFF, 0xDB,
|
||||
0xFF, 0xFF, 0xCB, 0xD1, 0xDA, 0xF7, 0xFF, 0x7F, 0xF8, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x71, 0x44, 0xFC, 0xF6, 0xFF, 0x3F,
|
||||
0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB0, 0xC0,
|
||||
0xA8, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFC, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F,
|
||||
0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x7F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, };
|
||||
#define hopper_width 128
|
||||
#define hopper_height 128
|
||||
static char hopper_bits[] = {
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0x3D, 0x80, 0x96, 0xDA, 0xB6, 0xD6, 0x2A,
|
||||
0xA9, 0x6D, 0x25, 0x29, 0xFF, 0xFF, 0xFF, 0xBF, 0xFE, 0x7D, 0xC0, 0xFB,
|
||||
0x69, 0x69, 0xA9, 0xD5, 0x96, 0x96, 0x5E, 0x9A, 0xFF, 0xFF, 0xFF, 0x9F,
|
||||
0xFE, 0xFD, 0x80, 0xFF, 0x97, 0xB6, 0x5A, 0x6A, 0x5D, 0x6D, 0x5A, 0x62,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFD, 0xC1, 0xCF, 0x5F, 0x89, 0xA5, 0xD5,
|
||||
0xAA, 0x92, 0xA5, 0x59, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFD, 0xF8, 0x00,
|
||||
0xB8, 0x59, 0xAA, 0x56, 0xDA, 0x5A, 0x56, 0x49, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFE, 0xFC, 0xF9, 0x00, 0xF0, 0xA6, 0x55, 0xA9, 0x65, 0xA5, 0xA9, 0xA2,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFD, 0x71, 0x00, 0x60, 0x70, 0xAA, 0x54,
|
||||
0xAA, 0x5A, 0x54, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0x38, 0x00,
|
||||
0xE0, 0x80, 0x55, 0xAB, 0x55, 0x75, 0xAB, 0x56, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFE, 0x1D, 0x70, 0x00, 0xF0, 0x00, 0xAE, 0xAA, 0xAA, 0xA6, 0x95, 0x55,
|
||||
0xFB, 0xFF, 0xFF, 0xFF, 0xFE, 0x1D, 0xF0, 0x00, 0xF0, 0x00, 0x50, 0x55,
|
||||
0x55, 0x59, 0x6A, 0xAA, 0xF3, 0xFF, 0xFF, 0xFF, 0xFE, 0x04, 0xF0, 0x00,
|
||||
0xF0, 0x00, 0xA4, 0xAA, 0xA9, 0xA5, 0x95, 0x55, 0x21, 0xFF, 0xFF, 0xFF,
|
||||
0xFE, 0x01, 0xF8, 0x00, 0xF0, 0x00, 0x50, 0x55, 0x56, 0x5A, 0x6A, 0xAA,
|
||||
0x83, 0x9F, 0xFF, 0xFF, 0xFE, 0x00, 0xFC, 0x00, 0xF0, 0x01, 0x50, 0xD5,
|
||||
0x95, 0x95, 0xA5, 0x5A, 0x83, 0x9F, 0xFF, 0xFF, 0xFE, 0x81, 0xFF, 0x00,
|
||||
0xE0, 0x0B, 0xA0, 0xAA, 0x7A, 0x6A, 0x5A, 0x65, 0x80, 0x1F, 0xF0, 0xFF,
|
||||
0xFE, 0xF0, 0xFF, 0x00, 0xF0, 0x3F, 0x50, 0x55, 0xA5, 0xB5, 0xA5, 0xAA,
|
||||
0x00, 0x1F, 0xF8, 0xFD, 0xFE, 0xF0, 0xF7, 0x00, 0xF0, 0x6D, 0xA0, 0xAA,
|
||||
0x5A, 0x6A, 0x5A, 0x55, 0x83, 0x0F, 0xF8, 0xC9, 0xFE, 0x79, 0x00, 0xF8,
|
||||
0x02, 0xC0, 0x81, 0x55, 0xAD, 0xD5, 0xA5, 0xA6, 0xE3, 0x03, 0xFC, 0xC0,
|
||||
0xFE, 0xFF, 0x04, 0xF0, 0x00, 0x80, 0x63, 0xAA, 0x52, 0x2A, 0x5A, 0x58,
|
||||
0xE7, 0x03, 0xFC, 0xE1, 0xFE, 0xFF, 0x2F, 0xFC, 0x03, 0x0C, 0xFE, 0x55,
|
||||
0xA9, 0x55, 0x66, 0x15, 0xF3, 0x0F, 0x7C, 0xF0, 0xFE, 0xFF, 0xFF, 0xFD,
|
||||
0xEF, 0x38, 0xFF, 0xAA, 0x56, 0xAA, 0x99, 0xAA, 0xF7, 0x1F, 0x78, 0xF0,
|
||||
0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0xFF, 0x55, 0xAA, 0x5B, 0x66, 0xA4,
|
||||
0xFF, 0x9F, 0xFD, 0xF0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB,
|
||||
0x65, 0xA4, 0x99, 0x1B, 0xFF, 0xDF, 0xFF, 0xE0, 0xFE, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x69, 0x51, 0x5A, 0x24, 0x62, 0xFF, 0xDF, 0xFF, 0xEC,
|
||||
0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x95, 0xAA, 0x24, 0x59, 0x55,
|
||||
0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x25,
|
||||
0x49, 0xAD, 0x55, 0x2A, 0xFF, 0xFF, 0xFF, 0xFC, 0xFD, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x9B, 0xA5, 0x52, 0x2A, 0x94, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x67, 0x64, 0xC1, 0x92, 0x6D,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x95,
|
||||
0x49, 0x2C, 0x55, 0x92, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF,
|
||||
0x7F, 0xFF, 0xFF, 0x15, 0xB4, 0x62, 0x44, 0x49, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFD, 0xFF, 0x51, 0x30, 0x03, 0xE0, 0xFF, 0x53, 0x03, 0x89, 0x96, 0x92,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x7F, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xCD,
|
||||
0x68, 0x19, 0x68, 0x99, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x1F, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFF, 0x13, 0x4A, 0x64, 0x23, 0x49, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x47, 0x8A, 0xA4, 0xD8, 0x30,
|
||||
0xFE, 0xFF, 0xFF, 0xFF, 0xFC, 0x07, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x39,
|
||||
0x29, 0x49, 0x06, 0x86, 0xCC, 0xFF, 0xFF, 0xFF, 0xFC, 0x03, 0x00, 0x00,
|
||||
0x80, 0x00, 0xF2, 0x81, 0x50, 0x31, 0xA2, 0x8C, 0xE4, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x0A, 0x08, 0x00, 0x00, 0x00, 0xF0, 0xA7, 0x46, 0x8C, 0x28, 0x31,
|
||||
0xC0, 0xFC, 0xFF, 0xFF, 0xFC, 0x03, 0x10, 0x00, 0xE0, 0x01, 0xE0, 0x19,
|
||||
0x41, 0x61, 0x66, 0x05, 0xE0, 0xB8, 0xFF, 0xFF, 0x7E, 0x0C, 0x44, 0x00,
|
||||
0x40, 0xBF, 0xEF, 0x41, 0x5C, 0x04, 0x00, 0xA8, 0xF0, 0xC1, 0xFF, 0xFF,
|
||||
0xFE, 0x21, 0x9E, 0x00, 0xE0, 0xFF, 0xED, 0xA5, 0x12, 0x92, 0xDB, 0xA2,
|
||||
0xE0, 0xC0, 0xFF, 0xFF, 0x7D, 0xFA, 0xFF, 0x00, 0x70, 0x00, 0xFF, 0x42,
|
||||
0x84, 0x0C, 0x00, 0x08, 0xC0, 0xC0, 0xFF, 0xFC, 0x7D, 0xFF, 0x90, 0x07,
|
||||
0xC0, 0x1F, 0xDB, 0x0A, 0x24, 0xC8, 0x68, 0x09, 0xCC, 0xC0, 0x7F, 0xFE,
|
||||
0x1E, 0x7F, 0x3E, 0x00, 0xD4, 0xFF, 0x3E, 0x60, 0x81, 0x21, 0x02, 0xA0,
|
||||
0xFC, 0xE0, 0x7F, 0xFF, 0xCE, 0x9F, 0xFF, 0x05, 0xFA, 0xFF, 0xBF, 0x04,
|
||||
0x24, 0x0A, 0x61, 0x1B, 0xFC, 0xC0, 0xBF, 0xFF, 0xAC, 0x7D, 0xFF, 0x03,
|
||||
0x40, 0x1F, 0x80, 0x91, 0xC2, 0xA0, 0x05, 0x80, 0xFF, 0x8D, 0x7F, 0xFF,
|
||||
0xEF, 0xF5, 0xDF, 0x00, 0x00, 0x94, 0x42, 0x81, 0x01, 0x10, 0x92, 0x85,
|
||||
0xFF, 0xFD, 0xFF, 0xFE, 0x2C, 0x62, 0x03, 0x00, 0x20, 0x00, 0x10, 0x2B,
|
||||
0x24, 0x82, 0x00, 0x20, 0xFF, 0xFD, 0xFF, 0xFF, 0xBD, 0x55, 0x01, 0x00,
|
||||
0x40, 0x00, 0x08, 0x19, 0x81, 0x58, 0x54, 0x14, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x3C, 0x82, 0x05, 0x08, 0x00, 0x24, 0x20, 0x81, 0x24, 0x02, 0x02, 0x82,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0x82, 0x01, 0x00, 0x00, 0x00, 0x69, 0x22,
|
||||
0x90, 0xA0, 0x49, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0x2D, 0x26, 0x00, 0x00,
|
||||
0x00, 0x00, 0x20, 0x20, 0x0A, 0x02, 0x20, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x04, 0x81, 0x01, 0x00, 0x10, 0x00, 0xA0, 0x04, 0x02, 0x0A, 0x09, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x81, 0x19, 0x02, 0x02, 0x00, 0x00, 0x02, 0x42,
|
||||
0x50, 0xA0, 0x20, 0x95, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x60, 0x00, 0x01,
|
||||
0x80, 0x02, 0x42, 0x52, 0x40, 0x20, 0xA0, 0x20, 0xFF, 0xFF, 0xFF, 0x7F,
|
||||
0x00, 0x00, 0x8C, 0x01, 0x40, 0x00, 0x00, 0x00, 0x06, 0x06, 0x09, 0x05,
|
||||
0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x50, 0x00, 0x00, 0x40, 0x00, 0x02, 0x18,
|
||||
0xA0, 0x90, 0x84, 0x64, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x10, 0x81, 0x07,
|
||||
0xD0, 0x00, 0x48, 0x82, 0x02, 0x02, 0x20, 0x00, 0xFF, 0xFF, 0xFF, 0x0F,
|
||||
0x00, 0x04, 0xC0, 0x7E, 0x9F, 0x01, 0x10, 0x04, 0x00, 0x00, 0x24, 0x25,
|
||||
0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x60, 0x48, 0xC0, 0xC1, 0x13, 0x00, 0x41,
|
||||
0x9A, 0x99, 0x81, 0x00, 0xFF, 0xFF, 0xFF, 0x03, 0x40, 0x40, 0x60, 0x00,
|
||||
0x84, 0x0B, 0x00, 0x50, 0x02, 0x40, 0x24, 0x90, 0xFF, 0xFF, 0xFF, 0x01,
|
||||
0x00, 0x00, 0x32, 0x00, 0x00, 0x57, 0x00, 0x04, 0x40, 0x02, 0x01, 0x05,
|
||||
0xF8, 0xFF, 0xFF, 0x01, 0x40, 0x00, 0x38, 0x00, 0x00, 0x0E, 0x10, 0x05,
|
||||
0x99, 0x0A, 0xA4, 0x0A, 0xFC, 0xFF, 0x7F, 0x00, 0x80, 0x30, 0x10, 0x00,
|
||||
0x00, 0x84, 0x04, 0x60, 0x00, 0x50, 0x00, 0x60, 0xFC, 0xFF, 0xFF, 0x00,
|
||||
0x00, 0x3A, 0x08, 0x00, 0x00, 0x04, 0x8E, 0x06, 0x00, 0x41, 0x56, 0x00,
|
||||
0xF8, 0xFE, 0xFF, 0x01, 0x80, 0x79, 0xA0, 0x7F, 0xFF, 0x01, 0x06, 0x20,
|
||||
0x51, 0x08, 0x00, 0x2A, 0xF8, 0xFF, 0xFF, 0x00, 0xE0, 0x3F, 0xE0, 0xAF,
|
||||
0x00, 0x00, 0x06, 0x11, 0x91, 0x52, 0x02, 0x92, 0xF8, 0xFF, 0xFF, 0x00,
|
||||
0x00, 0x7F, 0x00, 0x00, 0x80, 0x02, 0x02, 0x08, 0x00, 0x00, 0x50, 0x00,
|
||||
0x7E, 0xFF, 0xFF, 0x01, 0x40, 0x7F, 0x00, 0x00, 0x10, 0x80, 0x86, 0x00,
|
||||
0x08, 0x09, 0x06, 0x08, 0xFF, 0xFF, 0xFF, 0x01, 0x80, 0xFC, 0x20, 0x51,
|
||||
0x0D, 0x20, 0x23, 0x94, 0x91, 0x50, 0x20, 0x92, 0xFF, 0xFE, 0xFF, 0x03,
|
||||
0x20, 0x70, 0x05, 0x88, 0x01, 0x80, 0x21, 0x06, 0x84, 0x44, 0x80, 0x25,
|
||||
0xFF, 0xFF, 0xFF, 0x03, 0x40, 0xEA, 0x90, 0x00, 0x20, 0xA4, 0x05, 0x00,
|
||||
0x00, 0x10, 0x26, 0x00, 0xFF, 0xFF, 0xFF, 0x07, 0x40, 0xD8, 0x08, 0x00,
|
||||
0x00, 0xA0, 0x81, 0x92, 0x01, 0x01, 0x84, 0x40, 0xFF, 0xFF, 0xFF, 0x0F,
|
||||
0x20, 0xC3, 0x42, 0x00, 0x00, 0x0A, 0x24, 0x00, 0x44, 0x48, 0x20, 0x25,
|
||||
0xFF, 0xFF, 0xFF, 0x0F, 0x20, 0xD5, 0x05, 0x02, 0x00, 0x46, 0x12, 0x40,
|
||||
0x02, 0x22, 0x44, 0x00, 0xFF, 0xFF, 0xFF, 0x1F, 0x90, 0x50, 0x90, 0x00,
|
||||
0x00, 0x9A, 0x40, 0x02, 0x40, 0x00, 0x10, 0x64, 0xFF, 0xFF, 0xFF, 0x1F,
|
||||
0x98, 0x62, 0x7C, 0x10, 0x11, 0xDF, 0x07, 0x14, 0x28, 0x08, 0x01, 0x05,
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0x20, 0x74, 0xF8, 0xE5, 0xEA, 0x87, 0x23, 0x01,
|
||||
0x81, 0x11, 0x48, 0x20, 0xFF, 0xFF, 0xFF, 0x1F, 0x50, 0x38, 0xF2, 0xFF,
|
||||
0xFF, 0xC7, 0x8F, 0x80, 0x00, 0x84, 0x40, 0x04, 0xFF, 0xFF, 0xFF, 0xBF,
|
||||
0x68, 0x3D, 0xE9, 0xFF, 0x7F, 0xC1, 0x1F, 0x28, 0x14, 0x10, 0x06, 0x50,
|
||||
0xFF, 0xFF, 0xFF, 0x3F, 0x90, 0x3F, 0x81, 0xFE, 0x5F, 0x89, 0x3F, 0x82,
|
||||
0x00, 0x02, 0xA2, 0x01, 0xFF, 0xFF, 0xFF, 0xBF, 0xB0, 0x3F, 0xB1, 0xFF,
|
||||
0xBF, 0xC1, 0xFF, 0x00, 0x82, 0x80, 0x00, 0x24, 0xFF, 0xFB, 0xFF, 0x7F,
|
||||
0xF8, 0x3F, 0xA9, 0xFC, 0x5F, 0x81, 0xFF, 0x0F, 0x08, 0x00, 0x04, 0x48,
|
||||
0xFF, 0xF0, 0xFF, 0xBF, 0xFC, 0x3F, 0x41, 0xEB, 0xE7, 0xC0, 0xFF, 0x1F,
|
||||
0x40, 0x24, 0x40, 0x01, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0x3F, 0xB3, 0x7D,
|
||||
0xAD, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0xA0, 0x90, 0x7F, 0xC0, 0xFF, 0xFF,
|
||||
0xFF, 0x3F, 0x43, 0xFA, 0x27, 0xC0, 0xFF, 0xFF, 0x93, 0x51, 0x04, 0x04,
|
||||
0x7F, 0x80, 0xFF, 0xFF, 0xFF, 0x3F, 0x60, 0x6D, 0x56, 0xC0, 0xFF, 0xFF,
|
||||
0x1F, 0x20, 0x0A, 0x40, 0x7F, 0x80, 0xFF, 0xFF, 0xFF, 0x3F, 0x84, 0x6A,
|
||||
0x6D, 0xC0, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x02, 0x7F, 0x00, 0xFF, 0xFF,
|
||||
0xFF, 0x3F, 0x2C, 0xBA, 0x22, 0xC0, 0xFF, 0xFF, 0xFF, 0x87, 0x04, 0x98,
|
||||
0x7F, 0x80, 0xFF, 0xFF, 0xFF, 0x3F, 0x48, 0x66, 0xD5, 0xC0, 0xFF, 0xFF,
|
||||
0xFF, 0x3F, 0x90, 0x02, 0x7F, 0xC0, 0xFF, 0xFF, 0xFF, 0x7F, 0x80, 0xA6,
|
||||
0x63, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x24, 0x7F, 0xF8, 0xFF, 0xFF,
|
||||
0xFF, 0x7F, 0x90, 0x78, 0x3A, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x27, 0x00,
|
||||
0x7F, 0xFC, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xF9, 0x06, 0xF0, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x8F, 0x61, 0x7F, 0xFC, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xA4,
|
||||
0x0B, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x04, 0x7F, 0xFE, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x00, 0xD0, 0x01, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x08,
|
||||
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x00, 0xF8, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x61, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x88,
|
||||
0x01, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFE, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x48,
|
||||
0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x07, 0xFC, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x01, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xD0,
|
||||
0x0F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x69, 0xF8, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x03, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x05,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0x3F, 0xFE, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x21, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0xFF,
|
||||
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6B,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x23, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xE0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xEF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x27,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x0F, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x03, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F,
|
||||
0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2F,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xF8, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00,
|
||||
0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x3F, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F,
|
||||
0xF8, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0x03, 0x00, 0xF1, 0xFF, 0x7F, 0x80,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0x03, 0x00,
|
||||
0xF0, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x7F, 0x6F, 0xFD, 0xFF, 0xFF, 0x1F,
|
||||
0xF8, 0xFF, 0x03, 0x00, 0xE0, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0x7F, 0x7F,
|
||||
0xFD, 0xFF, 0xFF, 0x7F, 0xF0, 0xFF, 0x03, 0x00, 0xC0, 0xFF, 0xFF, 0x90,
|
||||
0xFF, 0xFF, 0x5F, 0xA2, 0xF4, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0x03, 0x00,
|
||||
0x80, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0x0F, 0xAA, 0x42, 0xF1, 0xFF, 0x3F,
|
||||
0xF8, 0xFF, 0xAF, 0x00, 0x80, 0xFF, 0xFF, 0xD9, 0xFF, 0xFF, 0x0F, 0x02,
|
||||
0x64, 0xF1, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0x3F, 0xC2, 0xFF, 0xFF, 0xDB,
|
||||
0xFF, 0xFF, 0xCB, 0xD1, 0xDA, 0xF7, 0xFF, 0x7F, 0xF8, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x71, 0x44, 0xFC, 0xF6, 0xFF, 0x3F,
|
||||
0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB0, 0xC0,
|
||||
0xA8, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFC, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F,
|
||||
0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x7F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, };
|
||||
|
|
|
@ -1,178 +1,178 @@
|
|||
/* XPM */
|
||||
static char *hopper[] = {
|
||||
/* columns rows colors chars-per-pixel */
|
||||
"128 128 44 1 ",
|
||||
" c #110E13",
|
||||
". c #2A1110",
|
||||
"X c #13122C",
|
||||
"o c #25192A",
|
||||
"O c #312831",
|
||||
"+ c #302219",
|
||||
"@ c #5F241A",
|
||||
"# c #6F4832",
|
||||
"$ c #17174A",
|
||||
"% c #26264F",
|
||||
"& c #65595D",
|
||||
"* c #4B3C54",
|
||||
"= c #8E1F1A",
|
||||
"- c #914E33",
|
||||
"; c #A75335",
|
||||
": c #AC6736",
|
||||
"> c #B26F4E",
|
||||
", c #9B6657",
|
||||
"< c #CA7652",
|
||||
"1 c #CC7866",
|
||||
"2 c #C25135",
|
||||
"3 c #B0896D",
|
||||
"4 c #D28859",
|
||||
"5 c #D28E6D",
|
||||
"6 c #E79371",
|
||||
"7 c #E5A36E",
|
||||
"8 c #D58932",
|
||||
"9 c #3E65AE",
|
||||
"0 c #4970B5",
|
||||
"q c #606D95",
|
||||
"w c #557CC1",
|
||||
"e c #91778A",
|
||||
"r c #6A86B9",
|
||||
"t c #5C83C3",
|
||||
"y c #6D8FCA",
|
||||
"u c #7799E3",
|
||||
"i c #A89A9D",
|
||||
"p c #CFAA90",
|
||||
"a c #F4B08F",
|
||||
"s c #D6A799",
|
||||
"d c #ECCCAB",
|
||||
"f c #F9F4F4",
|
||||
"g c #E3D8D5",
|
||||
"h c #AAAECA",
|
||||
/* pixels */
|
||||
"$XX$$XXX$%$$$$$$$$$$$$$$$$$$$egip3dr %% @p# Oqgffgfgfgo%q999q9999999999999999999099999099099990999999909909990w999000wwww00w00w0",
|
||||
"$$X$X$XX$$$$$$$$9$$$$XX$$$$$$ws&7+O&%$Xo@3#XXX&ihffggg%%9q*9*%q99qq9q99999999999999090900909909909099999999999999999000wwwwww0ww",
|
||||
"X$X$$XXX$$$$$$$$$$$$$$$$$$$$$eq@i#+$$$%X#pOX$%$%*dfffgiX%%OX%XO*%**990909999999009090990900999999099990999w999990990000wwwwwwwww",
|
||||
"$XX$$$XX$$$$$$$$$$$$XX$$$$$$$*O*7#XX%$%X@p*XX$%Xohfi3hOXOoX*r3*OOO%O99099999q0q990990009090909000999090999999099909999ww0w0000w0",
|
||||
"$XX$$XXX$$$$$$$$$9$$$$$$$$$$o$.&3++X$$$o#p+X$$%$OhgOX oo+ii*if&+ri&OO%q0990099009090090990909009990999099w999990999090w0000w0ww0",
|
||||
"X$X$$XXX$$$$$$$$$$$$$$$$$$$$$oX#p#OO%$$o#7O%X$$XOg&O o.&fffgifirfffiOO*&qq990990000000009909099000990990999990999w90099000000000",
|
||||
"XX$$$XXX$$$$$$$$$$$$$$$$$$$$$oo*3+o$$%$.#7+X$%XOOhii+X,fgifffffffddfgOOrhi0qq000090000090099990909909009w9w9909990999099900000w0",
|
||||
"X$X$$$XX$$$$$%$$$$$$X$X$$$$$X$X#7@X$$$$o:3+XX$OqgffrXOe&&#*&iggi&&3&*&OOfffgrq900009000099099090000909009999990999900900000000w0",
|
||||
"X$q$XXXX$$$X%$$$$$$$X$$$$$$$$$X*p+O$%$$o-3oOX%gffff&o++3pgg3fddd3fdg&+OOhffffgt0099090090009090990909990999990999000099090090000",
|
||||
"X$g&$XXX%$X$%$$$$$$$$$X$$$$$$$o*p+X%$%$X,5+ *gfffff& ++&pddffffffgdd#OOOiffffffhq9qt009w990090900999w9w9900999w90999909009900000",
|
||||
"X$ggO %$$$X$%$$$$$$$$$$$$$$$Xo*3#$$%%$X,3+&ffffffg#+.+Odddgggggggpd*+OOifffffffgtqt09t909090990090909099990099w0990090909090000",
|
||||
"X%hfr&h&$$$$%q$X$$$$XXX$$$$$Xoo*p@o$$$$X:3OffffgppdO. ++,ddfffffffd3+ ++&ffffffffgq900909090900999099090w9w990990009009090009900",
|
||||
"Xohfffh&X$o$$h&$$$$$$$X$$$$$Xo$*7# %%$$ 35dffg73&#++++ +pd3gfffffg3d,++++3ddffffffhq90009099990999909090990909w99990099900900000",
|
||||
"oegffgiO$$$$$gh$$%&qXXXX$%XX$X.*3# X%X$+#pgfd3&+. + ++3iddgfffddpd&+O++++#pgfffffrq9900900q99090909990099009990009990999090000",
|
||||
"hffffg&X$%$X$gg*&hg*XXXX%i%$$Xo*5#XX$$$o,dfg&+.. .#&++ +&ddd3gfgdddd#++++&+++#3dfgghq009099090000909090990999090909000099000000w",
|
||||
"hgffffp*X$X%Ogggfgh$XXX$%g*XXooO5#o$%$$+&df3...&#++3 O#+#pd7di&,ppdd&+++#3+&&..#iffgqq009009009909900990090009990009999009990000",
|
||||
"o%qffgh&o%o*iffgfg%%X$XX*gi OqO*p#+$%$XO&h3 . +pdpp3pdgdd3#+++++++#ppggpp3ddp+##+ifghqrq09090090090090900909999009009w900009w0w9",
|
||||
"Xo*fh**%$%igfgfgg&%$$X$X&ggih3o+p# X%X$XX .+33+pdppdddfp,#+O&dfggdddd3pdddd+++dh&%%&q0090909009909090090000900w000w99w0900ww",
|
||||
"X%&fq%oX$%&hgfffgi%oXXX &fgshOoO3#+X%%XX+ . +#&++7dp3&#O&O&#&33dd3#3&.+#ppiiO#+ X%9909000909099090090900009w9w009ww9ww9w00",
|
||||
"X$%g*o$XX%Xo*gffffq$X%&egfhp&oXO7# XXX + #++.+++ +..O+ ++O++#ppp+++&3++ o XXq9000900009000090009000009w909w09w00w00w",
|
||||
"$$*i$$oX$XoX%hfeegg%$%&idggh+X$O4#+XOX + . + ..o + + ++ +&3gg#. X999909000000000000009000000000w09w0www0w",
|
||||
"$$%%$$$X$$o$$hh*$$q&$o o3ggd,ooo3#+ ++ +++ ++*++ X%0q9q900000ww000000000000ww99w00w9w99ww0",
|
||||
"$$$$%%X$$$X$%g0$$%%%oX .&fshg*Xo3: X + + X*0000000000w000000000w00000ww0www90wwww0",
|
||||
"$%$$%$$XX$$X%h$%$%$$XXX qg*XiqXo3:+ %0q0000000w00000w0ww000w0ww990009w0w99ww",
|
||||
"$$$%%%$$$XX$$%%$%$$$XXXXihXXX%X.,: %t000t90w0w0000090w00w00009w000wwww9www9",
|
||||
"$$$$$%X$X$$$$%$$$$$$XXXXq*XXXXXo3: . %0q0000t0w0ww00ww00ww00ww0w9w0w0w99ww9ww",
|
||||
"$$$$$$$XX$X$$$$$$$$$$XXX*$$XXXX :> %q0t0t00w0w0w0w00ww0w0w0w00w0w0www90w09w",
|
||||
"$$$$$$XX$$XX$$$$%$$$$XXX$$$$XXX.:3. . . .... .. . ....... X%qw000t00www0wwwwwww0ww0www0w00w00w09w9w",
|
||||
"$$$$%%$$$XX$$$$$$$$$XXXX$$$$XXX -3 . ....+@@@@@@.@@....@@@@#####*@.. %ttt9ttt0t0tw0www0ww0ww00w9ww0w09w9www0w",
|
||||
"$$$%$%$$X$$$$$$$%%9$XXXX$$$$XXX :3 ...#->1>>1,>>,,--;,--,,,1531>13>#@. X09q9r00t0t0wwwww0w0wwwwwwww0wwwwww0w00w",
|
||||
"$$$$$$XXX$$$$$$$$$$$XX X$$$$$XX.:: .#11ss65assa56a511155557a775555p5,,. Xqttr0trt0wtwwwwww0ww0wwwwww0wwwww0ww0ww",
|
||||
"$$$$$$$X$$$$9$9$$$$$XXXXX$$$XX$ >;. ...#,pps55paaaaasadasaaaaaaaaa777a77p53,*... Xt0tq9t0ttwww0wwwwwwww0wwww0wwww0wwwwwww",
|
||||
"*o$%$%$XX$$$$$$$%$$$$XXXX$$$$XXX,> +#*-,5pp7apasaadddaaaaddadaaadddaaa6pp733,##. Xqrtttttt0t0rt0tt000t0t0t0t00t0t0ttt0ttt",
|
||||
"go%$$*%$XXX$$$$$$$$$$X XX$$$$XX :> .&,#,5p77p7aaaaadaaadaddaaadaaaasaapp7775534#@ Xr90tq0ttt0tt0ttt0ttttt00tttt0tt0t0tttt0",
|
||||
"fio%whXXX%$$$$$$$$$$$XXX$$$$X$X.,8. o###-155pppadaasasaaadaaaaaaaaa51>3355455535>>#+ %t0r0r0rttt00tt0ttttttt0tttttt0ttttttttt",
|
||||
"gg&gf&X *qo$$$$$$$$$$X X$$$$$XX 3: OO##,135565431>113sadaaaddsss611>1>>55s5355333,*+ %rr0r0ttt0tttttrtt0ttqttt0ttttttttt0tttt",
|
||||
"gffghOXX*g*$$$%$$$$$XXXX$$$$XXX -> +###,>3575p5<><355saaaaaaaap615>;;-;>5a7p335333#+ %rrtttt0t0trtttttttttttttttttttttttttttt",
|
||||
"fgfg&oo &giO$qi%X$$$XX XX$$$XX .::+ +#,,,3355p55>>;;;,>16s777aaas61>;=--@#@@@@##&##&&+X*rrtttttttt0tttttttttttttttttttttttttttt",
|
||||
"gggg&o &gg,sfe$X$$$$X XX$$$XXX :: +&#-,,35333>>,-,-,>>15apaadap1>>;@@@#;-##@+,&@##&O+&rttttt0ttttttt0tttttttttttttttttttttttt",
|
||||
"gffgg*oX&gfggh%X$X$$XX X%%XXX 3:+ ++3:-####@@.@..@++@@->6aaaaaa74>=@,3,11335d&+@+O*&##qrrttttytttttttrtttttttttttttttttttttttt",
|
||||
"sggggho*dgggg&O$$$$$ *+Oii$X X .::+++&,-##+@+@@:ss1,1i1--=:4a77764::a1,@@@@=,,4d#+##*&,-eqyrwyrwttttttttttttttytytttytytttyttttt",
|
||||
"id**qi&Ogggdd+X$$$$$o*&eh*X XXX.::.O#,>-#@...+,,,-@@@@-5><<<76748:2<>-@#.@@@@=-@##@@+#,isiryywyyrttrttttyttytytttttytttttttttytu",
|
||||
",hO%X$Xo&gggg&O$$$$XoO,e&OXXXXX.3:.@33;#+@@@.-,>-@.@..@=::;<4<4<:28<2@#@.@@@@==-,-##-,1,eheywyywyttttyytytyttttttyttttttttytyttt",
|
||||
"i&o$$X Ogggfg%X$$$$oO,&+ XX X :3+@3,,;##@#@##,@@@..@-;==;426a76<<<;>;--#==;;::4>4>:;:==1ryewywttyrtytttytyytyyttyttuytyttyttyt",
|
||||
"**%$$$XX+hiO&h&%$$$XX*,,& XXX X ::+#1-#-;,,>,#-==#=#;-;<4444;6ad7<661<<11>2;2<<<445<>:<<@,ryytytyytyyttyyttytyttytyttyttyttyuytt",
|
||||
"%X$$$$X Og*o%$*X$$$$X*&&i* XXXX :3.#,=;>,-35:-#===:4s51446a6;6aaa6661<66aaa6<664445>:15<-,ewyytyytytyyytyyytytytytyyytyyttuttttu",
|
||||
"X$$$$XXXOi$$$$$X$$$XXX.o&qXo X .>>.#-@>;-:<6:<;==2<66a6<<6a<<aaaa7<a76167661<665655326a1-1ityytyyytytyyyyyyyyytyyttuyyyyytutyyyt",
|
||||
"$XX$$XX %%$$$$$X$%$$X ooX$XXX -8.@,=11>-:44:<82<<11<<<aa621addad167aa4<8<2<<7545511:66;eqrryytytyyyytyyttyytytyytttyttyytyttyy",
|
||||
"X$$$$XXXXX$$$$$$$$X$X XXXXXXXX :3.+>=54;;<<<<1<;2<<<1aada6:7adadd74aaadaa6446764444;=>s,eitryyyyyyyyyyyyttyyyyyyyytyyttyttutytu",
|
||||
"XX$$$XXXX$$$$XX$$$$$XXXXXX$X$X .::.@,;6<-;<<1<4::46aadddaa46aadddad66aaaaaa7a76564>4<-;51eryyttyyyttryytyyyyyryrtuyytyyyyyyttytt",
|
||||
"X$$$$XX XX$$$$X$$$XXXXX XXXXXXX :8+ia>44;;<<<44<;87dadddda<aaadddaaa1saadaa676444>>5a221eiiwtyyyyyyyyyyyyyyyyyyytyytytyytttytuyy",
|
||||
"$X$X$X XX$X$$X$$$$$XX XX$XX$XX #73pda6<>56>2<44<26addaa6>:6adaaadda2;16666a7a6<4>47a1<1ieyyyyytyyytyyyyyyryyyyyyyyytutyyuyyytyy",
|
||||
"X$$$XX XX$$$XX$$$$XXXX XXXXXX :75ps565577>:<:46<<1aa11;;6aaadddaada<2>2;<6676<<435a1>5eiyytyyyyyyyyyyyyytyyyyyyyyyyyyyyytyyuty",
|
||||
"XX$$$XX XX$$$$$$$$X$XXXXXXXXX X3773sdp565p742<:<61<2;2;2=<66aaaaadaaa1>6a66a665<5>456>15ewyyyyyyyytyyyyyyyyyyyyytyytyyyyytuyyttu",
|
||||
"$$$XXX X$$$$$X$$$XXXXXXXXXX &pp73dd357577<<:>481611612;661a1saas6111;21aa664444>56<163iyyytyyyyyyyyyyyyyyyyryyutyyyyyyyyyyyyyy",
|
||||
"$X$$XX XX$$X$$$$XXXXXXXXXX *ip773ss345775<<<848111aa1;=;-=><1511;;====116166165>4>6615rtyyyyyyyyyyyyyyyyyyyyyyyyyyyyytyyyyytuy",
|
||||
"X$$X$X XX$$$XX$X$XXXXX X XX*ipp773dd33783::<<<4<<6664;=6<@===-==#;=;1;@21<<646655>>>>6iryyyryyyyyyyyyyyyyyyyyywyryyyyyyyyyyyutu",
|
||||
"XXX$XX X$$$$$$X$XXXX XXXX&iipp783pp33735771<<46<644<=<66641,-@@:41112==2<4<44545a775piiyyyyyryyyyyyyyyyyyywyyyyyywyyyytyyyutyy",
|
||||
"XX$*XX XX$$$$$$$$XXXXXXX oriipsp784dp333a7p761446<442=2661666611<6161<1<@=;2<46555aa5ppqryyyyrryryyyyyyyyyyyyyryywyywyywuytyyyyy",
|
||||
"*oe*XX XXXXX$XXX$XXX Xoiihhisp774ppp837a7dp>4464<<2=<16666666666116661===;<1<445a77p3iryyyyyyyyyyyyyyyyyryyyyyyyyyyyyytyyyyyyy",
|
||||
"iiiXXXX XXXXX$XX$X X o@iihishpp788dpp#:7p7a,3447842=;166aaa6aaaaaa16666<;=;<<4643ap33iirryyyryyryyyyyyyyyyryyyyyyyyyyyytyyttyyy",
|
||||
"di&o o %*%XXXX$XXXX Oeiishippp773dd3:#:57>.-47664;@8<61a6a1aaaaaa676a11<=<<6548->53iirrryyyyyyyyyyyyyyyyyyyryyyrryyywyyyyyutuy",
|
||||
"ppO.oX *q&XXXXXX$XXX..@,eshsipdp783pp3:##:,@.#:4474<:<<11<>1<1661<21<<<6<6;166643##,7irrryyyyyyyyyyyyyryyyyyywyyyryrywtyyyyyyyty",
|
||||
"di*+X. *&OoXXXXXXX$ .o@&,sshsiip377pd3,##:3,@@4466718<<<2=====22=2===-=;2<6676158##333iryyyyytyyyyyyyyyyyyyyyyyyyyyyyyyyytytyyyy",
|
||||
"gge. *OoXXXXXXXXXX..@@,3shsipp778dp3,-@@@@+@-46667<22==;22,22=2111<6<<<<8677453##33iriyyyyyyyyyyyyyyyyyyyyyyyryyyyytyyyyyyyyyy",
|
||||
"esi* &*XXXXXXXXXX .@@=;ppssppp77377:-:@+.+++-446774<<<1116666aa16a61<66<6766558#,3ihrryyyyyyyyyyyyyyyyyyyrryyyyyyyyyytytyyyyyy",
|
||||
"&.&eo oi& XXX$XXXXXX.@@@=ishhpsp873p3,:28@@.@+=4<4774868<1116aa6a611<88668664453##&3iryyyyyyyyhyyyyyyyyyyyyyyyyyyyryyyyyytyyyyyy",
|
||||
"oXXo XX&eXXXXX XXXXX..=@@1ssipsp875p3::888:@.@@;44464<68<<2112;;;22<<6664<16443>##3iiryhuyyyyyyyyyyyyryyryyyyrryyyyyyryyyyyyyyyy",
|
||||
"XXXXX X&OXXXXXXXX .@@===6ssis577377>::88882@@-:<<68<66611<2;;;2=;:<<<<644<<<5-#3&3iyhyyyyyyyyyyyyyyyyyyyyyyyyyryyyyyryyyyyyyyy",
|
||||
"XXXX X %OoXXXXXXXX..@=@=@1ssis578377:::82822;@;:4<8244<8<1<46a56144<<<656<6<<1#&eerryryyyyyyuyyyyyyyyyyyyyyyyyyyyyyyyyytytytyty",
|
||||
"XXXXX XXXXXXXXX..@=@====sspp578877:8228282;=;<<><46666666aaaaaa66777a5<4<1,i-&3riryyyyyyyyyuyyyyyyyyyyyyyyyyyyyyyyyryyyyyyyyy",
|
||||
"X$XXX XXXXXX ..@@==@===1ppp5878p8222828282==<:<<6<<<84667aaaa6aa777744<;113,eiryyyyyyyyyyuyuyhyyyiyyyyyyyyyyyyyyyyyyyytyyyyy",
|
||||
"XXXXX XXXXXX X .@===@=====1ap387838:8:282822=@>4:>44>44644666a66aaa744>>:::>3,erryyuuyyyyyyyyhyyyyyyuyyyyyyyyyyyyyyytyyyyyyuty",
|
||||
"XXXX XXXXXXXo@@@===@@===11s>87888:8:828828@-p4;::<:<44<4446455656548>#---33Oirryyuyyyyyyuyyuyyyyyyyyhyyyyhyyyuyyyyuyyytuyyyy",
|
||||
"XXXXX XXXXXX .@@==========;1s187882;8:28888=+sp1,-=;-:<<444<<><141<<:;=@@=>p,XOrryuuuyyyyyyyyyhyyyyyyyyyyyyyyyyyyyyyyyyyytyyyy",
|
||||
"XXXX X XXXX .@@======@===@=1118788:;8:8288;.+d151-@@@@;:>2:---;,,-;--#@@@:333 ++qyyyyuyyyyyyyyyyuyyyuyyyyyyyyyuyyyyyyyyyyyutuy",
|
||||
"XXXXX XXXXX..@@=======@==@==>5<8788:;8:8:8:..&d,35>-@@@@-@@@@@@@@@@@@==@@,55p, Xqyyyyyyyyyhyyyyyyyyyyyyyyyyyyyyyuyyyyyyuttyyy",
|
||||
"$XXX o...@@=========@====262888:;-82::-.. ip#513:=@@@@@..@......@@---;1>53, Xqhyyhyyyyuyyyyyhyuyhhuuyhyyyyyyyyyyyyyyyyuyy",
|
||||
"XXXXX oXoO@@@=======@=@=====s;878:=-:-;@.. hp@74>:---##@@......@@#-,--,<51p3 +Oryyuhuyyyyyyyyyyyyyyuyyyyyyyyyyuyyyyuyyyyy",
|
||||
"XXXX X .o**==========@@@=@===1;878:;-:#.. gd@54>3:-:--@@@.....@@-;--;<>13d& + +O&ryyyyhyuyuyyyuyyyyyyyyyyyuyyyyyuyyyyyyyu",
|
||||
"XXXXX .&h1@=========@@@=====2;778:@@. hd@343<;;;,--@@@@O@@@#;;-->1>5pg&X X%qyyyyyyyyyuyyyuyyyyyyyyyuyuyyyyyyyyyyy",
|
||||
"XXXXX Xisi1;===@======@@=====>>88#+ gg#,5>:>:-;---@@@@@@=-;;-;<>53df& X X&ryyyyyyyyuhyuyhyhyyyyhyyyuyyyyyyyyy",
|
||||
"XXXX &idi31=========@@@=@==@=. + dg+-51<:;;;-#==#@#---->;-:>>5dff& XXXX*rhyyhuyyyyyyuyyyuyyyyyuyyhyyyyyyy",
|
||||
"X XX +iipi3s2==@======@@@=@@.. df@#55<>:>,---#=#-;=-;;;:>>35gggO X XXX$XOqrhyyyyhuyuyyyyyyyuuyuyyyyyyyuy",
|
||||
"X X X+pssiiss2======@....... igs@>1<>::>;-----;;;;;>;>>3>dffg . XX XO %qyyyyyyyhhyyuuyyyuyyuyyyyhyyy",
|
||||
"XXX .iissshss===@@... .. egf,-1<:<:>:----;>;;;>:;;>>5ggfs X XO+OX O*qiyyyyyyyyyyuyuyyuyyyyyyyy",
|
||||
"XXXX .ppssssdg,...... &gfd@>4::>>>----;;;;;>>;>>,gfggq X+ X XXXOOO9rryyyyhyyyyyyyuyyyyyyy",
|
||||
"XXX X .iphhshhsO X&gff,#><>:>;;---;>;2;>::--pgfgf* o ++ + X XXX++O++%&ryyyhyyuyyyyyyyyyy",
|
||||
"XXXX +3pdphi3 *ggfg#-><;:>:-;=;-;;;>;-#3gfgfg X+XX +X XXXXXXXXX%qyhyyyyyyuyyyyyy",
|
||||
"XXX iphi++ %ggffd-><><3---@----;>:@,gfffgi. +XX X+X X+ XXXoXXXXXX%qyyrhryyuyyyyy",
|
||||
"XXXX. pdi+ . Ogffffg;>1<>:-;@---=2,-,gffffgO XXXX X +X++X+X+ X+X XXX%%riryyyuyyyyy",
|
||||
" X X .ih& hgffffd-56>::-=--#->,-dfffffg X XXX X + X+o X+XOXXXX%ryyyyyyyyy",
|
||||
" o X ii + *ggffffp:553>;-,--,>#gffffffr XX X XX+X+ Xo o+ OXo XXX%yyyyyyyyy",
|
||||
"O o i& +ggfffff3,555>,3>,1,gfffffffO o+XXXX XXX X o XoXX +XXX$ryuyyuyyy",
|
||||
",. 3+. qgffffff3>531>1>13gfffffffh . X X++XX +X+XX X X X + + X$*yyyuyyyy",
|
||||
"iO & o&gfffffff35pddddsiffffffff& X X XXXX X X o X X X X XXrhyyytyy",
|
||||
"si . O ogfffffffffgfdhpO Ogfffffg ++ + X X+XX+ +X X+ X X XX X Xrryuyyry",
|
||||
"si# ... Xifffffffe**O+o ++ OgffffqX +X OX +X X X+X XX X+ X X X&yyyyyyy",
|
||||
"ssi@ &ffffffq+ + + o OgffgOX + X++ X++ OX+ XX+XXXXXXXX XX X X X$yyyyyyy",
|
||||
"sip&.... &gffff& +o + %gfr + + X X X X+XX+X X +X+ +X X X X$yyyyyyy",
|
||||
"pisi+. . +hfff&X + + &gO X X+ X+XO+X + X X X XX o XX X X Xqryryuy",
|
||||
"ppp3#. +eff& o + *+ + + + + XX X OXXX X +X X+ X XX X Xhyyyyu",
|
||||
"ppi3,. X*fq X + + O + ++ X++XX+X X X+XXXX+ Xo X X X XXrrhyyy",
|
||||
"p5pi,.. O& + +XX X + X X X O+X X X X X X X XX X*yryyu",
|
||||
"p5pi3o o + X o+OO X X +X+ X+ + +X X o o X X+ XX X X XXryyuy",
|
||||
"spp3,. X riggggghy+ + + + X+ X Xo XXo+X X X X+ X X X X Xqyyyu",
|
||||
"ppi3, . X O+ &gfffffffg&+ + +X X X +X o +X X+ X qiyyu",
|
||||
"6pp3,. X +hgfffffffgqX o +XX + X X ooX X X X X X X X %yyyu",
|
||||
"pp5i, X+ +X &gffffffffgO X X + ++ + X oX X X XX Xyhyy",
|
||||
"ppi3# . +X Ohgfffffffgi+ + ++ X X X +X +X o X XX XX X Xryyu",
|
||||
"p5ii# Oigffffffffg* X X+X ++XX+ + +XXXoX XX X X X Xryyu",
|
||||
"5pp1*. X +XX Oiggfffffffhh OO X+ + + X+XX +.X X o+ X XX X X&uyy",
|
||||
"5pp3@ X +XX ihffffffffgh#oX X+O + X X o o X X XX X X*uuu",
|
||||
"p3pi. + X+eggffffffgiqO +X++X oo o + . ooo + X X X%uuu",
|
||||
"p53p. &ii&&&&#O+ + + O*hgfffffgi&O X o O ++ oo .o.o$OO% . X X X $hyu",
|
||||
"p5i3. 3hfffi3rihhhii3r&& X oihffffgi&&XXoX+X X O+ X ooooo+*@*=#=*=*&, X . XX X$hyu",
|
||||
"p5i3 .idffg&iiiiphhddhip& Xo &hgffgi&&* o X oX X X X oXX o.Oe,22,,2112s%oXX . X Xryy",
|
||||
"5ii,. Oihgggiiiihhphhhiihi* X X XXOhdggh&ii XX O XXX+X+X+X+ oo .ooe,=222e22eso.o$... . XXryy",
|
||||
"p3p# Opgghfiiihgggdgghhhhi* oX ehgheid*XXoXXX X+ XX+X+ X ..&ieeq*1ee,eeee&,e=2=#--&* X Xquh",
|
||||
"pppO *rpggiqqiiiiihiphpphiio OX o.&gsieii. X+ XX+X + .@&ifseeeheeeeehq,de122=17i*. . X*yu",
|
||||
"p3p. . O&&q&&iiiiiihihihiiiii X X + hp&&3O X + X+ + + +.@=,sgh1e,heeesqhe,s11222221&% + X+ X%uu",
|
||||
"ppi. . +oO*&&e&i,iiiiiX XX X &i**& + X + XX X +@-,2212eeieqee,,ee*,22222222@o X X X%hu",
|
||||
"ii,. .XoO +&OO+ XX ++ +..+@>6a5=2,eih*ihf*&hie=22222==1o + X XXOyy",
|
||||
"5p,. X +** X +X ..*-375522=eigqeig&,ie,222222=2<oo X X X Xyh",
|
||||
"5i# + O+ + XX oo.@O##O@@@@O**oo+*+OOO..@@....@. X XXX XXXuy",
|
||||
"ip# X o .oo....+..ooo.XooX Xoo..oo..+.. X + Xrh",
|
||||
"p3@ + X oXoX .oo .oXo .oo .oo o .oo X + + X X X X XXqy",
|
||||
"pi@ X XX +o+ X X XXX XX.. XOoX X oo X X + X X XX&y"
|
||||
};
|
||||
/* XPM */
|
||||
static char *hopper[] = {
|
||||
/* columns rows colors chars-per-pixel */
|
||||
"128 128 44 1 ",
|
||||
" c #110E13",
|
||||
". c #2A1110",
|
||||
"X c #13122C",
|
||||
"o c #25192A",
|
||||
"O c #312831",
|
||||
"+ c #302219",
|
||||
"@ c #5F241A",
|
||||
"# c #6F4832",
|
||||
"$ c #17174A",
|
||||
"% c #26264F",
|
||||
"& c #65595D",
|
||||
"* c #4B3C54",
|
||||
"= c #8E1F1A",
|
||||
"- c #914E33",
|
||||
"; c #A75335",
|
||||
": c #AC6736",
|
||||
"> c #B26F4E",
|
||||
", c #9B6657",
|
||||
"< c #CA7652",
|
||||
"1 c #CC7866",
|
||||
"2 c #C25135",
|
||||
"3 c #B0896D",
|
||||
"4 c #D28859",
|
||||
"5 c #D28E6D",
|
||||
"6 c #E79371",
|
||||
"7 c #E5A36E",
|
||||
"8 c #D58932",
|
||||
"9 c #3E65AE",
|
||||
"0 c #4970B5",
|
||||
"q c #606D95",
|
||||
"w c #557CC1",
|
||||
"e c #91778A",
|
||||
"r c #6A86B9",
|
||||
"t c #5C83C3",
|
||||
"y c #6D8FCA",
|
||||
"u c #7799E3",
|
||||
"i c #A89A9D",
|
||||
"p c #CFAA90",
|
||||
"a c #F4B08F",
|
||||
"s c #D6A799",
|
||||
"d c #ECCCAB",
|
||||
"f c #F9F4F4",
|
||||
"g c #E3D8D5",
|
||||
"h c #AAAECA",
|
||||
/* pixels */
|
||||
"$XX$$XXX$%$$$$$$$$$$$$$$$$$$$egip3dr %% @p# Oqgffgfgfgo%q999q9999999999999999999099999099099990999999909909990w999000wwww00w00w0",
|
||||
"$$X$X$XX$$$$$$$$9$$$$XX$$$$$$ws&7+O&%$Xo@3#XXX&ihffggg%%9q*9*%q99qq9q99999999999999090900909909909099999999999999999000wwwwww0ww",
|
||||
"X$X$$XXX$$$$$$$$$$$$$$$$$$$$$eq@i#+$$$%X#pOX$%$%*dfffgiX%%OX%XO*%**990909999999009090990900999999099990999w999990990000wwwwwwwww",
|
||||
"$XX$$$XX$$$$$$$$$$$$XX$$$$$$$*O*7#XX%$%X@p*XX$%Xohfi3hOXOoX*r3*OOO%O99099999q0q990990009090909000999090999999099909999ww0w0000w0",
|
||||
"$XX$$XXX$$$$$$$$$9$$$$$$$$$$o$.&3++X$$$o#p+X$$%$OhgOX oo+ii*if&+ri&OO%q0990099009090090990909009990999099w999990999090w0000w0ww0",
|
||||
"X$X$$XXX$$$$$$$$$$$$$$$$$$$$$oX#p#OO%$$o#7O%X$$XOg&O o.&fffgifirfffiOO*&qq990990000000009909099000990990999990999w90099000000000",
|
||||
"XX$$$XXX$$$$$$$$$$$$$$$$$$$$$oo*3+o$$%$.#7+X$%XOOhii+X,fgifffffffddfgOOrhi0qq000090000090099990909909009w9w9909990999099900000w0",
|
||||
"X$X$$$XX$$$$$%$$$$$$X$X$$$$$X$X#7@X$$$$o:3+XX$OqgffrXOe&&#*&iggi&&3&*&OOfffgrq900009000099099090000909009999990999900900000000w0",
|
||||
"X$q$XXXX$$$X%$$$$$$$X$$$$$$$$$X*p+O$%$$o-3oOX%gffff&o++3pgg3fddd3fdg&+OOhffffgt0099090090009090990909990999990999000099090090000",
|
||||
"X$g&$XXX%$X$%$$$$$$$$$X$$$$$$$o*p+X%$%$X,5+ *gfffff& ++&pddffffffgdd#OOOiffffffhq9qt009w990090900999w9w9900999w90999909009900000",
|
||||
"X$ggO %$$$X$%$$$$$$$$$$$$$$$Xo*3#$$%%$X,3+&ffffffg#+.+Odddgggggggpd*+OOifffffffgtqt09t909090990090909099990099w0990090909090000",
|
||||
"X%hfr&h&$$$$%q$X$$$$XXX$$$$$Xoo*p@o$$$$X:3OffffgppdO. ++,ddfffffffd3+ ++&ffffffffgq900909090900999099090w9w990990009009090009900",
|
||||
"Xohfffh&X$o$$h&$$$$$$$X$$$$$Xo$*7# %%$$ 35dffg73&#++++ +pd3gfffffg3d,++++3ddffffffhq90009099990999909090990909w99990099900900000",
|
||||
"oegffgiO$$$$$gh$$%&qXXXX$%XX$X.*3# X%X$+#pgfd3&+. + ++3iddgfffddpd&+O++++#pgfffffrq9900900q99090909990099009990009990999090000",
|
||||
"hffffg&X$%$X$gg*&hg*XXXX%i%$$Xo*5#XX$$$o,dfg&+.. .#&++ +&ddd3gfgdddd#++++&+++#3dfgghq009099090000909090990999090909000099000000w",
|
||||
"hgffffp*X$X%Ogggfgh$XXX$%g*XXooO5#o$%$$+&df3...&#++3 O#+#pd7di&,ppdd&+++#3+&&..#iffgqq009009009909900990090009990009999009990000",
|
||||
"o%qffgh&o%o*iffgfg%%X$XX*gi OqO*p#+$%$XO&h3 . +pdpp3pdgdd3#+++++++#ppggpp3ddp+##+ifghqrq09090090090090900909999009009w900009w0w9",
|
||||
"Xo*fh**%$%igfgfgg&%$$X$X&ggih3o+p# X%X$XX .+33+pdppdddfp,#+O&dfggdddd3pdddd+++dh&%%&q0090909009909090090000900w000w99w0900ww",
|
||||
"X%&fq%oX$%&hgfffgi%oXXX &fgshOoO3#+X%%XX+ . +#&++7dp3&#O&O&#&33dd3#3&.+#ppiiO#+ X%9909000909099090090900009w9w009ww9ww9w00",
|
||||
"X$%g*o$XX%Xo*gffffq$X%&egfhp&oXO7# XXX + #++.+++ +..O+ ++O++#ppp+++&3++ o XXq9000900009000090009000009w909w09w00w00w",
|
||||
"$$*i$$oX$XoX%hfeegg%$%&idggh+X$O4#+XOX + . + ..o + + ++ +&3gg#. X999909000000000000009000000000w09w0www0w",
|
||||
"$$%%$$$X$$o$$hh*$$q&$o o3ggd,ooo3#+ ++ +++ ++*++ X%0q9q900000ww000000000000ww99w00w9w99ww0",
|
||||
"$$$$%%X$$$X$%g0$$%%%oX .&fshg*Xo3: X + + X*0000000000w000000000w00000ww0www90wwww0",
|
||||
"$%$$%$$XX$$X%h$%$%$$XXX qg*XiqXo3:+ %0q0000000w00000w0ww000w0ww990009w0w99ww",
|
||||
"$$$%%%$$$XX$$%%$%$$$XXXXihXXX%X.,: %t000t90w0w0000090w00w00009w000wwww9www9",
|
||||
"$$$$$%X$X$$$$%$$$$$$XXXXq*XXXXXo3: . %0q0000t0w0ww00ww00ww00ww0w9w0w0w99ww9ww",
|
||||
"$$$$$$$XX$X$$$$$$$$$$XXX*$$XXXX :> %q0t0t00w0w0w0w00ww0w0w0w00w0w0www90w09w",
|
||||
"$$$$$$XX$$XX$$$$%$$$$XXX$$$$XXX.:3. . . .... .. . ....... X%qw000t00www0wwwwwww0ww0www0w00w00w09w9w",
|
||||
"$$$$%%$$$XX$$$$$$$$$XXXX$$$$XXX -3 . ....+@@@@@@.@@....@@@@#####*@.. %ttt9ttt0t0tw0www0ww0ww00w9ww0w09w9www0w",
|
||||
"$$$%$%$$X$$$$$$$%%9$XXXX$$$$XXX :3 ...#->1>>1,>>,,--;,--,,,1531>13>#@. X09q9r00t0t0wwwww0w0wwwwwwww0wwwwww0w00w",
|
||||
"$$$$$$XXX$$$$$$$$$$$XX X$$$$$XX.:: .#11ss65assa56a511155557a775555p5,,. Xqttr0trt0wtwwwwww0ww0wwwwww0wwwww0ww0ww",
|
||||
"$$$$$$$X$$$$9$9$$$$$XXXXX$$$XX$ >;. ...#,pps55paaaaasadasaaaaaaaaa777a77p53,*... Xt0tq9t0ttwww0wwwwwwww0wwww0wwww0wwwwwww",
|
||||
"*o$%$%$XX$$$$$$$%$$$$XXXX$$$$XXX,> +#*-,5pp7apasaadddaaaaddadaaadddaaa6pp733,##. Xqrtttttt0t0rt0tt000t0t0t0t00t0t0ttt0ttt",
|
||||
"go%$$*%$XXX$$$$$$$$$$X XX$$$$XX :> .&,#,5p77p7aaaaadaaadaddaaadaaaasaapp7775534#@ Xr90tq0ttt0tt0ttt0ttttt00tttt0tt0t0tttt0",
|
||||
"fio%whXXX%$$$$$$$$$$$XXX$$$$X$X.,8. o###-155pppadaasasaaadaaaaaaaaa51>3355455535>>#+ %t0r0r0rttt00tt0ttttttt0tttttt0ttttttttt",
|
||||
"gg&gf&X *qo$$$$$$$$$$X X$$$$$XX 3: OO##,135565431>113sadaaaddsss611>1>>55s5355333,*+ %rr0r0ttt0tttttrtt0ttqttt0ttttttttt0tttt",
|
||||
"gffghOXX*g*$$$%$$$$$XXXX$$$$XXX -> +###,>3575p5<><355saaaaaaaap615>;;-;>5a7p335333#+ %rrtttt0t0trtttttttttttttttttttttttttttt",
|
||||
"fgfg&oo &giO$qi%X$$$XX XX$$$XX .::+ +#,,,3355p55>>;;;,>16s777aaas61>;=--@#@@@@##&##&&+X*rrtttttttt0tttttttttttttttttttttttttttt",
|
||||
"gggg&o &gg,sfe$X$$$$X XX$$$XXX :: +&#-,,35333>>,-,-,>>15apaadap1>>;@@@#;-##@+,&@##&O+&rttttt0ttttttt0tttttttttttttttttttttttt",
|
||||
"gffgg*oX&gfggh%X$X$$XX X%%XXX 3:+ ++3:-####@@.@..@++@@->6aaaaaa74>=@,3,11335d&+@+O*&##qrrttttytttttttrtttttttttttttttttttttttt",
|
||||
"sggggho*dgggg&O$$$$$ *+Oii$X X .::+++&,-##+@+@@:ss1,1i1--=:4a77764::a1,@@@@=,,4d#+##*&,-eqyrwyrwttttttttttttttytytttytytttyttttt",
|
||||
"id**qi&Ogggdd+X$$$$$o*&eh*X XXX.::.O#,>-#@...+,,,-@@@@-5><<<76748:2<>-@#.@@@@=-@##@@+#,isiryywyyrttrttttyttytytttttytttttttttytu",
|
||||
",hO%X$Xo&gggg&O$$$$XoO,e&OXXXXX.3:.@33;#+@@@.-,>-@.@..@=::;<4<4<:28<2@#@.@@@@==-,-##-,1,eheywyywyttttyytytyttttttyttttttttytyttt",
|
||||
"i&o$$X Ogggfg%X$$$$oO,&+ XX X :3+@3,,;##@#@##,@@@..@-;==;426a76<<<;>;--#==;;::4>4>:;:==1ryewywttyrtytttytyytyyttyttuytyttyttyt",
|
||||
"**%$$$XX+hiO&h&%$$$XX*,,& XXX X ::+#1-#-;,,>,#-==#=#;-;<4444;6ad7<661<<11>2;2<<<445<>:<<@,ryytytyytyyttyyttytyttytyttyttyttyuytt",
|
||||
"%X$$$$X Og*o%$*X$$$$X*&&i* XXXX :3.#,=;>,-35:-#===:4s51446a6;6aaa6661<66aaa6<664445>:15<-,ewyytyytytyyytyyytytytytyyytyyttuttttu",
|
||||
"X$$$$XXXOi$$$$$X$$$XXX.o&qXo X .>>.#-@>;-:<6:<;==2<66a6<<6a<<aaaa7<a76167661<665655326a1-1ityytyyytytyyyyyyyyytyyttuyyyyytutyyyt",
|
||||
"$XX$$XX %%$$$$$X$%$$X ooX$XXX -8.@,=11>-:44:<82<<11<<<aa621addad167aa4<8<2<<7545511:66;eqrryytytyyyytyyttyytytyytttyttyytyttyy",
|
||||
"X$$$$XXXXX$$$$$$$$X$X XXXXXXXX :3.+>=54;;<<<<1<;2<<<1aada6:7adadd74aaadaa6446764444;=>s,eitryyyyyyyyyyyyttyyyyyyyytyyttyttutytu",
|
||||
"XX$$$XXXX$$$$XX$$$$$XXXXXX$X$X .::.@,;6<-;<<1<4::46aadddaa46aadddad66aaaaaa7a76564>4<-;51eryyttyyyttryytyyyyyryrtuyytyyyyyyttytt",
|
||||
"X$$$$XX XX$$$$X$$$XXXXX XXXXXXX :8+ia>44;;<<<44<;87dadddda<aaadddaaa1saadaa676444>>5a221eiiwtyyyyyyyyyyyyyyyyyyytyytytyytttytuyy",
|
||||
"$X$X$X XX$X$$X$$$$$XX XX$XX$XX #73pda6<>56>2<44<26addaa6>:6adaaadda2;16666a7a6<4>47a1<1ieyyyyytyyytyyyyyyryyyyyyyyytutyyuyyytyy",
|
||||
"X$$$XX XX$$$XX$$$$XXXX XXXXXX :75ps565577>:<:46<<1aa11;;6aaadddaada<2>2;<6676<<435a1>5eiyytyyyyyyyyyyyyytyyyyyyyyyyyyyyytyyuty",
|
||||
"XX$$$XX XX$$$$$$$$X$XXXXXXXXX X3773sdp565p742<:<61<2;2;2=<66aaaaadaaa1>6a66a665<5>456>15ewyyyyyyyytyyyyyyyyyyyyytyytyyyyytuyyttu",
|
||||
"$$$XXX X$$$$$X$$$XXXXXXXXXX &pp73dd357577<<:>481611612;661a1saas6111;21aa664444>56<163iyyytyyyyyyyyyyyyyyyyryyutyyyyyyyyyyyyyy",
|
||||
"$X$$XX XX$$X$$$$XXXXXXXXXX *ip773ss345775<<<848111aa1;=;-=><1511;;====116166165>4>6615rtyyyyyyyyyyyyyyyyyyyyyyyyyyyyytyyyyytuy",
|
||||
"X$$X$X XX$$$XX$X$XXXXX X XX*ipp773dd33783::<<<4<<6664;=6<@===-==#;=;1;@21<<646655>>>>6iryyyryyyyyyyyyyyyyyyyyywyryyyyyyyyyyyutu",
|
||||
"XXX$XX X$$$$$$X$XXXX XXXX&iipp783pp33735771<<46<644<=<66641,-@@:41112==2<4<44545a775piiyyyyyryyyyyyyyyyyyywyyyyyywyyyytyyyutyy",
|
||||
"XX$*XX XX$$$$$$$$XXXXXXX oriipsp784dp333a7p761446<442=2661666611<6161<1<@=;2<46555aa5ppqryyyyrryryyyyyyyyyyyyyryywyywyywuytyyyyy",
|
||||
"*oe*XX XXXXX$XXX$XXX Xoiihhisp774ppp837a7dp>4464<<2=<16666666666116661===;<1<445a77p3iryyyyyyyyyyyyyyyyyryyyyyyyyyyyyytyyyyyyy",
|
||||
"iiiXXXX XXXXX$XX$X X o@iihishpp788dpp#:7p7a,3447842=;166aaa6aaaaaa16666<;=;<<4643ap33iirryyyryyryyyyyyyyyyryyyyyyyyyyyytyyttyyy",
|
||||
"di&o o %*%XXXX$XXXX Oeiishippp773dd3:#:57>.-47664;@8<61a6a1aaaaaa676a11<=<<6548->53iirrryyyyyyyyyyyyyyyyyyyryyyrryyywyyyyyutuy",
|
||||
"ppO.oX *q&XXXXXX$XXX..@,eshsipdp783pp3:##:,@.#:4474<:<<11<>1<1661<21<<<6<6;166643##,7irrryyyyyyyyyyyyyryyyyyywyyyryrywtyyyyyyyty",
|
||||
"di*+X. *&OoXXXXXXX$ .o@&,sshsiip377pd3,##:3,@@4466718<<<2=====22=2===-=;2<6676158##333iryyyyytyyyyyyyyyyyyyyyyyyyyyyyyyyytytyyyy",
|
||||
"gge. *OoXXXXXXXXXX..@@,3shsipp778dp3,-@@@@+@-46667<22==;22,22=2111<6<<<<8677453##33iriyyyyyyyyyyyyyyyyyyyyyyyryyyyytyyyyyyyyyy",
|
||||
"esi* &*XXXXXXXXXX .@@=;ppssppp77377:-:@+.+++-446774<<<1116666aa16a61<66<6766558#,3ihrryyyyyyyyyyyyyyyyyyyrryyyyyyyyyytytyyyyyy",
|
||||
"&.&eo oi& XXX$XXXXXX.@@@=ishhpsp873p3,:28@@.@+=4<4774868<1116aa6a611<88668664453##&3iryyyyyyyyhyyyyyyyyyyyyyyyyyyyryyyyyytyyyyyy",
|
||||
"oXXo XX&eXXXXX XXXXX..=@@1ssipsp875p3::888:@.@@;44464<68<<2112;;;22<<6664<16443>##3iiryhuyyyyyyyyyyyyryyryyyyrryyyyyyryyyyyyyyyy",
|
||||
"XXXXX X&OXXXXXXXX .@@===6ssis577377>::88882@@-:<<68<66611<2;;;2=;:<<<<644<<<5-#3&3iyhyyyyyyyyyyyyyyyyyyyyyyyyyryyyyyryyyyyyyyy",
|
||||
"XXXX X %OoXXXXXXXX..@=@=@1ssis578377:::82822;@;:4<8244<8<1<46a56144<<<656<6<<1#&eerryryyyyyyuyyyyyyyyyyyyyyyyyyyyyyyyyytytytyty",
|
||||
"XXXXX XXXXXXXXX..@=@====sspp578877:8228282;=;<<><46666666aaaaaa66777a5<4<1,i-&3riryyyyyyyyyuyyyyyyyyyyyyyyyyyyyyyyyryyyyyyyyy",
|
||||
"X$XXX XXXXXX ..@@==@===1ppp5878p8222828282==<:<<6<<<84667aaaa6aa777744<;113,eiryyyyyyyyyyuyuyhyyyiyyyyyyyyyyyyyyyyyyyytyyyyy",
|
||||
"XXXXX XXXXXX X .@===@=====1ap387838:8:282822=@>4:>44>44644666a66aaa744>>:::>3,erryyuuyyyyyyyyhyyyyyyuyyyyyyyyyyyyyyytyyyyyyuty",
|
||||
"XXXX XXXXXXXo@@@===@@===11s>87888:8:828828@-p4;::<:<44<4446455656548>#---33Oirryyuyyyyyyuyyuyyyyyyyyhyyyyhyyyuyyyyuyyytuyyyy",
|
||||
"XXXXX XXXXXX .@@==========;1s187882;8:28888=+sp1,-=;-:<<444<<><141<<:;=@@=>p,XOrryuuuyyyyyyyyyhyyyyyyyyyyyyyyyyyyyyyyyyyytyyyy",
|
||||
"XXXX X XXXX .@@======@===@=1118788:;8:8288;.+d151-@@@@;:>2:---;,,-;--#@@@:333 ++qyyyyuyyyyyyyyyyuyyyuyyyyyyyyyuyyyyyyyyyyyutuy",
|
||||
"XXXXX XXXXX..@@=======@==@==>5<8788:;8:8:8:..&d,35>-@@@@-@@@@@@@@@@@@==@@,55p, Xqyyyyyyyyyhyyyyyyyyyyyyyyyyyyyyyuyyyyyyuttyyy",
|
||||
"$XXX o...@@=========@====262888:;-82::-.. ip#513:=@@@@@..@......@@---;1>53, Xqhyyhyyyyuyyyyyhyuyhhuuyhyyyyyyyyyyyyyyyyuyy",
|
||||
"XXXXX oXoO@@@=======@=@=====s;878:=-:-;@.. hp@74>:---##@@......@@#-,--,<51p3 +Oryyuhuyyyyyyyyyyyyyyuyyyyyyyyyyuyyyyuyyyyy",
|
||||
"XXXX X .o**==========@@@=@===1;878:;-:#.. gd@54>3:-:--@@@.....@@-;--;<>13d& + +O&ryyyyhyuyuyyyuyyyyyyyyyyyuyyyyyuyyyyyyyu",
|
||||
"XXXXX .&h1@=========@@@=====2;778:@@. hd@343<;;;,--@@@@O@@@#;;-->1>5pg&X X%qyyyyyyyyyuyyyuyyyyyyyyyuyuyyyyyyyyyyy",
|
||||
"XXXXX Xisi1;===@======@@=====>>88#+ gg#,5>:>:-;---@@@@@@=-;;-;<>53df& X X&ryyyyyyyyuhyuyhyhyyyyhyyyuyyyyyyyyy",
|
||||
"XXXX &idi31=========@@@=@==@=. + dg+-51<:;;;-#==#@#---->;-:>>5dff& XXXX*rhyyhuyyyyyyuyyyuyyyyyuyyhyyyyyyy",
|
||||
"X XX +iipi3s2==@======@@@=@@.. df@#55<>:>,---#=#-;=-;;;:>>35gggO X XXX$XOqrhyyyyhuyuyyyyyyyuuyuyyyyyyyuy",
|
||||
"X X X+pssiiss2======@....... igs@>1<>::>;-----;;;;;>;>>3>dffg . XX XO %qyyyyyyyhhyyuuyyyuyyuyyyyhyyy",
|
||||
"XXX .iissshss===@@... .. egf,-1<:<:>:----;>;;;>:;;>>5ggfs X XO+OX O*qiyyyyyyyyyyuyuyyuyyyyyyyy",
|
||||
"XXXX .ppssssdg,...... &gfd@>4::>>>----;;;;;>>;>>,gfggq X+ X XXXOOO9rryyyyhyyyyyyyuyyyyyyy",
|
||||
"XXX X .iphhshhsO X&gff,#><>:>;;---;>;2;>::--pgfgf* o ++ + X XXX++O++%&ryyyhyyuyyyyyyyyyy",
|
||||
"XXXX +3pdphi3 *ggfg#-><;:>:-;=;-;;;>;-#3gfgfg X+XX +X XXXXXXXXX%qyhyyyyyyuyyyyyy",
|
||||
"XXX iphi++ %ggffd-><><3---@----;>:@,gfffgi. +XX X+X X+ XXXoXXXXXX%qyyrhryyuyyyyy",
|
||||
"XXXX. pdi+ . Ogffffg;>1<>:-;@---=2,-,gffffgO XXXX X +X++X+X+ X+X XXX%%riryyyuyyyyy",
|
||||
" X X .ih& hgffffd-56>::-=--#->,-dfffffg X XXX X + X+o X+XOXXXX%ryyyyyyyyy",
|
||||
" o X ii + *ggffffp:553>;-,--,>#gffffffr XX X XX+X+ Xo o+ OXo XXX%yyyyyyyyy",
|
||||
"O o i& +ggfffff3,555>,3>,1,gfffffffO o+XXXX XXX X o XoXX +XXX$ryuyyuyyy",
|
||||
",. 3+. qgffffff3>531>1>13gfffffffh . X X++XX +X+XX X X X + + X$*yyyuyyyy",
|
||||
"iO & o&gfffffff35pddddsiffffffff& X X XXXX X X o X X X X XXrhyyytyy",
|
||||
"si . O ogfffffffffgfdhpO Ogfffffg ++ + X X+XX+ +X X+ X X XX X Xrryuyyry",
|
||||
"si# ... Xifffffffe**O+o ++ OgffffqX +X OX +X X X+X XX X+ X X X&yyyyyyy",
|
||||
"ssi@ &ffffffq+ + + o OgffgOX + X++ X++ OX+ XX+XXXXXXXX XX X X X$yyyyyyy",
|
||||
"sip&.... &gffff& +o + %gfr + + X X X X+XX+X X +X+ +X X X X$yyyyyyy",
|
||||
"pisi+. . +hfff&X + + &gO X X+ X+XO+X + X X X XX o XX X X Xqryryuy",
|
||||
"ppp3#. +eff& o + *+ + + + + XX X OXXX X +X X+ X XX X Xhyyyyu",
|
||||
"ppi3,. X*fq X + + O + ++ X++XX+X X X+XXXX+ Xo X X X XXrrhyyy",
|
||||
"p5pi,.. O& + +XX X + X X X O+X X X X X X X XX X*yryyu",
|
||||
"p5pi3o o + X o+OO X X +X+ X+ + +X X o o X X+ XX X X XXryyuy",
|
||||
"spp3,. X riggggghy+ + + + X+ X Xo XXo+X X X X+ X X X X Xqyyyu",
|
||||
"ppi3, . X O+ &gfffffffg&+ + +X X X +X o +X X+ X qiyyu",
|
||||
"6pp3,. X +hgfffffffgqX o +XX + X X ooX X X X X X X X %yyyu",
|
||||
"pp5i, X+ +X &gffffffffgO X X + ++ + X oX X X XX Xyhyy",
|
||||
"ppi3# . +X Ohgfffffffgi+ + ++ X X X +X +X o X XX XX X Xryyu",
|
||||
"p5ii# Oigffffffffg* X X+X ++XX+ + +XXXoX XX X X X Xryyu",
|
||||
"5pp1*. X +XX Oiggfffffffhh OO X+ + + X+XX +.X X o+ X XX X X&uyy",
|
||||
"5pp3@ X +XX ihffffffffgh#oX X+O + X X o o X X XX X X*uuu",
|
||||
"p3pi. + X+eggffffffgiqO +X++X oo o + . ooo + X X X%uuu",
|
||||
"p53p. &ii&&&&#O+ + + O*hgfffffgi&O X o O ++ oo .o.o$OO% . X X X $hyu",
|
||||
"p5i3. 3hfffi3rihhhii3r&& X oihffffgi&&XXoX+X X O+ X ooooo+*@*=#=*=*&, X . XX X$hyu",
|
||||
"p5i3 .idffg&iiiiphhddhip& Xo &hgffgi&&* o X oX X X X oXX o.Oe,22,,2112s%oXX . X Xryy",
|
||||
"5ii,. Oihgggiiiihhphhhiihi* X X XXOhdggh&ii XX O XXX+X+X+X+ oo .ooe,=222e22eso.o$... . XXryy",
|
||||
"p3p# Opgghfiiihgggdgghhhhi* oX ehgheid*XXoXXX X+ XX+X+ X ..&ieeq*1ee,eeee&,e=2=#--&* X Xquh",
|
||||
"pppO *rpggiqqiiiiihiphpphiio OX o.&gsieii. X+ XX+X + .@&ifseeeheeeeehq,de122=17i*. . X*yu",
|
||||
"p3p. . O&&q&&iiiiiihihihiiiii X X + hp&&3O X + X+ + + +.@=,sgh1e,heeesqhe,s11222221&% + X+ X%uu",
|
||||
"ppi. . +oO*&&e&i,iiiiiX XX X &i**& + X + XX X +@-,2212eeieqee,,ee*,22222222@o X X X%hu",
|
||||
"ii,. .XoO +&OO+ XX ++ +..+@>6a5=2,eih*ihf*&hie=22222==1o + X XXOyy",
|
||||
"5p,. X +** X +X ..*-375522=eigqeig&,ie,222222=2<oo X X X Xyh",
|
||||
"5i# + O+ + XX oo.@O##O@@@@O**oo+*+OOO..@@....@. X XXX XXXuy",
|
||||
"ip# X o .oo....+..ooo.XooX Xoo..oo..+.. X + Xrh",
|
||||
"p3@ + X oXoX .oo .oXo .oo .oo o .oo X + + X X X X XXqy",
|
||||
"pi@ X XX +o+ X X XXX XX.. XOoX X oo X X + X X XX&y"
|
||||
};
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,2 +1,2 @@
|
|||
P7 332
|
||||
# Artificially edited file to cause unexpected EOF
|
||||
P7 332
|
||||
# Artificially edited file to cause unexpected EOF
|
||||
|
|
|
@ -1,174 +1,174 @@
|
|||
#define hopper_underscore_width 128
|
||||
#define hopper_underscore_height 128
|
||||
static char hopper_underscore_bits[] = {
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0x3D, 0x80, 0x96, 0xDA, 0xB6, 0xD6, 0x2A,
|
||||
0xA9, 0x6D, 0x25, 0x29, 0xFF, 0xFF, 0xFF, 0xBF, 0xFE, 0x7D, 0xC0, 0xFB,
|
||||
0x69, 0x69, 0xA9, 0xD5, 0x96, 0x96, 0x5E, 0x9A, 0xFF, 0xFF, 0xFF, 0x9F,
|
||||
0xFE, 0xFD, 0x80, 0xFF, 0x97, 0xB6, 0x5A, 0x6A, 0x5D, 0x6D, 0x5A, 0x62,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFD, 0xC1, 0xCF, 0x5F, 0x89, 0xA5, 0xD5,
|
||||
0xAA, 0x92, 0xA5, 0x59, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFD, 0xF8, 0x00,
|
||||
0xB8, 0x59, 0xAA, 0x56, 0xDA, 0x5A, 0x56, 0x49, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFE, 0xFC, 0xF9, 0x00, 0xF0, 0xA6, 0x55, 0xA9, 0x65, 0xA5, 0xA9, 0xA2,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFD, 0x71, 0x00, 0x60, 0x70, 0xAA, 0x54,
|
||||
0xAA, 0x5A, 0x54, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0x38, 0x00,
|
||||
0xE0, 0x80, 0x55, 0xAB, 0x55, 0x75, 0xAB, 0x56, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFE, 0x1D, 0x70, 0x00, 0xF0, 0x00, 0xAE, 0xAA, 0xAA, 0xA6, 0x95, 0x55,
|
||||
0xFB, 0xFF, 0xFF, 0xFF, 0xFE, 0x1D, 0xF0, 0x00, 0xF0, 0x00, 0x50, 0x55,
|
||||
0x55, 0x59, 0x6A, 0xAA, 0xF3, 0xFF, 0xFF, 0xFF, 0xFE, 0x04, 0xF0, 0x00,
|
||||
0xF0, 0x00, 0xA4, 0xAA, 0xA9, 0xA5, 0x95, 0x55, 0x21, 0xFF, 0xFF, 0xFF,
|
||||
0xFE, 0x01, 0xF8, 0x00, 0xF0, 0x00, 0x50, 0x55, 0x56, 0x5A, 0x6A, 0xAA,
|
||||
0x83, 0x9F, 0xFF, 0xFF, 0xFE, 0x00, 0xFC, 0x00, 0xF0, 0x01, 0x50, 0xD5,
|
||||
0x95, 0x95, 0xA5, 0x5A, 0x83, 0x9F, 0xFF, 0xFF, 0xFE, 0x81, 0xFF, 0x00,
|
||||
0xE0, 0x0B, 0xA0, 0xAA, 0x7A, 0x6A, 0x5A, 0x65, 0x80, 0x1F, 0xF0, 0xFF,
|
||||
0xFE, 0xF0, 0xFF, 0x00, 0xF0, 0x3F, 0x50, 0x55, 0xA5, 0xB5, 0xA5, 0xAA,
|
||||
0x00, 0x1F, 0xF8, 0xFD, 0xFE, 0xF0, 0xF7, 0x00, 0xF0, 0x6D, 0xA0, 0xAA,
|
||||
0x5A, 0x6A, 0x5A, 0x55, 0x83, 0x0F, 0xF8, 0xC9, 0xFE, 0x79, 0x00, 0xF8,
|
||||
0x02, 0xC0, 0x81, 0x55, 0xAD, 0xD5, 0xA5, 0xA6, 0xE3, 0x03, 0xFC, 0xC0,
|
||||
0xFE, 0xFF, 0x04, 0xF0, 0x00, 0x80, 0x63, 0xAA, 0x52, 0x2A, 0x5A, 0x58,
|
||||
0xE7, 0x03, 0xFC, 0xE1, 0xFE, 0xFF, 0x2F, 0xFC, 0x03, 0x0C, 0xFE, 0x55,
|
||||
0xA9, 0x55, 0x66, 0x15, 0xF3, 0x0F, 0x7C, 0xF0, 0xFE, 0xFF, 0xFF, 0xFD,
|
||||
0xEF, 0x38, 0xFF, 0xAA, 0x56, 0xAA, 0x99, 0xAA, 0xF7, 0x1F, 0x78, 0xF0,
|
||||
0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0xFF, 0x55, 0xAA, 0x5B, 0x66, 0xA4,
|
||||
0xFF, 0x9F, 0xFD, 0xF0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB,
|
||||
0x65, 0xA4, 0x99, 0x1B, 0xFF, 0xDF, 0xFF, 0xE0, 0xFE, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x69, 0x51, 0x5A, 0x24, 0x62, 0xFF, 0xDF, 0xFF, 0xEC,
|
||||
0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x95, 0xAA, 0x24, 0x59, 0x55,
|
||||
0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x25,
|
||||
0x49, 0xAD, 0x55, 0x2A, 0xFF, 0xFF, 0xFF, 0xFC, 0xFD, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x9B, 0xA5, 0x52, 0x2A, 0x94, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x67, 0x64, 0xC1, 0x92, 0x6D,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x95,
|
||||
0x49, 0x2C, 0x55, 0x92, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF,
|
||||
0x7F, 0xFF, 0xFF, 0x15, 0xB4, 0x62, 0x44, 0x49, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFD, 0xFF, 0x51, 0x30, 0x03, 0xE0, 0xFF, 0x53, 0x03, 0x89, 0x96, 0x92,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x7F, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xCD,
|
||||
0x68, 0x19, 0x68, 0x99, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x1F, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFF, 0x13, 0x4A, 0x64, 0x23, 0x49, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x47, 0x8A, 0xA4, 0xD8, 0x30,
|
||||
0xFE, 0xFF, 0xFF, 0xFF, 0xFC, 0x07, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x39,
|
||||
0x29, 0x49, 0x06, 0x86, 0xCC, 0xFF, 0xFF, 0xFF, 0xFC, 0x03, 0x00, 0x00,
|
||||
0x80, 0x00, 0xF2, 0x81, 0x50, 0x31, 0xA2, 0x8C, 0xE4, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x0A, 0x08, 0x00, 0x00, 0x00, 0xF0, 0xA7, 0x46, 0x8C, 0x28, 0x31,
|
||||
0xC0, 0xFC, 0xFF, 0xFF, 0xFC, 0x03, 0x10, 0x00, 0xE0, 0x01, 0xE0, 0x19,
|
||||
0x41, 0x61, 0x66, 0x05, 0xE0, 0xB8, 0xFF, 0xFF, 0x7E, 0x0C, 0x44, 0x00,
|
||||
0x40, 0xBF, 0xEF, 0x41, 0x5C, 0x04, 0x00, 0xA8, 0xF0, 0xC1, 0xFF, 0xFF,
|
||||
0xFE, 0x21, 0x9E, 0x00, 0xE0, 0xFF, 0xED, 0xA5, 0x12, 0x92, 0xDB, 0xA2,
|
||||
0xE0, 0xC0, 0xFF, 0xFF, 0x7D, 0xFA, 0xFF, 0x00, 0x70, 0x00, 0xFF, 0x42,
|
||||
0x84, 0x0C, 0x00, 0x08, 0xC0, 0xC0, 0xFF, 0xFC, 0x7D, 0xFF, 0x90, 0x07,
|
||||
0xC0, 0x1F, 0xDB, 0x0A, 0x24, 0xC8, 0x68, 0x09, 0xCC, 0xC0, 0x7F, 0xFE,
|
||||
0x1E, 0x7F, 0x3E, 0x00, 0xD4, 0xFF, 0x3E, 0x60, 0x81, 0x21, 0x02, 0xA0,
|
||||
0xFC, 0xE0, 0x7F, 0xFF, 0xCE, 0x9F, 0xFF, 0x05, 0xFA, 0xFF, 0xBF, 0x04,
|
||||
0x24, 0x0A, 0x61, 0x1B, 0xFC, 0xC0, 0xBF, 0xFF, 0xAC, 0x7D, 0xFF, 0x03,
|
||||
0x40, 0x1F, 0x80, 0x91, 0xC2, 0xA0, 0x05, 0x80, 0xFF, 0x8D, 0x7F, 0xFF,
|
||||
0xEF, 0xF5, 0xDF, 0x00, 0x00, 0x94, 0x42, 0x81, 0x01, 0x10, 0x92, 0x85,
|
||||
0xFF, 0xFD, 0xFF, 0xFE, 0x2C, 0x62, 0x03, 0x00, 0x20, 0x00, 0x10, 0x2B,
|
||||
0x24, 0x82, 0x00, 0x20, 0xFF, 0xFD, 0xFF, 0xFF, 0xBD, 0x55, 0x01, 0x00,
|
||||
0x40, 0x00, 0x08, 0x19, 0x81, 0x58, 0x54, 0x14, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x3C, 0x82, 0x05, 0x08, 0x00, 0x24, 0x20, 0x81, 0x24, 0x02, 0x02, 0x82,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0x82, 0x01, 0x00, 0x00, 0x00, 0x69, 0x22,
|
||||
0x90, 0xA0, 0x49, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0x2D, 0x26, 0x00, 0x00,
|
||||
0x00, 0x00, 0x20, 0x20, 0x0A, 0x02, 0x20, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x04, 0x81, 0x01, 0x00, 0x10, 0x00, 0xA0, 0x04, 0x02, 0x0A, 0x09, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x81, 0x19, 0x02, 0x02, 0x00, 0x00, 0x02, 0x42,
|
||||
0x50, 0xA0, 0x20, 0x95, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x60, 0x00, 0x01,
|
||||
0x80, 0x02, 0x42, 0x52, 0x40, 0x20, 0xA0, 0x20, 0xFF, 0xFF, 0xFF, 0x7F,
|
||||
0x00, 0x00, 0x8C, 0x01, 0x40, 0x00, 0x00, 0x00, 0x06, 0x06, 0x09, 0x05,
|
||||
0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x50, 0x00, 0x00, 0x40, 0x00, 0x02, 0x18,
|
||||
0xA0, 0x90, 0x84, 0x64, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x10, 0x81, 0x07,
|
||||
0xD0, 0x00, 0x48, 0x82, 0x02, 0x02, 0x20, 0x00, 0xFF, 0xFF, 0xFF, 0x0F,
|
||||
0x00, 0x04, 0xC0, 0x7E, 0x9F, 0x01, 0x10, 0x04, 0x00, 0x00, 0x24, 0x25,
|
||||
0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x60, 0x48, 0xC0, 0xC1, 0x13, 0x00, 0x41,
|
||||
0x9A, 0x99, 0x81, 0x00, 0xFF, 0xFF, 0xFF, 0x03, 0x40, 0x40, 0x60, 0x00,
|
||||
0x84, 0x0B, 0x00, 0x50, 0x02, 0x40, 0x24, 0x90, 0xFF, 0xFF, 0xFF, 0x01,
|
||||
0x00, 0x00, 0x32, 0x00, 0x00, 0x57, 0x00, 0x04, 0x40, 0x02, 0x01, 0x05,
|
||||
0xF8, 0xFF, 0xFF, 0x01, 0x40, 0x00, 0x38, 0x00, 0x00, 0x0E, 0x10, 0x05,
|
||||
0x99, 0x0A, 0xA4, 0x0A, 0xFC, 0xFF, 0x7F, 0x00, 0x80, 0x30, 0x10, 0x00,
|
||||
0x00, 0x84, 0x04, 0x60, 0x00, 0x50, 0x00, 0x60, 0xFC, 0xFF, 0xFF, 0x00,
|
||||
0x00, 0x3A, 0x08, 0x00, 0x00, 0x04, 0x8E, 0x06, 0x00, 0x41, 0x56, 0x00,
|
||||
0xF8, 0xFE, 0xFF, 0x01, 0x80, 0x79, 0xA0, 0x7F, 0xFF, 0x01, 0x06, 0x20,
|
||||
0x51, 0x08, 0x00, 0x2A, 0xF8, 0xFF, 0xFF, 0x00, 0xE0, 0x3F, 0xE0, 0xAF,
|
||||
0x00, 0x00, 0x06, 0x11, 0x91, 0x52, 0x02, 0x92, 0xF8, 0xFF, 0xFF, 0x00,
|
||||
0x00, 0x7F, 0x00, 0x00, 0x80, 0x02, 0x02, 0x08, 0x00, 0x00, 0x50, 0x00,
|
||||
0x7E, 0xFF, 0xFF, 0x01, 0x40, 0x7F, 0x00, 0x00, 0x10, 0x80, 0x86, 0x00,
|
||||
0x08, 0x09, 0x06, 0x08, 0xFF, 0xFF, 0xFF, 0x01, 0x80, 0xFC, 0x20, 0x51,
|
||||
0x0D, 0x20, 0x23, 0x94, 0x91, 0x50, 0x20, 0x92, 0xFF, 0xFE, 0xFF, 0x03,
|
||||
0x20, 0x70, 0x05, 0x88, 0x01, 0x80, 0x21, 0x06, 0x84, 0x44, 0x80, 0x25,
|
||||
0xFF, 0xFF, 0xFF, 0x03, 0x40, 0xEA, 0x90, 0x00, 0x20, 0xA4, 0x05, 0x00,
|
||||
0x00, 0x10, 0x26, 0x00, 0xFF, 0xFF, 0xFF, 0x07, 0x40, 0xD8, 0x08, 0x00,
|
||||
0x00, 0xA0, 0x81, 0x92, 0x01, 0x01, 0x84, 0x40, 0xFF, 0xFF, 0xFF, 0x0F,
|
||||
0x20, 0xC3, 0x42, 0x00, 0x00, 0x0A, 0x24, 0x00, 0x44, 0x48, 0x20, 0x25,
|
||||
0xFF, 0xFF, 0xFF, 0x0F, 0x20, 0xD5, 0x05, 0x02, 0x00, 0x46, 0x12, 0x40,
|
||||
0x02, 0x22, 0x44, 0x00, 0xFF, 0xFF, 0xFF, 0x1F, 0x90, 0x50, 0x90, 0x00,
|
||||
0x00, 0x9A, 0x40, 0x02, 0x40, 0x00, 0x10, 0x64, 0xFF, 0xFF, 0xFF, 0x1F,
|
||||
0x98, 0x62, 0x7C, 0x10, 0x11, 0xDF, 0x07, 0x14, 0x28, 0x08, 0x01, 0x05,
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0x20, 0x74, 0xF8, 0xE5, 0xEA, 0x87, 0x23, 0x01,
|
||||
0x81, 0x11, 0x48, 0x20, 0xFF, 0xFF, 0xFF, 0x1F, 0x50, 0x38, 0xF2, 0xFF,
|
||||
0xFF, 0xC7, 0x8F, 0x80, 0x00, 0x84, 0x40, 0x04, 0xFF, 0xFF, 0xFF, 0xBF,
|
||||
0x68, 0x3D, 0xE9, 0xFF, 0x7F, 0xC1, 0x1F, 0x28, 0x14, 0x10, 0x06, 0x50,
|
||||
0xFF, 0xFF, 0xFF, 0x3F, 0x90, 0x3F, 0x81, 0xFE, 0x5F, 0x89, 0x3F, 0x82,
|
||||
0x00, 0x02, 0xA2, 0x01, 0xFF, 0xFF, 0xFF, 0xBF, 0xB0, 0x3F, 0xB1, 0xFF,
|
||||
0xBF, 0xC1, 0xFF, 0x00, 0x82, 0x80, 0x00, 0x24, 0xFF, 0xFB, 0xFF, 0x7F,
|
||||
0xF8, 0x3F, 0xA9, 0xFC, 0x5F, 0x81, 0xFF, 0x0F, 0x08, 0x00, 0x04, 0x48,
|
||||
0xFF, 0xF0, 0xFF, 0xBF, 0xFC, 0x3F, 0x41, 0xEB, 0xE7, 0xC0, 0xFF, 0x1F,
|
||||
0x40, 0x24, 0x40, 0x01, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0x3F, 0xB3, 0x7D,
|
||||
0xAD, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0xA0, 0x90, 0x7F, 0xC0, 0xFF, 0xFF,
|
||||
0xFF, 0x3F, 0x43, 0xFA, 0x27, 0xC0, 0xFF, 0xFF, 0x93, 0x51, 0x04, 0x04,
|
||||
0x7F, 0x80, 0xFF, 0xFF, 0xFF, 0x3F, 0x60, 0x6D, 0x56, 0xC0, 0xFF, 0xFF,
|
||||
0x1F, 0x20, 0x0A, 0x40, 0x7F, 0x80, 0xFF, 0xFF, 0xFF, 0x3F, 0x84, 0x6A,
|
||||
0x6D, 0xC0, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x02, 0x7F, 0x00, 0xFF, 0xFF,
|
||||
0xFF, 0x3F, 0x2C, 0xBA, 0x22, 0xC0, 0xFF, 0xFF, 0xFF, 0x87, 0x04, 0x98,
|
||||
0x7F, 0x80, 0xFF, 0xFF, 0xFF, 0x3F, 0x48, 0x66, 0xD5, 0xC0, 0xFF, 0xFF,
|
||||
0xFF, 0x3F, 0x90, 0x02, 0x7F, 0xC0, 0xFF, 0xFF, 0xFF, 0x7F, 0x80, 0xA6,
|
||||
0x63, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x24, 0x7F, 0xF8, 0xFF, 0xFF,
|
||||
0xFF, 0x7F, 0x90, 0x78, 0x3A, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x27, 0x00,
|
||||
0x7F, 0xFC, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xF9, 0x06, 0xF0, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x8F, 0x61, 0x7F, 0xFC, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xA4,
|
||||
0x0B, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x04, 0x7F, 0xFE, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x00, 0xD0, 0x01, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x08,
|
||||
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x00, 0xF8, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x61, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x88,
|
||||
0x01, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFE, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x48,
|
||||
0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x07, 0xFC, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x01, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xD0,
|
||||
0x0F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x69, 0xF8, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x03, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x05,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0x3F, 0xFE, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x21, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0xFF,
|
||||
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6B,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x23, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xE0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xEF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x27,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x0F, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x03, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F,
|
||||
0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2F,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xF8, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00,
|
||||
0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x3F, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F,
|
||||
0xF8, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0x03, 0x00, 0xF1, 0xFF, 0x7F, 0x80,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0x03, 0x00,
|
||||
0xF0, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x7F, 0x6F, 0xFD, 0xFF, 0xFF, 0x1F,
|
||||
0xF8, 0xFF, 0x03, 0x00, 0xE0, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0x7F, 0x7F,
|
||||
0xFD, 0xFF, 0xFF, 0x7F, 0xF0, 0xFF, 0x03, 0x00, 0xC0, 0xFF, 0xFF, 0x90,
|
||||
0xFF, 0xFF, 0x5F, 0xA2, 0xF4, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0x03, 0x00,
|
||||
0x80, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0x0F, 0xAA, 0x42, 0xF1, 0xFF, 0x3F,
|
||||
0xF8, 0xFF, 0xAF, 0x00, 0x80, 0xFF, 0xFF, 0xD9, 0xFF, 0xFF, 0x0F, 0x02,
|
||||
0x64, 0xF1, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0x3F, 0xC2, 0xFF, 0xFF, 0xDB,
|
||||
0xFF, 0xFF, 0xCB, 0xD1, 0xDA, 0xF7, 0xFF, 0x7F, 0xF8, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x71, 0x44, 0xFC, 0xF6, 0xFF, 0x3F,
|
||||
0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB0, 0xC0,
|
||||
0xA8, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFC, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F,
|
||||
0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x7F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, };
|
||||
#define hopper_underscore_width 128
|
||||
#define hopper_underscore_height 128
|
||||
static char hopper_underscore_bits[] = {
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0x3D, 0x80, 0x96, 0xDA, 0xB6, 0xD6, 0x2A,
|
||||
0xA9, 0x6D, 0x25, 0x29, 0xFF, 0xFF, 0xFF, 0xBF, 0xFE, 0x7D, 0xC0, 0xFB,
|
||||
0x69, 0x69, 0xA9, 0xD5, 0x96, 0x96, 0x5E, 0x9A, 0xFF, 0xFF, 0xFF, 0x9F,
|
||||
0xFE, 0xFD, 0x80, 0xFF, 0x97, 0xB6, 0x5A, 0x6A, 0x5D, 0x6D, 0x5A, 0x62,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFD, 0xC1, 0xCF, 0x5F, 0x89, 0xA5, 0xD5,
|
||||
0xAA, 0x92, 0xA5, 0x59, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFD, 0xF8, 0x00,
|
||||
0xB8, 0x59, 0xAA, 0x56, 0xDA, 0x5A, 0x56, 0x49, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFE, 0xFC, 0xF9, 0x00, 0xF0, 0xA6, 0x55, 0xA9, 0x65, 0xA5, 0xA9, 0xA2,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFD, 0x71, 0x00, 0x60, 0x70, 0xAA, 0x54,
|
||||
0xAA, 0x5A, 0x54, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0x38, 0x00,
|
||||
0xE0, 0x80, 0x55, 0xAB, 0x55, 0x75, 0xAB, 0x56, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFE, 0x1D, 0x70, 0x00, 0xF0, 0x00, 0xAE, 0xAA, 0xAA, 0xA6, 0x95, 0x55,
|
||||
0xFB, 0xFF, 0xFF, 0xFF, 0xFE, 0x1D, 0xF0, 0x00, 0xF0, 0x00, 0x50, 0x55,
|
||||
0x55, 0x59, 0x6A, 0xAA, 0xF3, 0xFF, 0xFF, 0xFF, 0xFE, 0x04, 0xF0, 0x00,
|
||||
0xF0, 0x00, 0xA4, 0xAA, 0xA9, 0xA5, 0x95, 0x55, 0x21, 0xFF, 0xFF, 0xFF,
|
||||
0xFE, 0x01, 0xF8, 0x00, 0xF0, 0x00, 0x50, 0x55, 0x56, 0x5A, 0x6A, 0xAA,
|
||||
0x83, 0x9F, 0xFF, 0xFF, 0xFE, 0x00, 0xFC, 0x00, 0xF0, 0x01, 0x50, 0xD5,
|
||||
0x95, 0x95, 0xA5, 0x5A, 0x83, 0x9F, 0xFF, 0xFF, 0xFE, 0x81, 0xFF, 0x00,
|
||||
0xE0, 0x0B, 0xA0, 0xAA, 0x7A, 0x6A, 0x5A, 0x65, 0x80, 0x1F, 0xF0, 0xFF,
|
||||
0xFE, 0xF0, 0xFF, 0x00, 0xF0, 0x3F, 0x50, 0x55, 0xA5, 0xB5, 0xA5, 0xAA,
|
||||
0x00, 0x1F, 0xF8, 0xFD, 0xFE, 0xF0, 0xF7, 0x00, 0xF0, 0x6D, 0xA0, 0xAA,
|
||||
0x5A, 0x6A, 0x5A, 0x55, 0x83, 0x0F, 0xF8, 0xC9, 0xFE, 0x79, 0x00, 0xF8,
|
||||
0x02, 0xC0, 0x81, 0x55, 0xAD, 0xD5, 0xA5, 0xA6, 0xE3, 0x03, 0xFC, 0xC0,
|
||||
0xFE, 0xFF, 0x04, 0xF0, 0x00, 0x80, 0x63, 0xAA, 0x52, 0x2A, 0x5A, 0x58,
|
||||
0xE7, 0x03, 0xFC, 0xE1, 0xFE, 0xFF, 0x2F, 0xFC, 0x03, 0x0C, 0xFE, 0x55,
|
||||
0xA9, 0x55, 0x66, 0x15, 0xF3, 0x0F, 0x7C, 0xF0, 0xFE, 0xFF, 0xFF, 0xFD,
|
||||
0xEF, 0x38, 0xFF, 0xAA, 0x56, 0xAA, 0x99, 0xAA, 0xF7, 0x1F, 0x78, 0xF0,
|
||||
0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0xFF, 0x55, 0xAA, 0x5B, 0x66, 0xA4,
|
||||
0xFF, 0x9F, 0xFD, 0xF0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB,
|
||||
0x65, 0xA4, 0x99, 0x1B, 0xFF, 0xDF, 0xFF, 0xE0, 0xFE, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x69, 0x51, 0x5A, 0x24, 0x62, 0xFF, 0xDF, 0xFF, 0xEC,
|
||||
0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x95, 0xAA, 0x24, 0x59, 0x55,
|
||||
0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x25,
|
||||
0x49, 0xAD, 0x55, 0x2A, 0xFF, 0xFF, 0xFF, 0xFC, 0xFD, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x9B, 0xA5, 0x52, 0x2A, 0x94, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x67, 0x64, 0xC1, 0x92, 0x6D,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x95,
|
||||
0x49, 0x2C, 0x55, 0x92, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF,
|
||||
0x7F, 0xFF, 0xFF, 0x15, 0xB4, 0x62, 0x44, 0x49, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFD, 0xFF, 0x51, 0x30, 0x03, 0xE0, 0xFF, 0x53, 0x03, 0x89, 0x96, 0x92,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x7F, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xCD,
|
||||
0x68, 0x19, 0x68, 0x99, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x1F, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFF, 0x13, 0x4A, 0x64, 0x23, 0x49, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x47, 0x8A, 0xA4, 0xD8, 0x30,
|
||||
0xFE, 0xFF, 0xFF, 0xFF, 0xFC, 0x07, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x39,
|
||||
0x29, 0x49, 0x06, 0x86, 0xCC, 0xFF, 0xFF, 0xFF, 0xFC, 0x03, 0x00, 0x00,
|
||||
0x80, 0x00, 0xF2, 0x81, 0x50, 0x31, 0xA2, 0x8C, 0xE4, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x0A, 0x08, 0x00, 0x00, 0x00, 0xF0, 0xA7, 0x46, 0x8C, 0x28, 0x31,
|
||||
0xC0, 0xFC, 0xFF, 0xFF, 0xFC, 0x03, 0x10, 0x00, 0xE0, 0x01, 0xE0, 0x19,
|
||||
0x41, 0x61, 0x66, 0x05, 0xE0, 0xB8, 0xFF, 0xFF, 0x7E, 0x0C, 0x44, 0x00,
|
||||
0x40, 0xBF, 0xEF, 0x41, 0x5C, 0x04, 0x00, 0xA8, 0xF0, 0xC1, 0xFF, 0xFF,
|
||||
0xFE, 0x21, 0x9E, 0x00, 0xE0, 0xFF, 0xED, 0xA5, 0x12, 0x92, 0xDB, 0xA2,
|
||||
0xE0, 0xC0, 0xFF, 0xFF, 0x7D, 0xFA, 0xFF, 0x00, 0x70, 0x00, 0xFF, 0x42,
|
||||
0x84, 0x0C, 0x00, 0x08, 0xC0, 0xC0, 0xFF, 0xFC, 0x7D, 0xFF, 0x90, 0x07,
|
||||
0xC0, 0x1F, 0xDB, 0x0A, 0x24, 0xC8, 0x68, 0x09, 0xCC, 0xC0, 0x7F, 0xFE,
|
||||
0x1E, 0x7F, 0x3E, 0x00, 0xD4, 0xFF, 0x3E, 0x60, 0x81, 0x21, 0x02, 0xA0,
|
||||
0xFC, 0xE0, 0x7F, 0xFF, 0xCE, 0x9F, 0xFF, 0x05, 0xFA, 0xFF, 0xBF, 0x04,
|
||||
0x24, 0x0A, 0x61, 0x1B, 0xFC, 0xC0, 0xBF, 0xFF, 0xAC, 0x7D, 0xFF, 0x03,
|
||||
0x40, 0x1F, 0x80, 0x91, 0xC2, 0xA0, 0x05, 0x80, 0xFF, 0x8D, 0x7F, 0xFF,
|
||||
0xEF, 0xF5, 0xDF, 0x00, 0x00, 0x94, 0x42, 0x81, 0x01, 0x10, 0x92, 0x85,
|
||||
0xFF, 0xFD, 0xFF, 0xFE, 0x2C, 0x62, 0x03, 0x00, 0x20, 0x00, 0x10, 0x2B,
|
||||
0x24, 0x82, 0x00, 0x20, 0xFF, 0xFD, 0xFF, 0xFF, 0xBD, 0x55, 0x01, 0x00,
|
||||
0x40, 0x00, 0x08, 0x19, 0x81, 0x58, 0x54, 0x14, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x3C, 0x82, 0x05, 0x08, 0x00, 0x24, 0x20, 0x81, 0x24, 0x02, 0x02, 0x82,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0x82, 0x01, 0x00, 0x00, 0x00, 0x69, 0x22,
|
||||
0x90, 0xA0, 0x49, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0x2D, 0x26, 0x00, 0x00,
|
||||
0x00, 0x00, 0x20, 0x20, 0x0A, 0x02, 0x20, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x04, 0x81, 0x01, 0x00, 0x10, 0x00, 0xA0, 0x04, 0x02, 0x0A, 0x09, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x81, 0x19, 0x02, 0x02, 0x00, 0x00, 0x02, 0x42,
|
||||
0x50, 0xA0, 0x20, 0x95, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x60, 0x00, 0x01,
|
||||
0x80, 0x02, 0x42, 0x52, 0x40, 0x20, 0xA0, 0x20, 0xFF, 0xFF, 0xFF, 0x7F,
|
||||
0x00, 0x00, 0x8C, 0x01, 0x40, 0x00, 0x00, 0x00, 0x06, 0x06, 0x09, 0x05,
|
||||
0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x50, 0x00, 0x00, 0x40, 0x00, 0x02, 0x18,
|
||||
0xA0, 0x90, 0x84, 0x64, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x10, 0x81, 0x07,
|
||||
0xD0, 0x00, 0x48, 0x82, 0x02, 0x02, 0x20, 0x00, 0xFF, 0xFF, 0xFF, 0x0F,
|
||||
0x00, 0x04, 0xC0, 0x7E, 0x9F, 0x01, 0x10, 0x04, 0x00, 0x00, 0x24, 0x25,
|
||||
0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x60, 0x48, 0xC0, 0xC1, 0x13, 0x00, 0x41,
|
||||
0x9A, 0x99, 0x81, 0x00, 0xFF, 0xFF, 0xFF, 0x03, 0x40, 0x40, 0x60, 0x00,
|
||||
0x84, 0x0B, 0x00, 0x50, 0x02, 0x40, 0x24, 0x90, 0xFF, 0xFF, 0xFF, 0x01,
|
||||
0x00, 0x00, 0x32, 0x00, 0x00, 0x57, 0x00, 0x04, 0x40, 0x02, 0x01, 0x05,
|
||||
0xF8, 0xFF, 0xFF, 0x01, 0x40, 0x00, 0x38, 0x00, 0x00, 0x0E, 0x10, 0x05,
|
||||
0x99, 0x0A, 0xA4, 0x0A, 0xFC, 0xFF, 0x7F, 0x00, 0x80, 0x30, 0x10, 0x00,
|
||||
0x00, 0x84, 0x04, 0x60, 0x00, 0x50, 0x00, 0x60, 0xFC, 0xFF, 0xFF, 0x00,
|
||||
0x00, 0x3A, 0x08, 0x00, 0x00, 0x04, 0x8E, 0x06, 0x00, 0x41, 0x56, 0x00,
|
||||
0xF8, 0xFE, 0xFF, 0x01, 0x80, 0x79, 0xA0, 0x7F, 0xFF, 0x01, 0x06, 0x20,
|
||||
0x51, 0x08, 0x00, 0x2A, 0xF8, 0xFF, 0xFF, 0x00, 0xE0, 0x3F, 0xE0, 0xAF,
|
||||
0x00, 0x00, 0x06, 0x11, 0x91, 0x52, 0x02, 0x92, 0xF8, 0xFF, 0xFF, 0x00,
|
||||
0x00, 0x7F, 0x00, 0x00, 0x80, 0x02, 0x02, 0x08, 0x00, 0x00, 0x50, 0x00,
|
||||
0x7E, 0xFF, 0xFF, 0x01, 0x40, 0x7F, 0x00, 0x00, 0x10, 0x80, 0x86, 0x00,
|
||||
0x08, 0x09, 0x06, 0x08, 0xFF, 0xFF, 0xFF, 0x01, 0x80, 0xFC, 0x20, 0x51,
|
||||
0x0D, 0x20, 0x23, 0x94, 0x91, 0x50, 0x20, 0x92, 0xFF, 0xFE, 0xFF, 0x03,
|
||||
0x20, 0x70, 0x05, 0x88, 0x01, 0x80, 0x21, 0x06, 0x84, 0x44, 0x80, 0x25,
|
||||
0xFF, 0xFF, 0xFF, 0x03, 0x40, 0xEA, 0x90, 0x00, 0x20, 0xA4, 0x05, 0x00,
|
||||
0x00, 0x10, 0x26, 0x00, 0xFF, 0xFF, 0xFF, 0x07, 0x40, 0xD8, 0x08, 0x00,
|
||||
0x00, 0xA0, 0x81, 0x92, 0x01, 0x01, 0x84, 0x40, 0xFF, 0xFF, 0xFF, 0x0F,
|
||||
0x20, 0xC3, 0x42, 0x00, 0x00, 0x0A, 0x24, 0x00, 0x44, 0x48, 0x20, 0x25,
|
||||
0xFF, 0xFF, 0xFF, 0x0F, 0x20, 0xD5, 0x05, 0x02, 0x00, 0x46, 0x12, 0x40,
|
||||
0x02, 0x22, 0x44, 0x00, 0xFF, 0xFF, 0xFF, 0x1F, 0x90, 0x50, 0x90, 0x00,
|
||||
0x00, 0x9A, 0x40, 0x02, 0x40, 0x00, 0x10, 0x64, 0xFF, 0xFF, 0xFF, 0x1F,
|
||||
0x98, 0x62, 0x7C, 0x10, 0x11, 0xDF, 0x07, 0x14, 0x28, 0x08, 0x01, 0x05,
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0x20, 0x74, 0xF8, 0xE5, 0xEA, 0x87, 0x23, 0x01,
|
||||
0x81, 0x11, 0x48, 0x20, 0xFF, 0xFF, 0xFF, 0x1F, 0x50, 0x38, 0xF2, 0xFF,
|
||||
0xFF, 0xC7, 0x8F, 0x80, 0x00, 0x84, 0x40, 0x04, 0xFF, 0xFF, 0xFF, 0xBF,
|
||||
0x68, 0x3D, 0xE9, 0xFF, 0x7F, 0xC1, 0x1F, 0x28, 0x14, 0x10, 0x06, 0x50,
|
||||
0xFF, 0xFF, 0xFF, 0x3F, 0x90, 0x3F, 0x81, 0xFE, 0x5F, 0x89, 0x3F, 0x82,
|
||||
0x00, 0x02, 0xA2, 0x01, 0xFF, 0xFF, 0xFF, 0xBF, 0xB0, 0x3F, 0xB1, 0xFF,
|
||||
0xBF, 0xC1, 0xFF, 0x00, 0x82, 0x80, 0x00, 0x24, 0xFF, 0xFB, 0xFF, 0x7F,
|
||||
0xF8, 0x3F, 0xA9, 0xFC, 0x5F, 0x81, 0xFF, 0x0F, 0x08, 0x00, 0x04, 0x48,
|
||||
0xFF, 0xF0, 0xFF, 0xBF, 0xFC, 0x3F, 0x41, 0xEB, 0xE7, 0xC0, 0xFF, 0x1F,
|
||||
0x40, 0x24, 0x40, 0x01, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0x3F, 0xB3, 0x7D,
|
||||
0xAD, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0xA0, 0x90, 0x7F, 0xC0, 0xFF, 0xFF,
|
||||
0xFF, 0x3F, 0x43, 0xFA, 0x27, 0xC0, 0xFF, 0xFF, 0x93, 0x51, 0x04, 0x04,
|
||||
0x7F, 0x80, 0xFF, 0xFF, 0xFF, 0x3F, 0x60, 0x6D, 0x56, 0xC0, 0xFF, 0xFF,
|
||||
0x1F, 0x20, 0x0A, 0x40, 0x7F, 0x80, 0xFF, 0xFF, 0xFF, 0x3F, 0x84, 0x6A,
|
||||
0x6D, 0xC0, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x02, 0x7F, 0x00, 0xFF, 0xFF,
|
||||
0xFF, 0x3F, 0x2C, 0xBA, 0x22, 0xC0, 0xFF, 0xFF, 0xFF, 0x87, 0x04, 0x98,
|
||||
0x7F, 0x80, 0xFF, 0xFF, 0xFF, 0x3F, 0x48, 0x66, 0xD5, 0xC0, 0xFF, 0xFF,
|
||||
0xFF, 0x3F, 0x90, 0x02, 0x7F, 0xC0, 0xFF, 0xFF, 0xFF, 0x7F, 0x80, 0xA6,
|
||||
0x63, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x24, 0x7F, 0xF8, 0xFF, 0xFF,
|
||||
0xFF, 0x7F, 0x90, 0x78, 0x3A, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x27, 0x00,
|
||||
0x7F, 0xFC, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xF9, 0x06, 0xF0, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x8F, 0x61, 0x7F, 0xFC, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xA4,
|
||||
0x0B, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x04, 0x7F, 0xFE, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x00, 0xD0, 0x01, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x08,
|
||||
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x00, 0xF8, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x61, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x88,
|
||||
0x01, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFE, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x48,
|
||||
0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x07, 0xFC, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x01, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xD0,
|
||||
0x0F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x69, 0xF8, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x03, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x05,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0x3F, 0xFE, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x21, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0xFF,
|
||||
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6B,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x23, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xE0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xEF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x27,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x0F, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x03, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F,
|
||||
0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2F,
|
||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xF8, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00,
|
||||
0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x3F, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F,
|
||||
0xF8, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0x03, 0x00, 0xF1, 0xFF, 0x7F, 0x80,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0x03, 0x00,
|
||||
0xF0, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x7F, 0x6F, 0xFD, 0xFF, 0xFF, 0x1F,
|
||||
0xF8, 0xFF, 0x03, 0x00, 0xE0, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0x7F, 0x7F,
|
||||
0xFD, 0xFF, 0xFF, 0x7F, 0xF0, 0xFF, 0x03, 0x00, 0xC0, 0xFF, 0xFF, 0x90,
|
||||
0xFF, 0xFF, 0x5F, 0xA2, 0xF4, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0x03, 0x00,
|
||||
0x80, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0x0F, 0xAA, 0x42, 0xF1, 0xFF, 0x3F,
|
||||
0xF8, 0xFF, 0xAF, 0x00, 0x80, 0xFF, 0xFF, 0xD9, 0xFF, 0xFF, 0x0F, 0x02,
|
||||
0x64, 0xF1, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0x3F, 0xC2, 0xFF, 0xFF, 0xDB,
|
||||
0xFF, 0xFF, 0xCB, 0xD1, 0xDA, 0xF7, 0xFF, 0x7F, 0xF8, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x71, 0x44, 0xFC, 0xF6, 0xFF, 0x3F,
|
||||
0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB0, 0xC0,
|
||||
0xA8, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFC, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F,
|
||||
0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x7F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, };
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
GIMP Palette
|
||||
Name: Test
|
||||
Columns: 0
|
||||
#
|
||||
GIMP Palette
|
||||
Name: Test
|
||||
Columns: 0
|
||||
#
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
Images in this directory were created with GIMP.
|
||||
|
||||
TGAs have names in the following format:
|
||||
|
||||
{width}x{height}_{mode}_{origin}_{compression}.tga
|
||||
|
||||
Where:
|
||||
mode is PIL mode in lower case (L, P, RGB, etc.)
|
||||
origin:
|
||||
"bl" - bottom left
|
||||
"tl" - top left
|
||||
compression is either "raw" or "rle"
|
||||
Images in this directory were created with GIMP.
|
||||
|
||||
TGAs have names in the following format:
|
||||
|
||||
{width}x{height}_{mode}_{origin}_{compression}.tga
|
||||
|
||||
Where:
|
||||
mode is PIL mode in lower case (L, P, RGB, etc.)
|
||||
origin:
|
||||
"bl" - bottom left
|
||||
"tl" - top left
|
||||
compression is either "raw" or "rle"
|
||||
|
|
|
@ -1,36 +1,36 @@
|
|||
#!/bin/bash -eu
|
||||
# Copyright 2020 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
python3 -m pip install .
|
||||
|
||||
# Build fuzzers in $OUT.
|
||||
for fuzzer in $(find $SRC -name 'fuzz_*.py'); do
|
||||
compile_python_fuzzer $fuzzer \
|
||||
--add-binary /usr/local/lib/libjpeg.so.62.4.0:. \
|
||||
--add-binary /usr/local/lib/libfreetype.so.6:. \
|
||||
--add-binary /usr/local/lib/liblcms2.so.2:. \
|
||||
--add-binary /usr/local/lib/libopenjp2.so.7:. \
|
||||
--add-binary /usr/local/lib/libpng16.so.16:. \
|
||||
--add-binary /usr/local/lib/libtiff.so.6:. \
|
||||
--add-binary /usr/local/lib/libwebp.so.7:. \
|
||||
--add-binary /usr/local/lib/libwebpdemux.so.2:. \
|
||||
--add-binary /usr/local/lib/libwebpmux.so.3:. \
|
||||
--add-binary /usr/local/lib/libxcb.so.1:.
|
||||
done
|
||||
|
||||
find Tests/images Tests/icc -print | zip -q $OUT/fuzz_pillow_seed_corpus.zip -@
|
||||
find Tests/fonts -print | zip -q $OUT/fuzz_font_seed_corpus.zip -@
|
||||
#!/bin/bash -eu
|
||||
# Copyright 2020 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
python3 -m pip install .
|
||||
|
||||
# Build fuzzers in $OUT.
|
||||
for fuzzer in $(find $SRC -name 'fuzz_*.py'); do
|
||||
compile_python_fuzzer $fuzzer \
|
||||
--add-binary /usr/local/lib/libjpeg.so.62.4.0:. \
|
||||
--add-binary /usr/local/lib/libfreetype.so.6:. \
|
||||
--add-binary /usr/local/lib/liblcms2.so.2:. \
|
||||
--add-binary /usr/local/lib/libopenjp2.so.7:. \
|
||||
--add-binary /usr/local/lib/libpng16.so.16:. \
|
||||
--add-binary /usr/local/lib/libtiff.so.6:. \
|
||||
--add-binary /usr/local/lib/libwebp.so.7:. \
|
||||
--add-binary /usr/local/lib/libwebpdemux.so.2:. \
|
||||
--add-binary /usr/local/lib/libwebpmux.so.3:. \
|
||||
--add-binary /usr/local/lib/libxcb.so.1:.
|
||||
done
|
||||
|
||||
find Tests/images Tests/icc -print | zip -q $OUT/fuzz_pillow_seed_corpus.zip -@
|
||||
find Tests/fonts -print | zip -q $OUT/fuzz_font_seed_corpus.zip -@
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
#!/bin/bash -eu
|
||||
# Copyright 2020 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
# Generate image dictionaries here for each of the fuzzers and put them in the
|
||||
# $OUT directory, named for the fuzzer
|
||||
|
||||
git clone --depth 1 https://github.com/google/fuzzing
|
||||
cat fuzzing/dictionaries/bmp.dict \
|
||||
fuzzing/dictionaries/dds.dict \
|
||||
fuzzing/dictionaries/gif.dict \
|
||||
fuzzing/dictionaries/icns.dict \
|
||||
fuzzing/dictionaries/jpeg.dict \
|
||||
fuzzing/dictionaries/jpeg2000.dict \
|
||||
fuzzing/dictionaries/pbm.dict \
|
||||
fuzzing/dictionaries/png.dict \
|
||||
fuzzing/dictionaries/psd.dict \
|
||||
fuzzing/dictionaries/tiff.dict \
|
||||
fuzzing/dictionaries/webp.dict \
|
||||
> $OUT/fuzz_pillow.dict
|
||||
#!/bin/bash -eu
|
||||
# Copyright 2020 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
# Generate image dictionaries here for each of the fuzzers and put them in the
|
||||
# $OUT directory, named for the fuzzer
|
||||
|
||||
git clone --depth 1 https://github.com/google/fuzzing
|
||||
cat fuzzing/dictionaries/bmp.dict \
|
||||
fuzzing/dictionaries/dds.dict \
|
||||
fuzzing/dictionaries/gif.dict \
|
||||
fuzzing/dictionaries/icns.dict \
|
||||
fuzzing/dictionaries/jpeg.dict \
|
||||
fuzzing/dictionaries/jpeg2000.dict \
|
||||
fuzzing/dictionaries/pbm.dict \
|
||||
fuzzing/dictionaries/png.dict \
|
||||
fuzzing/dictionaries/psd.dict \
|
||||
fuzzing/dictionaries/tiff.dict \
|
||||
fuzzing/dictionaries/webp.dict \
|
||||
> $OUT/fuzz_pillow.dict
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user