mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-25 00:34:14 +03:00
Merge branch 'main' into cover
This commit is contained in:
commit
810f5f06c4
8
.github/workflows/test-cygwin.yml
vendored
8
.github/workflows/test-cygwin.yml
vendored
|
@ -4,11 +4,19 @@ on:
|
|||
push:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- ".travis.yml"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- ".travis.yml"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
|
|
8
.github/workflows/test-docker.yml
vendored
8
.github/workflows/test-docker.yml
vendored
|
@ -4,11 +4,19 @@ on:
|
|||
push:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- ".travis.yml"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- ".travis.yml"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
|
|
8
.github/workflows/test-mingw.yml
vendored
8
.github/workflows/test-mingw.yml
vendored
|
@ -4,11 +4,19 @@ on:
|
|||
push:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- ".travis.yml"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- ".travis.yml"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
|
|
10
.github/workflows/test-windows.yml
vendored
10
.github/workflows/test-windows.yml
vendored
|
@ -4,11 +4,19 @@ on:
|
|||
push:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- ".travis.yml"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- ".travis.yml"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
|
@ -24,7 +32,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: ["pypy3.10", "pypy3.9", "3.8", "3.9", "3.10", "3.11", "3.12-dev"]
|
||||
python-version: ["pypy3.10", "pypy3.9", "3.8", "3.9", "3.10", "3.11", "3.12"]
|
||||
|
||||
timeout-minutes: 30
|
||||
|
||||
|
|
10
.github/workflows/test.yml
vendored
10
.github/workflows/test.yml
vendored
|
@ -4,11 +4,19 @@ on:
|
|||
push:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- ".travis.yml"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- ".github/workflows/docs.yml"
|
||||
- ".github/workflows/wheels*"
|
||||
- ".gitmodules"
|
||||
- ".travis.yml"
|
||||
- "docs/**"
|
||||
- "wheels/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
|
@ -31,7 +39,7 @@ jobs:
|
|||
python-version: [
|
||||
"pypy3.10",
|
||||
"pypy3.9",
|
||||
"3.12-dev",
|
||||
"3.12",
|
||||
"3.11",
|
||||
"3.10",
|
||||
"3.9",
|
||||
|
|
40
.github/workflows/wheels-build.sh
vendored
Executable file
40
.github/workflows/wheels-build.sh
vendored
Executable file
|
@ -0,0 +1,40 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||
# webp, zstd, xz, libtiff, libxcb cause a conflict with building webp, libtiff, libxcb
|
||||
# libxdmcp causes an issue on macOS < 11
|
||||
# curl from brew requires zstd, use system curl
|
||||
# if php is installed, brew tries to reinstall these after installing openblas
|
||||
# remove lcms2 and libpng to fix building openjpeg on arm64
|
||||
brew remove --ignore-dependencies webp zstd xz libpng libtiff libxcb libxdmcp curl php lcms2 ghostscript
|
||||
|
||||
brew install pkg-config
|
||||
|
||||
if [[ "$PLAT" == "arm64" ]]; then
|
||||
export MACOSX_DEPLOYMENT_TARGET="11.0"
|
||||
else
|
||||
export MACOSX_DEPLOYMENT_TARGET="10.10"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$MB_PYTHON_VERSION" == pypy3* ]]; then
|
||||
MB_PYTHON_OSX_VER="10.9"
|
||||
fi
|
||||
|
||||
echo "::group::Install a virtualenv"
|
||||
source wheels/multibuild/common_utils.sh
|
||||
source wheels/multibuild/travis_steps.sh
|
||||
python3 -m pip install virtualenv
|
||||
before_install
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Build wheel"
|
||||
build_wheel
|
||||
ls -l "${GITHUB_WORKSPACE}/${WHEEL_SDIR}/"
|
||||
echo "::endgroup::"
|
||||
|
||||
if [[ $MACOSX_DEPLOYMENT_TARGET != "11.0" ]]; then
|
||||
echo "::group::Test wheel"
|
||||
install_run
|
||||
echo "::endgroup::"
|
||||
fi
|
69
.github/workflows/wheels-linux.yml
vendored
Normal file
69
.github/workflows/wheels-linux.yml
vendored
Normal file
|
@ -0,0 +1,69 @@
|
|||
name: Build Linux wheels
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
artifacts-name:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
env:
|
||||
CONFIG_PATH: "wheels/config.sh"
|
||||
REPO_DIR: "."
|
||||
TEST_DEPENDS: "pytest pytest-timeout"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: ${{ matrix.python }} ${{ matrix.mb-ml-libc }}${{ matrix.mb-ml-ver }}
|
||||
runs-on: "ubuntu-latest"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python: [
|
||||
"pypy3.9-7.3.13",
|
||||
"pypy3.10-7.3.13",
|
||||
"3.8",
|
||||
"3.9",
|
||||
"3.10",
|
||||
"3.11",
|
||||
"3.12",
|
||||
]
|
||||
mb-ml-libc: [ "manylinux" ]
|
||||
mb-ml-ver: [ 2014, "_2_28" ]
|
||||
include:
|
||||
- python: "3.8"
|
||||
mb-ml-libc: "musllinux"
|
||||
mb-ml-ver: "_1_1"
|
||||
- python: "3.9"
|
||||
mb-ml-libc: "musllinux"
|
||||
mb-ml-ver: "_1_1"
|
||||
- python: "3.10"
|
||||
mb-ml-libc: "musllinux"
|
||||
mb-ml-ver: "_1_1"
|
||||
- python: "3.11"
|
||||
mb-ml-libc: "musllinux"
|
||||
mb-ml-ver: "_1_1"
|
||||
- python: "3.12"
|
||||
mb-ml-libc: "musllinux"
|
||||
mb-ml-ver: "_1_1"
|
||||
env:
|
||||
MB_PYTHON_VERSION: ${{ matrix.python }}
|
||||
MB_ML_LIBC: ${{ matrix.mb-ml-libc }}
|
||||
MB_ML_VER: ${{ matrix.mb-ml-ver }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.x"
|
||||
- name: Build Wheel
|
||||
run: .github/workflows/wheels-build.sh
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ inputs.artifacts-name }}
|
||||
path: wheelhouse/*.whl
|
||||
# Uncomment to get SSH access for testing
|
||||
# - name: Setup tmate session
|
||||
# if: failure()
|
||||
# uses: mxschmitt/action-tmate@v3
|
57
.github/workflows/wheels-macos.yml
vendored
Normal file
57
.github/workflows/wheels-macos.yml
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
name: Build macOS wheels
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
artifacts-name:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
env:
|
||||
CONFIG_PATH: "wheels/config.sh"
|
||||
REPO_DIR: "."
|
||||
TEST_DEPENDS: "pytest pytest-timeout"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: ${{ matrix.python }} ${{ matrix.platform }}
|
||||
runs-on: "macos-latest"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python: [
|
||||
"pypy3.9-7.3.13",
|
||||
"pypy3.10-7.3.13",
|
||||
"3.8",
|
||||
"3.9",
|
||||
"3.10",
|
||||
"3.11",
|
||||
"3.12",
|
||||
]
|
||||
platform: [ "x86_64", "arm64" ]
|
||||
exclude:
|
||||
- python: "pypy3.9-7.3.13"
|
||||
platform: "arm64"
|
||||
- python: "pypy3.10-7.3.13"
|
||||
platform: "arm64"
|
||||
env:
|
||||
PLAT: ${{ matrix.platform }}
|
||||
MB_PYTHON_VERSION: ${{ matrix.python }}
|
||||
TRAVIS_OS_NAME: "osx"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.x"
|
||||
- name: Build Wheel
|
||||
run: .github/workflows/wheels-build.sh
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ inputs.artifacts-name }}
|
||||
path: wheelhouse/*.whl
|
||||
# Uncomment to get SSH access for testing
|
||||
# - name: Setup tmate session
|
||||
# if: failure()
|
||||
# uses: mxschmitt/action-tmate@v3
|
42
.github/workflows/wheels.yml
vendored
Normal file
42
.github/workflows/wheels.yml
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
name: Wheels
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".github/workflows/wheels*.yml"
|
||||
- "wheels/*"
|
||||
tags:
|
||||
- "*"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/wheels*.yml"
|
||||
- "wheels/*"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
macos:
|
||||
uses: ./.github/workflows/wheels-macos.yml
|
||||
with:
|
||||
artifacts-name: "wheels"
|
||||
|
||||
linux:
|
||||
uses: ./.github/workflows/wheels-linux.yml
|
||||
with:
|
||||
artifacts-name: "wheels"
|
||||
|
||||
success:
|
||||
permissions:
|
||||
contents: none
|
||||
needs: [macos, linux]
|
||||
runs-on: ubuntu-latest
|
||||
name: Wheels Successful
|
||||
steps:
|
||||
- name: Success
|
||||
run: echo Wheels Successful
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "multibuild"]
|
||||
path = wheels/multibuild
|
||||
url = https://github.com/multi-build/multibuild.git
|
|
@ -66,7 +66,7 @@ repos:
|
|||
- id: sphinx-lint
|
||||
|
||||
- repo: https://github.com/tox-dev/pyproject-fmt
|
||||
rev: 1.1.0
|
||||
rev: 1.2.0
|
||||
hooks:
|
||||
- id: pyproject-fmt
|
||||
|
||||
|
|
135
.travis.yml
Normal file
135
.travis.yml
Normal file
|
@ -0,0 +1,135 @@
|
|||
if: tag IS present OR type = api
|
||||
|
||||
env:
|
||||
global:
|
||||
- CONFIG_PATH=wheels/config.sh
|
||||
- REPO_DIR=.
|
||||
- PLAT=aarch64
|
||||
- TEST_DEPENDS=pytest-timeout
|
||||
|
||||
language: python
|
||||
# Default Python version is usually 3.6
|
||||
python: "3.11"
|
||||
dist: focal
|
||||
services: docker
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- name: "3.8 Focal manylinux2014 aarch64"
|
||||
os: linux
|
||||
arch: arm64
|
||||
env:
|
||||
- MB_ML_VER=2014
|
||||
- MB_PYTHON_VERSION=3.8
|
||||
- name: "3.8 Focal manylinux_2_28 aarch64"
|
||||
os: linux
|
||||
arch: arm64
|
||||
env:
|
||||
- MB_ML_VER="_2_28"
|
||||
- MB_PYTHON_VERSION=3.8
|
||||
- name: "3.8 musllinux_1_1 aarch64"
|
||||
os: linux
|
||||
arch: arm64
|
||||
env:
|
||||
- MB_ML_VER="_1_1"
|
||||
- MB_ML_LIBC="musllinux"
|
||||
- MB_PYTHON_VERSION=3.8
|
||||
- name: "3.9 Focal manylinux2014 aarch64"
|
||||
os: linux
|
||||
arch: arm64
|
||||
env:
|
||||
- MB_ML_VER=2014
|
||||
- MB_PYTHON_VERSION=3.9
|
||||
- name: "3.9 Focal manylinux_2_28 aarch64"
|
||||
os: linux
|
||||
arch: arm64
|
||||
env:
|
||||
- MB_ML_VER="_2_28"
|
||||
- MB_PYTHON_VERSION=3.9
|
||||
- name: "3.9 musllinux_1_1 aarch64"
|
||||
os: linux
|
||||
arch: arm64
|
||||
env:
|
||||
- MB_ML_VER="_1_1"
|
||||
- MB_ML_LIBC="musllinux"
|
||||
- MB_PYTHON_VERSION=3.9
|
||||
- name: "3.10 Focal manylinux2014 aarch64"
|
||||
os: linux
|
||||
arch: arm64
|
||||
env:
|
||||
- MB_ML_VER=2014
|
||||
- MB_PYTHON_VERSION=3.10
|
||||
- name: "3.10 Focal manylinux_2_28 aarch64"
|
||||
os: linux
|
||||
arch: arm64
|
||||
env:
|
||||
- MB_ML_VER="_2_28"
|
||||
- MB_PYTHON_VERSION=3.10
|
||||
- name: "3.10 musllinux_1_1 aarch64"
|
||||
os: linux
|
||||
arch: arm64
|
||||
env:
|
||||
- MB_ML_VER="_1_1"
|
||||
- MB_ML_LIBC="musllinux"
|
||||
- MB_PYTHON_VERSION=3.10
|
||||
- name: "3.11 Focal manylinux_2_28 aarch64"
|
||||
os: linux
|
||||
arch: arm64
|
||||
env:
|
||||
- MB_ML_VER=2014
|
||||
- MB_PYTHON_VERSION=3.11
|
||||
- name: "3.11 Focal manylinux_2_28 aarch64"
|
||||
os: linux
|
||||
arch: arm64
|
||||
env:
|
||||
- MB_ML_VER="_2_28"
|
||||
- MB_PYTHON_VERSION=3.11
|
||||
- name: "3.11 musllinux_1_1 aarch64"
|
||||
os: linux
|
||||
arch: arm64
|
||||
env:
|
||||
- MB_ML_VER="_1_1"
|
||||
- MB_ML_LIBC="musllinux"
|
||||
- MB_PYTHON_VERSION=3.11
|
||||
- name: "3.12 Focal manylinux_2_28 aarch64"
|
||||
os: linux
|
||||
arch: arm64
|
||||
env:
|
||||
- MB_ML_VER=2014
|
||||
- MB_PYTHON_VERSION=3.12
|
||||
- name: "3.12 Focal manylinux_2_28 aarch64"
|
||||
os: linux
|
||||
arch: arm64
|
||||
env:
|
||||
- MB_ML_VER="_2_28"
|
||||
- MB_PYTHON_VERSION=3.12
|
||||
- name: "3.12 musllinux_1_1 aarch64"
|
||||
os: linux
|
||||
arch: arm64
|
||||
env:
|
||||
- MB_ML_VER="_1_1"
|
||||
- MB_ML_LIBC="musllinux"
|
||||
- MB_PYTHON_VERSION=3.12
|
||||
|
||||
before_install:
|
||||
- source wheels/multibuild/common_utils.sh
|
||||
- source wheels/multibuild/travis_steps.sh
|
||||
- before_install
|
||||
|
||||
install:
|
||||
- build_multilinux aarch64 build_wheel
|
||||
- ls -l "${TRAVIS_BUILD_DIR}/${WHEEL_SDIR}/"
|
||||
|
||||
script:
|
||||
- install_run
|
||||
|
||||
# Upload wheels to GitHub Releases
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key: $GITHUB_RELEASE_TOKEN
|
||||
file_glob: true
|
||||
file: "${TRAVIS_BUILD_DIR}/${WHEEL_SDIR}/*.whl"
|
||||
on:
|
||||
repo: python-pillow/Pillow
|
||||
tags: true
|
||||
skip_cleanup: true
|
39
CHANGES.rst
39
CHANGES.rst
|
@ -5,6 +5,45 @@ Changelog (Pillow)
|
|||
10.1.0 (unreleased)
|
||||
-------------------
|
||||
|
||||
- Support BGR;15, BGR;16 and BGR;24 access, unpacking and putdata #7303
|
||||
[radarhere]
|
||||
|
||||
- Added CMYK to RGB unpacker #7310
|
||||
[radarhere]
|
||||
|
||||
- Improved flexibility of XMP parsing #7274
|
||||
[radarhere]
|
||||
|
||||
- Support reading 8-bit YCbCr TIFF images #7415
|
||||
[radarhere]
|
||||
|
||||
- Allow saving I;16B images as PNG #7302
|
||||
[radarhere]
|
||||
|
||||
- Corrected drawing I;16 points and writing I;16 text #7257
|
||||
[radarhere]
|
||||
|
||||
- Set blue channel to 128 for BC5S #7413
|
||||
[radarhere]
|
||||
|
||||
- Increase flexibility when reading IPTC fields #7319
|
||||
[radarhere]
|
||||
|
||||
- Set C palette to be empty by default #7289
|
||||
[radarhere]
|
||||
|
||||
- Added gs_binary to control Ghostscript use on all platforms #7392
|
||||
[radarhere]
|
||||
|
||||
- Read bounding box information from the trailer of EPS files if specified #7382
|
||||
[nopperl, radarhere]
|
||||
|
||||
- Added reading 8-bit color DDS images #7426
|
||||
[radarhere]
|
||||
|
||||
- Added has_transparency_data #7420
|
||||
[radarhere, hugovk]
|
||||
|
||||
- Fixed bug when reading BC5S DDS images #7401
|
||||
[radarhere]
|
||||
|
||||
|
|
|
@ -29,3 +29,4 @@ global-exclude .git*
|
|||
global-exclude *.pyc
|
||||
global-exclude *.so
|
||||
prune .ci
|
||||
prune wheels
|
||||
|
|
14
README.md
14
README.md
|
@ -45,12 +45,12 @@ As of 2019, Pillow development is
|
|||
<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-wheels/actions"><img
|
||||
alt="GitHub Actions wheels build status (Wheels)"
|
||||
src="https://github.com/python-pillow/pillow-wheels/workflows/Wheels/badge.svg"></a>
|
||||
<a href="https://app.travis-ci.com/github/python-pillow/pillow-wheels"><img
|
||||
<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.travis-ci.com/github/python-pillow/Pillow"><img
|
||||
alt="Travis CI wheels build status (aarch64)"
|
||||
src="https://img.shields.io/travis/com/python-pillow/pillow-wheels/main.svg?label=aarch64%20wheels"></a>
|
||||
src="https://img.shields.io/travis/com/python-pillow/Pillow/main.svg?label=aarch64%20wheels"></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>
|
||||
|
@ -74,9 +74,9 @@ As of 2019, Pillow development is
|
|||
<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://bestpractices.coreinfrastructure.org/projects/6331"><img
|
||||
<a href="https://www.bestpractices.dev/projects/6331"><img
|
||||
alt="OpenSSF Best Practices"
|
||||
src="https://bestpractices.coreinfrastructure.org/projects/6331/badge"></a>
|
||||
src="https://www.bestpractices.dev/projects/6331/badge"></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
17
RELEASING.md
17
RELEASING.md
|
@ -10,7 +10,7 @@ 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 of the wheel builds [Pillow Wheel Builder](https://github.com/python-pillow/pillow-wheels) pass the tests in Travis CI and GitHub Actions.
|
||||
* [ ] Check that all of the wheel builds pass the tests in the [GitHub Actions "Wheels" workflow](https://github.com/python-pillow/Pillow/actions/workflows/wheels.yml) and [Travis CI](https://app.travis-ci.com/github/python-pillow/pillow) 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.
|
||||
|
@ -99,17 +99,14 @@ Released as needed privately to individual vendors for critical security-related
|
|||
## Binary Distributions
|
||||
|
||||
### macOS and Linux
|
||||
* [ ] Use the [Pillow Wheel Builder](https://github.com/python-pillow/pillow-wheels):
|
||||
* [ ] Download wheels from the [GitHub Actions "Wheels" workflow](https://github.com/python-pillow/Pillow/actions/workflows/wheels.yml)
|
||||
and copy into `dist/`. For example using [GitHub CLI](https://github.com/cli/cli):
|
||||
```bash
|
||||
git clone https://github.com/python-pillow/pillow-wheels
|
||||
cd pillow-wheels
|
||||
./update-pillow-tag.sh [[release tag]]
|
||||
```
|
||||
* [ ] Download wheels from the [Pillow Wheel Builder release](https://github.com/python-pillow/pillow-wheels/releases)
|
||||
and copy into `dist/`. For example using [GitHub CLI](https://github.com/cli/cli) from the main repo:
|
||||
```bash
|
||||
gh release download --dir dist --pattern "*.whl" --repo python-pillow/pillow-wheels
|
||||
gh run download --dir dist
|
||||
# select dist-x.y.z
|
||||
```
|
||||
* [ ] Download the Linux aarch64 wheels created by Travis CI from [GitHub releases](https://github.com/python-pillow/Pillow/releases)
|
||||
and copy into `dist`.
|
||||
|
||||
### Windows
|
||||
* [ ] Download the artifacts from the [GitHub Actions "Test Windows" workflow](https://github.com/python-pillow/Pillow/actions/workflows/test-windows.yml)
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 95 KiB |
Binary file not shown.
Before Width: | Height: | Size: 181 B After Width: | Height: | Size: 180 B |
BIN
Tests/images/palette.dds
Normal file
BIN
Tests/images/palette.dds
Normal file
Binary file not shown.
BIN
Tests/images/xmp_no_prefix.jpg
Normal file
BIN
Tests/images/xmp_no_prefix.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 788 B |
BIN
Tests/images/xmp_padded.jpg
Normal file
BIN
Tests/images/xmp_padded.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 778 B |
BIN
Tests/images/zero_bb_eof_before_boundingbox.eps
Normal file
BIN
Tests/images/zero_bb_eof_before_boundingbox.eps
Normal file
Binary file not shown.
BIN
Tests/images/zero_bb_trailer.eps
Normal file
BIN
Tests/images/zero_bb_trailer.eps
Normal file
Binary file not shown.
|
@ -298,6 +298,11 @@ def test_dxt5_colorblock_alpha_issue_4142():
|
|||
assert px[2] != 0
|
||||
|
||||
|
||||
def test_palette():
|
||||
with Image.open("Tests/images/palette.dds") as im:
|
||||
assert_image_equal_tofile(im, "Tests/images/transparent.gif")
|
||||
|
||||
|
||||
def test_unimplemented_pixel_format():
|
||||
with pytest.raises(NotImplementedError):
|
||||
with Image.open("Tests/images/unimplemented_pixel_format.dds"):
|
||||
|
|
|
@ -8,6 +8,7 @@ from .helper import (
|
|||
assert_image_similar,
|
||||
assert_image_similar_tofile,
|
||||
hopper,
|
||||
is_win32,
|
||||
mark_if_feature_version,
|
||||
skip_unless_feature,
|
||||
)
|
||||
|
@ -98,6 +99,20 @@ def test_load():
|
|||
assert im.load()[0, 0] == (255, 255, 255)
|
||||
|
||||
|
||||
def test_binary():
|
||||
if HAS_GHOSTSCRIPT:
|
||||
assert EpsImagePlugin.gs_binary is not None
|
||||
else:
|
||||
assert EpsImagePlugin.gs_binary is False
|
||||
|
||||
if not is_win32():
|
||||
assert EpsImagePlugin.gs_windows_binary is None
|
||||
elif not HAS_GHOSTSCRIPT:
|
||||
assert EpsImagePlugin.gs_windows_binary is False
|
||||
else:
|
||||
assert EpsImagePlugin.gs_windows_binary is not None
|
||||
|
||||
|
||||
def test_invalid_file():
|
||||
invalid_file = "Tests/images/flower.jpg"
|
||||
with pytest.raises(SyntaxError):
|
||||
|
@ -404,3 +419,18 @@ def test_timeout(test_file):
|
|||
with pytest.raises(Image.UnidentifiedImageError):
|
||||
with Image.open(f):
|
||||
pass
|
||||
|
||||
|
||||
def test_bounding_box_in_trailer():
|
||||
# Check bounding boxes are parsed in the same way
|
||||
# when specified in the header and the trailer
|
||||
with Image.open("Tests/images/zero_bb_trailer.eps") as trailer_image, Image.open(
|
||||
FILE1
|
||||
) as header_image:
|
||||
assert trailer_image.size == header_image.size
|
||||
|
||||
|
||||
def test_eof_before_bounding_box():
|
||||
with pytest.raises(OSError):
|
||||
with Image.open("Tests/images/zero_bb_eof_before_boundingbox.eps"):
|
||||
pass
|
||||
|
|
|
@ -205,14 +205,14 @@ def test_optimize_full_l():
|
|||
|
||||
|
||||
def test_optimize_if_palette_can_be_reduced_by_half():
|
||||
with Image.open("Tests/images/test.colors.gif") as im:
|
||||
# Reduce dimensions because original is too big for _get_optimize()
|
||||
im = im.resize((591, 443))
|
||||
im_rgb = im.convert("RGB")
|
||||
im = Image.new("P", (8, 1))
|
||||
im.palette = ImagePalette.raw("RGB", bytes((0, 0, 0) * 150))
|
||||
for i in range(8):
|
||||
im.putpixel((i, 0), (i + 1, 0, 0))
|
||||
|
||||
for optimize, colors in ((False, 256), (True, 8)):
|
||||
out = BytesIO()
|
||||
im_rgb.save(out, "GIF", optimize=optimize)
|
||||
im.save(out, "GIF", optimize=optimize)
|
||||
with Image.open(out) as reloaded:
|
||||
assert len(reloaded.palette.palette) // 3 == colors
|
||||
|
||||
|
@ -1180,18 +1180,17 @@ def test_palette_save_L(tmp_path):
|
|||
|
||||
|
||||
def test_palette_save_P(tmp_path):
|
||||
# Pass in a different palette, then construct what the image would look like.
|
||||
# Forcing a non-straight grayscale palette.
|
||||
|
||||
im = hopper("P")
|
||||
palette = bytes(255 - i // 3 for i in range(768))
|
||||
im = Image.new("P", (1, 2))
|
||||
im.putpixel((0, 1), 1)
|
||||
|
||||
out = str(tmp_path / "temp.gif")
|
||||
im.save(out, palette=palette)
|
||||
im.save(out, palette=bytes((1, 2, 3, 4, 5, 6)))
|
||||
|
||||
with Image.open(out) as reloaded:
|
||||
im.putpalette(palette)
|
||||
assert_image_equal(reloaded, im)
|
||||
reloaded_rgb = reloaded.convert("RGB")
|
||||
|
||||
assert reloaded_rgb.getpixel((0, 0)) == (1, 2, 3)
|
||||
assert reloaded_rgb.getpixel((0, 1)) == (4, 5, 6)
|
||||
|
||||
|
||||
def test_palette_save_duplicate_entries(tmp_path):
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import sys
|
||||
from io import StringIO
|
||||
from io import BytesIO, StringIO
|
||||
|
||||
from PIL import Image, IptcImagePlugin
|
||||
|
||||
|
@ -30,6 +30,36 @@ def test_getiptcinfo_jpg_found():
|
|||
assert iptc[(2, 101)] == b"Hungary"
|
||||
|
||||
|
||||
def test_getiptcinfo_fotostation():
|
||||
# Arrange
|
||||
with open(TEST_FILE, "rb") as fp:
|
||||
data = bytearray(fp.read())
|
||||
data[86] = 240
|
||||
f = BytesIO(data)
|
||||
with Image.open(f) as im:
|
||||
# Act
|
||||
iptc = IptcImagePlugin.getiptcinfo(im)
|
||||
|
||||
# Assert
|
||||
for tag in iptc.keys():
|
||||
if tag[0] == 240:
|
||||
return
|
||||
assert False, "FotoStation tag not found"
|
||||
|
||||
|
||||
def test_getiptcinfo_zero_padding():
|
||||
# Arrange
|
||||
with Image.open(TEST_FILE) as im:
|
||||
im.info["photoshop"][0x0404] += b"\x00\x00\x00"
|
||||
|
||||
# Act
|
||||
iptc = IptcImagePlugin.getiptcinfo(im)
|
||||
|
||||
# Assert
|
||||
assert isinstance(iptc, dict)
|
||||
assert len(iptc) == 3
|
||||
|
||||
|
||||
def test_getiptcinfo_tiff_none():
|
||||
# Arrange
|
||||
with Image.open("Tests/images/hopper.tif") as im:
|
||||
|
|
|
@ -882,7 +882,10 @@ class TestFileJpeg:
|
|||
def test_getxmp(self):
|
||||
with Image.open("Tests/images/xmp_test.jpg") as im:
|
||||
if ElementTree is None:
|
||||
with pytest.warns(UserWarning):
|
||||
with pytest.warns(
|
||||
UserWarning,
|
||||
match="XMP data cannot be read without defusedxml dependency",
|
||||
):
|
||||
assert im.getxmp() == {}
|
||||
else:
|
||||
xmp = im.getxmp()
|
||||
|
@ -905,6 +908,28 @@ class TestFileJpeg:
|
|||
with Image.open("Tests/images/hopper.jpg") as im:
|
||||
assert im.getxmp() == {}
|
||||
|
||||
def test_getxmp_no_prefix(self):
|
||||
with Image.open("Tests/images/xmp_no_prefix.jpg") as im:
|
||||
if ElementTree is None:
|
||||
with pytest.warns(
|
||||
UserWarning,
|
||||
match="XMP data cannot be read without defusedxml dependency",
|
||||
):
|
||||
assert im.getxmp() == {}
|
||||
else:
|
||||
assert im.getxmp() == {"xmpmeta": {"key": "value"}}
|
||||
|
||||
def test_getxmp_padded(self):
|
||||
with Image.open("Tests/images/xmp_padded.jpg") as im:
|
||||
if ElementTree is None:
|
||||
with pytest.warns(
|
||||
UserWarning,
|
||||
match="XMP data cannot be read without defusedxml dependency",
|
||||
):
|
||||
assert im.getxmp() == {}
|
||||
else:
|
||||
assert im.getxmp() == {"xmpmeta": None}
|
||||
|
||||
@pytest.mark.timeout(timeout=1)
|
||||
def test_eof(self):
|
||||
# Even though this decoder never says that it is finished
|
||||
|
|
|
@ -92,11 +92,11 @@ class TestFilePng:
|
|||
assert im.format == "PNG"
|
||||
assert im.get_format_mimetype() == "image/png"
|
||||
|
||||
for mode in ["1", "L", "P", "RGB", "I", "I;16"]:
|
||||
for mode in ["1", "L", "P", "RGB", "I", "I;16", "I;16B"]:
|
||||
im = hopper(mode)
|
||||
im.save(test_file)
|
||||
with Image.open(test_file) as reloaded:
|
||||
if mode == "I;16":
|
||||
if mode in ("I;16", "I;16B"):
|
||||
reloaded = reloaded.convert(mode)
|
||||
assert_image_equal(reloaded, im)
|
||||
|
||||
|
@ -665,7 +665,10 @@ class TestFilePng:
|
|||
def test_getxmp(self):
|
||||
with Image.open("Tests/images/color_snakes.png") as im:
|
||||
if ElementTree is None:
|
||||
with pytest.warns(UserWarning):
|
||||
with pytest.warns(
|
||||
UserWarning,
|
||||
match="XMP data cannot be read without defusedxml dependency",
|
||||
):
|
||||
assert im.getxmp() == {}
|
||||
else:
|
||||
xmp = im.getxmp()
|
||||
|
|
|
@ -734,7 +734,10 @@ class TestFileTiff:
|
|||
def test_getxmp(self):
|
||||
with Image.open("Tests/images/lab.tif") as im:
|
||||
if ElementTree is None:
|
||||
with pytest.warns(UserWarning):
|
||||
with pytest.warns(
|
||||
UserWarning,
|
||||
match="XMP data cannot be read without defusedxml dependency",
|
||||
):
|
||||
assert im.getxmp() == {}
|
||||
else:
|
||||
xmp = im.getxmp()
|
||||
|
|
|
@ -118,7 +118,10 @@ def test_getxmp():
|
|||
|
||||
with Image.open("Tests/images/flower2.webp") as im:
|
||||
if ElementTree is None:
|
||||
with pytest.warns(UserWarning):
|
||||
with pytest.warns(
|
||||
UserWarning,
|
||||
match="XMP data cannot be read without defusedxml dependency",
|
||||
):
|
||||
assert im.getxmp() == {}
|
||||
else:
|
||||
assert (
|
||||
|
|
|
@ -638,8 +638,8 @@ class TestImage:
|
|||
im.remap_palette(None)
|
||||
|
||||
def test_remap_palette_transparency(self):
|
||||
im = Image.new("P", (1, 2))
|
||||
im.putpixel((0, 1), 1)
|
||||
im = Image.new("P", (1, 2), (0, 0, 0))
|
||||
im.putpixel((0, 1), (255, 0, 0))
|
||||
im.info["transparency"] = 0
|
||||
|
||||
im_remapped = im.remap_palette([1, 0])
|
||||
|
|
|
@ -130,9 +130,16 @@ class TestImageGetPixel(AccessTest):
|
|||
bands = Image.getmodebands(mode)
|
||||
if bands == 1:
|
||||
return 1
|
||||
if mode in ("BGR;15", "BGR;16"):
|
||||
# These modes have less than 8 bits per band
|
||||
# So (1, 2, 3) cannot be roundtripped
|
||||
return (16, 32, 49)
|
||||
return tuple(range(1, bands + 1))
|
||||
|
||||
def check(self, mode, expected_color=None):
|
||||
if self._need_cffi_access and mode.startswith("BGR;"):
|
||||
pytest.skip("Support not added to deprecated module for BGR;* modes")
|
||||
|
||||
if not expected_color:
|
||||
expected_color = self.color(mode)
|
||||
|
||||
|
@ -203,6 +210,9 @@ class TestImageGetPixel(AccessTest):
|
|||
"F",
|
||||
"P",
|
||||
"PA",
|
||||
"BGR;15",
|
||||
"BGR;16",
|
||||
"BGR;24",
|
||||
"RGB",
|
||||
"RGBA",
|
||||
"RGBX",
|
||||
|
|
|
@ -117,11 +117,11 @@ def test_trns_p(tmp_path):
|
|||
f = str(tmp_path / "temp.png")
|
||||
|
||||
im_l = im.convert("L")
|
||||
assert im_l.info["transparency"] == 1 # undone
|
||||
assert im_l.info["transparency"] == 0
|
||||
im_l.save(f)
|
||||
|
||||
im_rgb = im.convert("RGB")
|
||||
assert im_rgb.info["transparency"] == (0, 1, 2) # undone
|
||||
assert im_rgb.info["transparency"] == (0, 0, 0)
|
||||
im_rgb.save(f)
|
||||
|
||||
|
||||
|
|
|
@ -76,6 +76,15 @@ def test_mode_F():
|
|||
assert list(im.getdata()) == target
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mode", ("BGR;15", "BGR;16", "BGR;24"))
|
||||
def test_mode_BGR(mode):
|
||||
data = [(16, 32, 49), (32, 32, 98)]
|
||||
im = Image.new(mode, (1, 2))
|
||||
im.putdata(data)
|
||||
|
||||
assert list(im.getdata()) == data
|
||||
|
||||
|
||||
def test_array_B():
|
||||
# shouldn't segfault
|
||||
# see https://github.com/python-pillow/Pillow/issues/1008
|
||||
|
|
|
@ -84,3 +84,14 @@ def test_rgba_palette(mode, palette):
|
|||
im.putpalette(palette, mode)
|
||||
assert im.getpalette() == [1, 2, 3]
|
||||
assert im.palette.colors == {(1, 2, 3, 4): 0}
|
||||
|
||||
|
||||
def test_empty_palette():
|
||||
im = Image.new("P", (1, 1))
|
||||
assert im.getpalette() == []
|
||||
|
||||
|
||||
def test_undefined_palette_index():
|
||||
im = Image.new("P", (1, 1), 3)
|
||||
im.putpalette((1, 2, 3))
|
||||
assert im.convert("RGB").getpixel((0, 0)) == (0, 0, 0)
|
||||
|
|
|
@ -586,6 +586,18 @@ def test_point(points):
|
|||
assert_image_equal_tofile(im, "Tests/images/imagedraw_point.png")
|
||||
|
||||
|
||||
def test_point_I16():
|
||||
# Arrange
|
||||
im = Image.new("I;16", (1, 1))
|
||||
draw = ImageDraw.Draw(im)
|
||||
|
||||
# Act
|
||||
draw.point((0, 0), fill=0x1234)
|
||||
|
||||
# Assert
|
||||
assert im.getpixel((0, 0)) == 0x1234
|
||||
|
||||
|
||||
@pytest.mark.parametrize("points", POINTS)
|
||||
def test_polygon(points):
|
||||
# Arrange
|
||||
|
@ -732,7 +744,7 @@ def test_rectangle_I16(bbox):
|
|||
draw = ImageDraw.Draw(im)
|
||||
|
||||
# Act
|
||||
draw.rectangle(bbox, fill="black", outline="green")
|
||||
draw.rectangle(bbox, outline=0xFFFF)
|
||||
|
||||
# Assert
|
||||
assert_image_equal_tofile(im.convert("I"), "Tests/images/imagedraw_rectangle_I.png")
|
||||
|
|
|
@ -141,7 +141,9 @@ def test_I16(font):
|
|||
draw = ImageDraw.Draw(im)
|
||||
|
||||
txt = "Hello World!"
|
||||
draw.text((10, 10), txt, font=font)
|
||||
draw.text((10, 10), txt, fill=0xFFFE, font=font)
|
||||
|
||||
assert im.getpixel((12, 14)) == 0xFFFE
|
||||
|
||||
target = "Tests/images/transparent_background_text_L.png"
|
||||
assert_image_similar_tofile(im.convert("L"), target, 0.01)
|
||||
|
|
|
@ -340,6 +340,17 @@ class TestLibUnpack:
|
|||
self.assert_unpack("RGB", "G;16N", 2, (0, 1, 0), (0, 3, 0), (0, 5, 0))
|
||||
self.assert_unpack("RGB", "B;16N", 2, (0, 0, 1), (0, 0, 3), (0, 0, 5))
|
||||
|
||||
self.assert_unpack(
|
||||
"RGB", "CMYK", 4, (250, 249, 248), (242, 241, 240), (234, 233, 233)
|
||||
)
|
||||
|
||||
def test_BGR(self):
|
||||
self.assert_unpack("BGR;15", "BGR;15", 3, (8, 131, 0), (24, 0, 8), (41, 131, 8))
|
||||
self.assert_unpack(
|
||||
"BGR;16", "BGR;16", 3, (8, 64, 0), (24, 129, 0), (41, 194, 0)
|
||||
)
|
||||
self.assert_unpack("BGR;24", "BGR;24", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
|
||||
|
||||
def test_RGBA(self):
|
||||
self.assert_unpack("RGBA", "LA", 2, (1, 1, 1, 2), (3, 3, 3, 4), (5, 5, 5, 6))
|
||||
self.assert_unpack(
|
||||
|
|
|
@ -12,7 +12,7 @@ The fork author's goal is to foster and support active development of PIL throug
|
|||
|
||||
.. _GitHub Actions: https://github.com/python-pillow/Pillow/actions
|
||||
.. _AppVeyor: https://ci.appveyor.com/project/Python-pillow/pillow
|
||||
.. _Travis CI: https://app.travis-ci.com/github/python-pillow/pillow-wheels
|
||||
.. _Travis CI: https://app.travis-ci.com/github/python-pillow/Pillow
|
||||
.. _GitHub: https://github.com/python-pillow/Pillow
|
||||
.. _Python Package Index: https://pypi.org/project/Pillow/
|
||||
|
||||
|
|
|
@ -318,7 +318,7 @@ def setup(app):
|
|||
|
||||
|
||||
linkcheck_allowed_redirects = {
|
||||
r"https://bestpractices.coreinfrastructure.org/projects/6331": r"https://bestpractices.coreinfrastructure.org/en/.*", # noqa: E501
|
||||
r"https://www.bestpractices.dev/projects/6331": r"https://www.bestpractices.dev/en/.*", # noqa: E501
|
||||
r"https://badges.gitter.im/python-pillow/Pillow.svg": r"https://badges.gitter.im/repo.svg", # noqa: E501
|
||||
r"https://gitter.im/python-pillow/Pillow?.*": r"https://app.gitter.im/#/room/#python-pillow_Pillow:gitter.im?.*", # noqa: E501
|
||||
r"https://pillow.readthedocs.io/?badge=latest": r"https://pillow.readthedocs.io/en/stable/?badge=latest", # noqa: E501
|
||||
|
|
|
@ -63,8 +63,35 @@ DDS
|
|||
^^^
|
||||
|
||||
DDS is a popular container texture format used in video games and natively supported
|
||||
by DirectX. Uncompressed RGB and RGBA can be read, and (since 8.3.0) written. DXT1,
|
||||
DXT3 (since 3.4.0) and DXT5 pixel formats can be read, only in ``RGBA`` mode.
|
||||
by DirectX.
|
||||
|
||||
DXT1 and DXT5 pixel formats can be read, only in ``RGBA`` mode.
|
||||
|
||||
.. versionadded:: 3.4.0
|
||||
DXT3 images can be read in ``RGB`` mode and DX10 images can be read in
|
||||
``RGB`` and ``RGBA`` mode.
|
||||
|
||||
.. versionadded:: 6.0.0
|
||||
Uncompressed ``RGBA`` images can be read.
|
||||
|
||||
|
||||
.. versionadded:: 8.3.0
|
||||
BC5S images can be opened in ``RGB`` mode, and uncompressed ``RGB`` images
|
||||
can be read. Uncompressed data can also be saved to image files.
|
||||
|
||||
|
||||
.. versionadded:: 9.3.0
|
||||
ATI1 images can be opened in ``L`` mode and ATI2 images can be opened in
|
||||
``RGB`` mode.
|
||||
|
||||
.. versionadded:: 9.4.0
|
||||
Uncompressed ``L`` ("luminance") and ``LA`` images can be opened and saved.
|
||||
|
||||
|
||||
.. versionadded:: 10.1.0
|
||||
BC5U can be read in ``RGB`` mode, and 8-bit color indexed images can be read
|
||||
in ``P`` mode.
|
||||
|
||||
|
||||
DIB
|
||||
^^^
|
||||
|
@ -88,8 +115,13 @@ in ``L``, ``RGB`` and ``CMYK`` modes.
|
|||
Loading
|
||||
~~~~~~~
|
||||
|
||||
To use Ghostscript, Pillow searches for the "gs" executable. On Windows, it
|
||||
also searches for "gswin32c" and "gswin64c". To customise this behaviour,
|
||||
``EpsImagePlugin.gs_binary = "gswin64"`` will set the name of the executable to
|
||||
use. ``EpsImagePlugin.gs_binary = False`` will prevent Ghostscript use.
|
||||
|
||||
If Ghostscript is available, you can call the :py:meth:`~PIL.Image.Image.load`
|
||||
method with the following parameters to affect how Ghostscript renders the EPS
|
||||
method with the following parameters to affect how Ghostscript renders the EPS.
|
||||
|
||||
**scale**
|
||||
Affects the scale of the resultant rasterized image. If the EPS suggests
|
||||
|
|
|
@ -37,12 +37,12 @@ Pillow for enterprise is available via the Tidelift Subscription. `Learn more <h
|
|||
:target: https://ci.appveyor.com/project/python-pillow/Pillow
|
||||
:alt: AppVeyor CI build status (Windows)
|
||||
|
||||
.. image:: https://github.com/python-pillow/pillow-wheels/workflows/Wheels/badge.svg
|
||||
:target: https://github.com/python-pillow/pillow-wheels/actions
|
||||
:alt: GitHub Actions wheels build status (Wheels)
|
||||
.. image:: https://github.com/python-pillow/Pillow/workflows/Wheels/badge.svg
|
||||
:target: https://github.com/python-pillow/Pillow/actions/workflows/wheels.yml
|
||||
:alt: GitHub Actions build status (Wheels)
|
||||
|
||||
.. image:: https://img.shields.io/travis/com/python-pillow/pillow-wheels/main.svg?label=aarch64%20wheels
|
||||
:target: https://app.travis-ci.com/github/python-pillow/pillow-wheels
|
||||
.. image:: https://img.shields.io/travis/com/python-pillow/Pillow/main.svg?label=aarch64%20wheels
|
||||
:target: https://app.travis-ci.com/github/python-pillow/Pillow
|
||||
:alt: Travis CI wheels build status (aarch64)
|
||||
|
||||
.. image:: https://codecov.io/gh/python-pillow/Pillow/branch/main/graph/badge.svg
|
||||
|
@ -69,8 +69,8 @@ Pillow for enterprise is available via the Tidelift Subscription. `Learn more <h
|
|||
:target: https://pypi.org/project/Pillow/
|
||||
:alt: Number of PyPI downloads
|
||||
|
||||
.. image:: https://bestpractices.coreinfrastructure.org/projects/6331/badge
|
||||
:target: https://bestpractices.coreinfrastructure.org/projects/6331
|
||||
.. image:: https://www.bestpractices.dev/projects/6331/badge
|
||||
:target: https://www.bestpractices.dev/projects/6331
|
||||
:alt: OpenSSF Best Practices
|
||||
|
||||
.. image:: https://badges.gitter.im/python-pillow/Pillow.svg
|
||||
|
|
|
@ -82,6 +82,8 @@ Install Pillow with :command:`pip`::
|
|||
|
||||
.. tab:: Windows
|
||||
|
||||
.. warning:: Pillow > 9.5.0 no longer includes 32-bit wheels.
|
||||
|
||||
We provide Pillow binaries for Windows compiled for the matrix of
|
||||
supported Pythons in 64-bit versions in the wheel format. These binaries include
|
||||
support for all optional libraries except libimagequant and libxcb. Raqm support
|
||||
|
@ -154,7 +156,7 @@ Many of Pillow's features require external libraries:
|
|||
|
||||
* **libtiff** provides compressed TIFF functionality
|
||||
|
||||
* Pillow has been tested with libtiff versions **3.x** and **4.0-4.5.1**
|
||||
* Pillow has been tested with libtiff versions **3.x** and **4.0-4.6.0**
|
||||
|
||||
* **libfreetype** provides type related services
|
||||
|
||||
|
|
|
@ -13,21 +13,30 @@ not about removing existing functionality, but instead about raising an
|
|||
explicit error to prevent later consequences. The ``convert`` method is the
|
||||
correct way to change an image's mode.
|
||||
|
||||
Deprecations
|
||||
============
|
||||
|
||||
TODO
|
||||
^^^^
|
||||
|
||||
TODO
|
||||
|
||||
API Changes
|
||||
===========
|
||||
|
||||
TODO
|
||||
^^^^
|
||||
Accept a list in getpixel()
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
TODO
|
||||
:py:meth:`~PIL.Image.Image.getpixel` now accepts a list of coordinates, as well
|
||||
as a tuple. ::
|
||||
|
||||
from PIL import Image
|
||||
im = Image.new("RGB", (1, 1))
|
||||
im.getpixel((0, 0))
|
||||
im.getpixel([0, 0])
|
||||
|
||||
BoxBlur and GaussianBlur allow for different x and y radii
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:py:class:`~PIL.ImageFilter.BoxBlur` and
|
||||
:py:class:`~PIL.ImageFilter.GaussianBlur` now allow a sequence of x and y radii
|
||||
to be specified, rather than a single number for both dimensions. ::
|
||||
|
||||
from PIL import ImageFilter
|
||||
ImageFilter.BoxBlur((2, 5))
|
||||
ImageFilter.GaussianBlur((2, 5))
|
||||
|
||||
API Additions
|
||||
=============
|
||||
|
@ -38,9 +47,17 @@ ImageOps.cover
|
|||
Returns a resized version of the image, so that the requested size is covered,
|
||||
while maintaining the original aspect ratio.
|
||||
|
||||
See :ref:`relative-resize` for a comparison between this and similar ImageOps
|
||||
See :ref:`relative-resize` for a comparison between this and similar ``ImageOps``
|
||||
methods.
|
||||
|
||||
EpsImagePlugin.gs_binary
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
``EpsImagePlugin.gs_windows_binary`` stores the name of the Ghostscript
|
||||
executable on Windows. ``EpsImagePlugin.gs_binary`` has now been added for all
|
||||
platforms, and can be used to customise the name of the executable, or disable
|
||||
use entirely through ``EpsImagePlugin.gs_binary = False``.
|
||||
|
||||
has_transparency_data
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -52,18 +69,17 @@ channel, a palette with an alpha channel, or a "transparency" key in the
|
|||
Even if this attribute is true, the image might still appear solid, if all of
|
||||
the values shown within are opaque.
|
||||
|
||||
Security
|
||||
========
|
||||
|
||||
TODO
|
||||
^^^^
|
||||
|
||||
TODO
|
||||
|
||||
Other Changes
|
||||
=============
|
||||
|
||||
TODO
|
||||
^^^^
|
||||
Added support for DDS BC5U and 8-bit color indexed images
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
TODO
|
||||
Support has been added to read BC5U DDS files as RGB images, and
|
||||
PALETTEINDEXED8 DDS files as P mode images.
|
||||
|
||||
Support reading signed 8-bit YCbCr TIFF images
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
TIFF images with unsigned integer data, 8 bits per sample and a photometric
|
||||
interpretation of YCbCr can now be read.
|
||||
|
|
|
@ -419,9 +419,11 @@ class BLPEncoder(ImageFile.PyEncoder):
|
|||
def _write_palette(self):
|
||||
data = b""
|
||||
palette = self.im.getpalette("RGBA", "RGBA")
|
||||
for i in range(256):
|
||||
for i in range(len(palette) // 4):
|
||||
r, g, b, a = palette[i * 4 : (i + 1) * 4]
|
||||
data += struct.pack("<4B", b, g, r, a)
|
||||
while len(data) < 256 * 4:
|
||||
data += b"\x00" * 4
|
||||
return data
|
||||
|
||||
def encode(self, bufsize):
|
||||
|
@ -442,7 +444,7 @@ class BLPEncoder(ImageFile.PyEncoder):
|
|||
return len(data), 0, data
|
||||
|
||||
|
||||
def _save(im, fp, filename, save_all=False):
|
||||
def _save(im, fp, filename):
|
||||
if im.mode != "P":
|
||||
msg = "Unsupported BLP image mode"
|
||||
raise ValueError(msg)
|
||||
|
|
|
@ -13,7 +13,7 @@ Full text of the CC0 license:
|
|||
import struct
|
||||
from io import BytesIO
|
||||
|
||||
from . import Image, ImageFile
|
||||
from . import Image, ImageFile, ImagePalette
|
||||
from ._binary import o32le as o32
|
||||
|
||||
# Magic ("DDS ")
|
||||
|
@ -157,6 +157,10 @@ class DdsImageFile(ImageFile.ImageFile):
|
|||
rawmode += masks[0xFF0000] + masks[0xFF00] + masks[0xFF]
|
||||
|
||||
self.tile = [("raw", (0, 0) + self.size, 0, (rawmode[::-1], 0, 1))]
|
||||
elif pfflags & DDPF_PALETTEINDEXED8:
|
||||
self._mode = "P"
|
||||
self.palette = ImagePalette.raw("RGBA", self.fp.read(1024))
|
||||
self.tile = [("raw", (0, 0) + self.size, 0, "L")]
|
||||
else:
|
||||
data_start = header_size + 4
|
||||
n = 0
|
||||
|
|
|
@ -37,33 +37,39 @@ from ._deprecate import deprecate
|
|||
split = re.compile(r"^%%([^:]*):[ \t]*(.*)[ \t]*$")
|
||||
field = re.compile(r"^%[%!\w]([^:]*)[ \t]*$")
|
||||
|
||||
gs_binary = None
|
||||
gs_windows_binary = None
|
||||
if sys.platform.startswith("win"):
|
||||
import shutil
|
||||
|
||||
for binary in ("gswin32c", "gswin64c", "gs"):
|
||||
if shutil.which(binary) is not None:
|
||||
gs_windows_binary = binary
|
||||
break
|
||||
else:
|
||||
gs_windows_binary = False
|
||||
|
||||
|
||||
def has_ghostscript():
|
||||
if gs_windows_binary:
|
||||
return True
|
||||
if not sys.platform.startswith("win"):
|
||||
try:
|
||||
subprocess.check_call(["gs", "--version"], stdout=subprocess.DEVNULL)
|
||||
return True
|
||||
except OSError:
|
||||
# No Ghostscript
|
||||
pass
|
||||
return False
|
||||
global gs_binary, gs_windows_binary
|
||||
if gs_binary is None:
|
||||
if sys.platform.startswith("win"):
|
||||
if gs_windows_binary is None:
|
||||
import shutil
|
||||
|
||||
for binary in ("gswin32c", "gswin64c", "gs"):
|
||||
if shutil.which(binary) is not None:
|
||||
gs_windows_binary = binary
|
||||
break
|
||||
else:
|
||||
gs_windows_binary = False
|
||||
gs_binary = gs_windows_binary
|
||||
else:
|
||||
try:
|
||||
subprocess.check_call(["gs", "--version"], stdout=subprocess.DEVNULL)
|
||||
gs_binary = "gs"
|
||||
except OSError:
|
||||
gs_binary = False
|
||||
return gs_binary is not False
|
||||
|
||||
|
||||
def Ghostscript(tile, size, fp, scale=1, transparency=False):
|
||||
"""Render an image using Ghostscript"""
|
||||
global gs_binary
|
||||
if not has_ghostscript():
|
||||
msg = "Unable to locate Ghostscript on paths"
|
||||
raise OSError(msg)
|
||||
|
||||
# Unpack decoder tile
|
||||
decoder, tile, offset, data = tile[0]
|
||||
|
@ -113,7 +119,7 @@ def Ghostscript(tile, size, fp, scale=1, transparency=False):
|
|||
|
||||
# Build Ghostscript command
|
||||
command = [
|
||||
"gs",
|
||||
gs_binary,
|
||||
"-q", # quiet mode
|
||||
"-g%dx%d" % size, # set output geometry (pixels)
|
||||
"-r%fx%f" % res, # set input DPI (dots per inch)
|
||||
|
@ -132,19 +138,6 @@ def Ghostscript(tile, size, fp, scale=1, transparency=False):
|
|||
"showpage",
|
||||
]
|
||||
|
||||
if gs_windows_binary is not None:
|
||||
if not gs_windows_binary:
|
||||
try:
|
||||
os.unlink(outfile)
|
||||
if infile_temp:
|
||||
os.unlink(infile_temp)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
msg = "Unable to locate Ghostscript on paths"
|
||||
raise OSError(msg)
|
||||
command[0] = gs_windows_binary
|
||||
|
||||
# push data through Ghostscript
|
||||
try:
|
||||
startupinfo = None
|
||||
|
@ -233,7 +226,9 @@ class EpsImageFile(ImageFile.ImageFile):
|
|||
byte_arr = bytearray(255)
|
||||
bytes_mv = memoryview(byte_arr)
|
||||
bytes_read = 0
|
||||
reading_comments = True
|
||||
reading_header_comments = True
|
||||
reading_trailer_comments = False
|
||||
trailer_reached = False
|
||||
|
||||
def check_required_header_comments():
|
||||
if "PS-Adobe" not in self.info:
|
||||
|
@ -243,6 +238,36 @@ class EpsImageFile(ImageFile.ImageFile):
|
|||
msg = 'EPS header missing "%%BoundingBox" comment'
|
||||
raise SyntaxError(msg)
|
||||
|
||||
def _read_comment(s):
|
||||
nonlocal reading_trailer_comments
|
||||
try:
|
||||
m = split.match(s)
|
||||
except re.error as e:
|
||||
msg = "not an EPS file"
|
||||
raise SyntaxError(msg) from e
|
||||
|
||||
if m:
|
||||
k, v = m.group(1, 2)
|
||||
self.info[k] = v
|
||||
if k == "BoundingBox":
|
||||
if v == "(atend)":
|
||||
reading_trailer_comments = True
|
||||
elif not self._size or (
|
||||
trailer_reached and reading_trailer_comments
|
||||
):
|
||||
try:
|
||||
# Note: The DSC spec says that BoundingBox
|
||||
# fields should be integers, but some drivers
|
||||
# put floating point values there anyway.
|
||||
box = [int(float(i)) for i in v.split()]
|
||||
self._size = box[2] - box[0], box[3] - box[1]
|
||||
self.tile = [
|
||||
("eps", (0, 0) + self.size, offset, (length, box))
|
||||
]
|
||||
except Exception:
|
||||
pass
|
||||
return True
|
||||
|
||||
while True:
|
||||
byte = self.fp.read(1)
|
||||
if byte == b"":
|
||||
|
@ -265,9 +290,9 @@ class EpsImageFile(ImageFile.ImageFile):
|
|||
msg = "not an EPS file"
|
||||
raise SyntaxError(msg)
|
||||
else:
|
||||
if reading_comments:
|
||||
if reading_header_comments:
|
||||
check_required_header_comments()
|
||||
reading_comments = False
|
||||
reading_header_comments = False
|
||||
# reset bytes_read so we can keep reading
|
||||
# data until the end of the line
|
||||
bytes_read = 0
|
||||
|
@ -275,7 +300,7 @@ class EpsImageFile(ImageFile.ImageFile):
|
|||
bytes_read += 1
|
||||
continue
|
||||
|
||||
if reading_comments:
|
||||
if reading_header_comments:
|
||||
# Load EPS header
|
||||
|
||||
# if this line doesn't start with a "%",
|
||||
|
@ -283,33 +308,11 @@ class EpsImageFile(ImageFile.ImageFile):
|
|||
# then we've reached the end of the header/comments
|
||||
if byte_arr[0] != ord("%") or bytes_mv[:13] == b"%%EndComments":
|
||||
check_required_header_comments()
|
||||
reading_comments = False
|
||||
reading_header_comments = False
|
||||
continue
|
||||
|
||||
s = str(bytes_mv[:bytes_read], "latin-1")
|
||||
|
||||
try:
|
||||
m = split.match(s)
|
||||
except re.error as e:
|
||||
msg = "not an EPS file"
|
||||
raise SyntaxError(msg) from e
|
||||
|
||||
if m:
|
||||
k, v = m.group(1, 2)
|
||||
self.info[k] = v
|
||||
if k == "BoundingBox":
|
||||
try:
|
||||
# Note: The DSC spec says that BoundingBox
|
||||
# fields should be integers, but some drivers
|
||||
# put floating point values there anyway.
|
||||
box = [int(float(i)) for i in v.split()]
|
||||
self._size = box[2] - box[0], box[3] - box[1]
|
||||
self.tile = [
|
||||
("eps", (0, 0) + self.size, offset, (length, box))
|
||||
]
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
if not _read_comment(s):
|
||||
m = field.match(s)
|
||||
if m:
|
||||
k = m.group(1)
|
||||
|
@ -355,7 +358,18 @@ class EpsImageFile(ImageFile.ImageFile):
|
|||
|
||||
self._size = columns, rows
|
||||
return
|
||||
elif trailer_reached and reading_trailer_comments:
|
||||
# Load EPS trailer
|
||||
|
||||
# if this line starts with "%%EOF",
|
||||
# then we've reached the end of the file
|
||||
if bytes_mv[:5] == b"%%EOF":
|
||||
break
|
||||
|
||||
s = str(bytes_mv[:bytes_read], "latin-1")
|
||||
_read_comment(s)
|
||||
elif bytes_mv[:9] == b"%%Trailer":
|
||||
trailer_reached = True
|
||||
bytes_read = 0
|
||||
|
||||
check_required_header_comments()
|
||||
|
|
|
@ -1074,7 +1074,7 @@ class Image:
|
|||
if mode == "P" and palette != Palette.ADAPTIVE:
|
||||
from . import ImagePalette
|
||||
|
||||
new_im.palette = ImagePalette.ImagePalette("RGB", list(range(256)) * 3)
|
||||
new_im.palette = ImagePalette.ImagePalette("RGB", im.getpalette("RGB"))
|
||||
if delete_trns:
|
||||
# crash fail if we leave a bytes transparency in an rgb/l mode.
|
||||
del new_im.info["transparency"]
|
||||
|
@ -1385,7 +1385,7 @@ class Image:
|
|||
|
||||
def _getxmp(self, xmp_tags):
|
||||
def get_name(tag):
|
||||
return tag.split("}")[1]
|
||||
return re.sub("^{[^}]+}", "", tag)
|
||||
|
||||
def get_value(element):
|
||||
value = {get_name(k): v for k, v in element.attrib.items()}
|
||||
|
|
|
@ -563,14 +563,21 @@ class FreeTypeFont:
|
|||
if start is None:
|
||||
start = (0, 0)
|
||||
im = None
|
||||
size = None
|
||||
|
||||
def fill(mode, size):
|
||||
nonlocal im
|
||||
def fill(mode, im_size):
|
||||
nonlocal im, size
|
||||
|
||||
size = im_size
|
||||
if Image.MAX_IMAGE_PIXELS is not None:
|
||||
pixels = max(1, size[0]) * max(1, size[1])
|
||||
if pixels > 2 * Image.MAX_IMAGE_PIXELS:
|
||||
return
|
||||
|
||||
im = Image.core.fill(mode, size)
|
||||
return im
|
||||
|
||||
size, offset = self.font.render(
|
||||
offset = self.font.render(
|
||||
text,
|
||||
fill,
|
||||
mode,
|
||||
|
@ -582,7 +589,6 @@ class FreeTypeFont:
|
|||
ink,
|
||||
start[0],
|
||||
start[1],
|
||||
Image.MAX_IMAGE_PIXELS,
|
||||
)
|
||||
Image._decompression_bomb_check(size)
|
||||
return im, offset
|
||||
|
|
|
@ -58,13 +58,13 @@ class IptcImageFile(ImageFile.ImageFile):
|
|||
#
|
||||
# get a IPTC field header
|
||||
s = self.fp.read(5)
|
||||
if not len(s):
|
||||
if not s.strip(b"\x00"):
|
||||
return None, 0
|
||||
|
||||
tag = s[1], s[2]
|
||||
|
||||
# syntax
|
||||
if s[0] != 0x1C or tag[0] < 1 or tag[0] > 9:
|
||||
if s[0] != 0x1C or tag[0] not in [1, 2, 3, 4, 5, 6, 7, 8, 9, 240]:
|
||||
msg = "invalid IPTC/NAA file"
|
||||
raise SyntaxError(msg)
|
||||
|
||||
|
|
|
@ -496,7 +496,7 @@ class JpegImageFile(ImageFile.ImageFile):
|
|||
|
||||
for segment, content in self.applist:
|
||||
if segment == "APP1":
|
||||
marker, xmp_tags = content.rsplit(b"\x00", 1)
|
||||
marker, xmp_tags = content.split(b"\x00")[:2]
|
||||
if marker == b"http://ns.adobe.com/xap/1.0/":
|
||||
return self._getxmp(xmp_tags)
|
||||
return {}
|
||||
|
|
|
@ -1042,6 +1042,7 @@ _OUTMODES = {
|
|||
"LA": ("LA", b"\x08\x04"),
|
||||
"I": ("I;16B", b"\x10\x00"),
|
||||
"I;16": ("I;16B", b"\x10\x00"),
|
||||
"I;16B": ("I;16B", b"\x10\x00"),
|
||||
"P;1": ("P;1", b"\x01\x03"),
|
||||
"P;2": ("P;2", b"\x02\x03"),
|
||||
"P;4": ("P;4", b"\x04\x03"),
|
||||
|
|
|
@ -251,6 +251,8 @@ OPEN_INFO = {
|
|||
(II, 5, (1,), 1, (8, 8, 8, 8, 8, 8), (0, 0)): ("CMYK", "CMYKXX"),
|
||||
(MM, 5, (1,), 1, (8, 8, 8, 8, 8, 8), (0, 0)): ("CMYK", "CMYKXX"),
|
||||
(II, 5, (1,), 1, (16, 16, 16, 16), ()): ("CMYK", "CMYK;16L"),
|
||||
(II, 6, (1,), 1, (8,), ()): ("L", "L"),
|
||||
(MM, 6, (1,), 1, (8,), ()): ("L", "L"),
|
||||
# JPEG compressed images handled by LibTiff and auto-converted to RGBX
|
||||
# Minimal Baseline TIFF requires YCbCr images to have 3 SamplesPerPixel
|
||||
(II, 6, (1,), 1, (8, 8, 8), ()): ("RGB", "RGBX"),
|
||||
|
|
|
@ -475,8 +475,10 @@ getpixel(Imaging im, ImagingAccess access, int x, int y) {
|
|||
case IMAGING_TYPE_FLOAT32:
|
||||
return PyFloat_FromDouble(pixel.f);
|
||||
case IMAGING_TYPE_SPECIAL:
|
||||
if (strncmp(im->mode, "I;16", 4) == 0) {
|
||||
if (im->bands == 1) {
|
||||
return PyLong_FromLong(pixel.h);
|
||||
} else {
|
||||
return Py_BuildValue("BBB", pixel.b[0], pixel.b[1], pixel.b[2]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -599,7 +601,7 @@ getink(PyObject *color, Imaging im, char *ink) {
|
|||
} else if (tupleSize != 3) {
|
||||
PyErr_SetString(PyExc_TypeError, "color must be int, or tuple of one or three elements");
|
||||
return NULL;
|
||||
} else if (!PyArg_ParseTuple(color, "Lii", &r, &g, &b)) {
|
||||
} else if (!PyArg_ParseTuple(color, "iiL", &b, &g, &r)) {
|
||||
return NULL;
|
||||
}
|
||||
if (!strcmp(im->mode, "BGR;15")) {
|
||||
|
@ -1571,21 +1573,46 @@ if (PySequence_Check(op)) { \
|
|||
PyErr_SetString(PyExc_TypeError, must_be_sequence);
|
||||
return NULL;
|
||||
}
|
||||
int endian = strncmp(image->mode, "I;16", 4) == 0 ? (strcmp(image->mode, "I;16B") == 0 ? 2 : 1) : 0;
|
||||
double value;
|
||||
for (i = x = y = 0; i < n; i++) {
|
||||
set_value_to_item(seq, i);
|
||||
if (scale != 1.0 || offset != 0.0) {
|
||||
value = value * scale + offset;
|
||||
if (image->bands == 1) {
|
||||
int bigendian;
|
||||
if (image->type == IMAGING_TYPE_SPECIAL) {
|
||||
// I;16*
|
||||
bigendian = strcmp(image->mode, "I;16B") == 0;
|
||||
}
|
||||
if (endian == 0) {
|
||||
image->image8[y][x] = (UINT8)CLIP8(value);
|
||||
} else {
|
||||
image->image8[y][x * 2 + (endian == 2 ? 1 : 0)] = CLIP8((int)value % 256);
|
||||
image->image8[y][x * 2 + (endian == 2 ? 0 : 1)] = CLIP8((int)value >> 8);
|
||||
for (i = x = y = 0; i < n; i++) {
|
||||
set_value_to_item(seq, i);
|
||||
if (scale != 1.0 || offset != 0.0) {
|
||||
value = value * scale + offset;
|
||||
}
|
||||
if (image->type == IMAGING_TYPE_SPECIAL) {
|
||||
image->image8[y][x * 2 + (bigendian ? 1 : 0)] = CLIP8((int)value % 256);
|
||||
image->image8[y][x * 2 + (bigendian ? 0 : 1)] = CLIP8((int)value >> 8);
|
||||
} else {
|
||||
image->image8[y][x] = (UINT8)CLIP8(value);
|
||||
}
|
||||
if (++x >= (int)image->xsize) {
|
||||
x = 0, y++;
|
||||
}
|
||||
}
|
||||
if (++x >= (int)image->xsize) {
|
||||
x = 0, y++;
|
||||
} else {
|
||||
// BGR;*
|
||||
int b;
|
||||
for (i = x = y = 0; i < n; i++) {
|
||||
char ink[4];
|
||||
|
||||
op = PySequence_Fast_GET_ITEM(seq, i);
|
||||
if (!op || !getink(op, image, ink)) {
|
||||
Py_DECREF(seq);
|
||||
return NULL;
|
||||
}
|
||||
/* FIXME: what about scale and offset? */
|
||||
for (b = 0; b < image->pixelsize; b++) {
|
||||
image->image8[y][x * image->pixelsize + b] = ink[b];
|
||||
}
|
||||
if (++x >= (int)image->xsize) {
|
||||
x = 0, y++;
|
||||
}
|
||||
}
|
||||
}
|
||||
PyErr_Clear(); /* Avoid weird exceptions */
|
||||
|
|
|
@ -815,7 +815,6 @@ font_render(FontObject *self, PyObject *args) {
|
|||
float y_start = 0;
|
||||
int width, height, x_offset, y_offset;
|
||||
int horizontal_dir; /* is primary axis horizontal? */
|
||||
PyObject *max_image_pixels = Py_None;
|
||||
|
||||
/* render string into given buffer (the buffer *must* have
|
||||
the right size, or this will crash) */
|
||||
|
@ -833,8 +832,7 @@ font_render(FontObject *self, PyObject *args) {
|
|||
&anchor,
|
||||
&foreground_ink_long,
|
||||
&x_start,
|
||||
&y_start,
|
||||
&max_image_pixels)) {
|
||||
&y_start)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -879,15 +877,11 @@ font_render(FontObject *self, PyObject *args) {
|
|||
|
||||
width += stroke_width * 2 + ceil(x_start);
|
||||
height += stroke_width * 2 + ceil(y_start);
|
||||
if (max_image_pixels != Py_None) {
|
||||
if ((long long)(width > 1 ? width : 1) * (height > 1 ? height : 1) > PyLong_AsLongLong(max_image_pixels) * 2) {
|
||||
PyMem_Del(glyph_info);
|
||||
return Py_BuildValue("(ii)(ii)", width, height, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
image = PyObject_CallFunction(fill, "s(ii)", strcmp(mode, "RGBA") == 0 ? "RGBA" : "L", width, height);
|
||||
if (image == NULL) {
|
||||
if (image == Py_None) {
|
||||
PyMem_Del(glyph_info);
|
||||
return Py_BuildValue("ii", 0, 0);
|
||||
} else if (image == NULL) {
|
||||
PyMem_Del(glyph_info);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -898,7 +892,7 @@ font_render(FontObject *self, PyObject *args) {
|
|||
y_offset -= stroke_width;
|
||||
if (count == 0 || width == 0 || height == 0) {
|
||||
PyMem_Del(glyph_info);
|
||||
return Py_BuildValue("(ii)(ii)", width, height, x_offset, y_offset);
|
||||
return Py_BuildValue("ii", x_offset, y_offset);
|
||||
}
|
||||
|
||||
if (stroke_width) {
|
||||
|
@ -1116,7 +1110,7 @@ font_render(FontObject *self, PyObject *args) {
|
|||
Py_DECREF(image);
|
||||
FT_Stroker_Done(stroker);
|
||||
PyMem_Del(glyph_info);
|
||||
return Py_BuildValue("(ii)(ii)", width, height, x_offset, y_offset);
|
||||
return Py_BuildValue("ii", x_offset, y_offset);
|
||||
|
||||
glyph_error:
|
||||
if (im->destroy) {
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
#include "Imaging.h"
|
||||
|
||||
/* use make_hash.py from the pillow-scripts repository to calculate these values */
|
||||
#define ACCESS_TABLE_SIZE 27
|
||||
#define ACCESS_TABLE_HASH 33051
|
||||
#define ACCESS_TABLE_SIZE 35
|
||||
#define ACCESS_TABLE_HASH 8940
|
||||
|
||||
static struct ImagingAccessInstance access_table[ACCESS_TABLE_SIZE];
|
||||
|
||||
|
@ -87,6 +87,31 @@ get_pixel_16(Imaging im, int x, int y, void *color) {
|
|||
memcpy(color, in, sizeof(UINT16));
|
||||
}
|
||||
|
||||
static void
|
||||
get_pixel_BGR15(Imaging im, int x, int y, void *color) {
|
||||
UINT8 *in = (UINT8 *)&im->image8[y][x * 2];
|
||||
UINT16 pixel = in[0] + (in[1] << 8);
|
||||
char *out = color;
|
||||
out[0] = (pixel & 31) * 255 / 31;
|
||||
out[1] = ((pixel >> 5) & 31) * 255 / 31;
|
||||
out[2] = ((pixel >> 10) & 31) * 255 / 31;
|
||||
}
|
||||
|
||||
static void
|
||||
get_pixel_BGR16(Imaging im, int x, int y, void *color) {
|
||||
UINT8 *in = (UINT8 *)&im->image8[y][x * 2];
|
||||
UINT16 pixel = in[0] + (in[1] << 8);
|
||||
char *out = color;
|
||||
out[0] = (pixel & 31) * 255 / 31;
|
||||
out[1] = ((pixel >> 5) & 63) * 255 / 63;
|
||||
out[2] = ((pixel >> 11) & 31) * 255 / 31;
|
||||
}
|
||||
|
||||
static void
|
||||
get_pixel_BGR24(Imaging im, int x, int y, void *color) {
|
||||
memcpy(color, &im->image8[y][x * 3], sizeof(UINT8) * 3);
|
||||
}
|
||||
|
||||
static void
|
||||
get_pixel_32(Imaging im, int x, int y, void *color) {
|
||||
memcpy(color, &im->image32[y][x], sizeof(INT32));
|
||||
|
@ -134,6 +159,16 @@ put_pixel_16B(Imaging im, int x, int y, const void *color) {
|
|||
out[1] = in[0];
|
||||
}
|
||||
|
||||
static void
|
||||
put_pixel_BGR1516(Imaging im, int x, int y, const void *color) {
|
||||
memcpy(&im->image8[y][x * 2], color, 2);
|
||||
}
|
||||
|
||||
static void
|
||||
put_pixel_BGR24(Imaging im, int x, int y, const void *color) {
|
||||
memcpy(&im->image8[y][x * 3], color, 3);
|
||||
}
|
||||
|
||||
static void
|
||||
put_pixel_32L(Imaging im, int x, int y, const void *color) {
|
||||
memcpy(&im->image8[y][x * 4], color, 4);
|
||||
|
@ -178,6 +213,9 @@ ImagingAccessInit() {
|
|||
ADD("F", get_pixel_32, put_pixel_32);
|
||||
ADD("P", get_pixel_8, put_pixel_8);
|
||||
ADD("PA", get_pixel_32_2bands, put_pixel_32);
|
||||
ADD("BGR;15", get_pixel_BGR15, put_pixel_BGR1516);
|
||||
ADD("BGR;16", get_pixel_BGR16, put_pixel_BGR1516);
|
||||
ADD("BGR;24", get_pixel_BGR24, put_pixel_BGR24);
|
||||
ADD("RGB", get_pixel_32, put_pixel_32);
|
||||
ADD("RGBA", get_pixel_32, put_pixel_32);
|
||||
ADD("RGBa", get_pixel_32, put_pixel_32);
|
||||
|
|
|
@ -850,10 +850,12 @@ decode_bcn(
|
|||
DECODE_LOOP(3, 16, rgba);
|
||||
DECODE_LOOP(4, 8, lum);
|
||||
case 5:
|
||||
{
|
||||
int sign = strcmp(pixel_format, "BC5S") == 0 ? 1 : 0;
|
||||
while (bytes >= 16) {
|
||||
rgba col[16];
|
||||
memset(col, 0, 16 * sizeof(col[0]));
|
||||
decode_bc5_block(col, ptr, strcmp(pixel_format, "BC5S") == 0 ? 1 : 0);
|
||||
memset(col, sign ? 128 : 0, 16 * sizeof(col[0]));
|
||||
decode_bc5_block(col, ptr, sign);
|
||||
put_block(im, state, (const char *)col, sizeof(col[0]), C);
|
||||
ptr += 16;
|
||||
bytes -= 16;
|
||||
|
@ -862,10 +864,13 @@ decode_bcn(
|
|||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
int sign = strcmp(pixel_format, "BC6HS") == 0 ? 1 : 0;
|
||||
while (bytes >= 16) {
|
||||
rgba col[16];
|
||||
decode_bc6_block(col, ptr, strcmp(pixel_format, "BC6HS") == 0 ? 1 : 0);
|
||||
decode_bc6_block(col, ptr, sign);
|
||||
put_block(im, state, (const char *)col, sizeof(col[0]), C);
|
||||
ptr += 16;
|
||||
bytes -= 16;
|
||||
|
@ -874,6 +879,7 @@ decode_bcn(
|
|||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
DECODE_LOOP(7, 16, rgba);
|
||||
#undef DECODE_LOOP
|
||||
}
|
||||
|
|
|
@ -564,7 +564,7 @@ rgb2cmyk(UINT8 *out, const UINT8 *in, int xsize) {
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
cmyk2rgb(UINT8 *out, const UINT8 *in, int xsize) {
|
||||
int x, nk, tmp;
|
||||
for (x = 0; x < xsize; x++) {
|
||||
|
@ -1295,7 +1295,6 @@ topalette(
|
|||
int alpha;
|
||||
int x, y;
|
||||
ImagingPalette palette = inpalette;
|
||||
;
|
||||
|
||||
/* Map L or RGB/RGBX/RGBA to palette image */
|
||||
if (strcmp(imIn->mode, "L") != 0 && strncmp(imIn->mode, "RGB", 3) != 0) {
|
||||
|
@ -1307,7 +1306,14 @@ topalette(
|
|||
if (palette == NULL) {
|
||||
/* FIXME: make user configurable */
|
||||
if (imIn->bands == 1) {
|
||||
palette = ImagingPaletteNew("RGB"); /* Initialised to grey ramp */
|
||||
palette = ImagingPaletteNew("RGB");
|
||||
|
||||
palette->size = 256;
|
||||
int i;
|
||||
for (i = 0; i < 256; i++) {
|
||||
palette->palette[i * 4] = palette->palette[i * 4 + 1] =
|
||||
palette->palette[i * 4 + 2] = (UINT8)i;
|
||||
}
|
||||
} else {
|
||||
palette = ImagingPaletteNewBrowser(); /* Standard colour cube */
|
||||
}
|
||||
|
|
2
src/libImaging/Convert.h
Normal file
2
src/libImaging/Convert.h
Normal file
|
@ -0,0 +1,2 @@
|
|||
extern void
|
||||
cmyk2rgb(UINT8 *out, const UINT8 *in, int xsize);
|
|
@ -41,6 +41,7 @@
|
|||
#define FLOOR(v) ((v) >= 0.0 ? (int)(v) : (int)floor(v))
|
||||
|
||||
#define INK8(ink) (*(UINT8 *)ink)
|
||||
#define INK16(ink) (*(UINT16 *)ink)
|
||||
|
||||
/*
|
||||
* Rounds around zero (up=away from zero, down=towards zero)
|
||||
|
@ -68,8 +69,13 @@ static inline void
|
|||
point8(Imaging im, int x, int y, int ink) {
|
||||
if (x >= 0 && x < im->xsize && y >= 0 && y < im->ysize) {
|
||||
if (strncmp(im->mode, "I;16", 4) == 0) {
|
||||
im->image8[y][x * 2] = (UINT8)ink;
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
im->image8[y][x * 2] = (UINT8)(ink >> 8);
|
||||
im->image8[y][x * 2 + 1] = (UINT8)ink;
|
||||
#else
|
||||
im->image8[y][x * 2] = (UINT8)ink;
|
||||
im->image8[y][x * 2 + 1] = (UINT8)(ink >> 8);
|
||||
#endif
|
||||
} else {
|
||||
im->image8[y][x] = (UINT8)ink;
|
||||
}
|
||||
|
@ -631,13 +637,17 @@ DRAW draw32rgba = {point32rgba, hline32rgba, line32rgba, polygon32rgba};
|
|||
/* Interface */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
#define DRAWINIT() \
|
||||
if (im->image8) { \
|
||||
draw = &draw8; \
|
||||
ink = INK8(ink_); \
|
||||
} else { \
|
||||
draw = (op) ? &draw32rgba : &draw32; \
|
||||
memcpy(&ink, ink_, sizeof(ink)); \
|
||||
#define DRAWINIT() \
|
||||
if (im->image8) { \
|
||||
draw = &draw8; \
|
||||
if (strncmp(im->mode, "I;16", 4) == 0) { \
|
||||
ink = INK16(ink_); \
|
||||
} else { \
|
||||
ink = INK8(ink_); \
|
||||
} \
|
||||
} else { \
|
||||
draw = (op) ? &draw32rgba : &draw32; \
|
||||
memcpy(&ink, ink_, sizeof(ink)); \
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -39,11 +39,8 @@ ImagingPaletteNew(const char *mode) {
|
|||
strncpy(palette->mode, mode, IMAGING_MODE_LENGTH - 1);
|
||||
palette->mode[IMAGING_MODE_LENGTH - 1] = 0;
|
||||
|
||||
/* Initialize to ramp */
|
||||
palette->size = 256;
|
||||
palette->size = 0;
|
||||
for (i = 0; i < 256; i++) {
|
||||
palette->palette[i * 4 + 0] = palette->palette[i * 4 + 1] =
|
||||
palette->palette[i * 4 + 2] = (UINT8)i;
|
||||
palette->palette[i * 4 + 3] = 255; /* opaque */
|
||||
}
|
||||
|
||||
|
@ -62,16 +59,10 @@ ImagingPaletteNewBrowser(void) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Blank out unused entries */
|
||||
/* FIXME: Add 10-level windows palette here? */
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
palette->palette[i * 4 + 0] = palette->palette[i * 4 + 1] =
|
||||
palette->palette[i * 4 + 2] = 0;
|
||||
}
|
||||
|
||||
/* Simple 6x6x6 colour cube */
|
||||
|
||||
i = 10;
|
||||
for (b = 0; b < 256; b += 51) {
|
||||
for (g = 0; g < 256; g += 51) {
|
||||
for (r = 0; r < 256; r += 51) {
|
||||
|
@ -82,15 +73,10 @@ ImagingPaletteNewBrowser(void) {
|
|||
}
|
||||
}
|
||||
}
|
||||
palette->size = i;
|
||||
|
||||
/* Blank out unused entries */
|
||||
/* FIXME: add 30-level greyscale wedge here? */
|
||||
|
||||
for (; i < 256; i++) {
|
||||
palette->palette[i * 4 + 0] = palette->palette[i * 4 + 1] =
|
||||
palette->palette[i * 4 + 2] = 0;
|
||||
}
|
||||
|
||||
return palette;
|
||||
}
|
||||
|
||||
|
|
|
@ -425,7 +425,7 @@ fill_mask_L(
|
|||
*out = BLEND(*mask, *out, ink[0], tmp1);
|
||||
if (strncmp(imOut->mode, "I;16", 4) == 0) {
|
||||
out++;
|
||||
*out = BLEND(*mask, *out, ink[0], tmp1);
|
||||
*out = BLEND(*mask, *out, ink[1], tmp1);
|
||||
}
|
||||
out++, mask++;
|
||||
}
|
||||
|
|
|
@ -1825,6 +1825,7 @@ ImagingQuantize(Imaging im, int colors, int mode, int kmeans) {
|
|||
|
||||
free(newData);
|
||||
|
||||
imOut->palette->size = (int)paletteLength;
|
||||
pp = imOut->palette->palette;
|
||||
|
||||
for (i = j = 0; i < (int)paletteLength; i++) {
|
||||
|
@ -1832,16 +1833,9 @@ ImagingQuantize(Imaging im, int colors, int mode, int kmeans) {
|
|||
*pp++ = palette[i].c.g;
|
||||
*pp++ = palette[i].c.b;
|
||||
if (withAlpha) {
|
||||
*pp++ = palette[i].c.a;
|
||||
} else {
|
||||
*pp++ = 255;
|
||||
*pp = palette[i].c.a;
|
||||
}
|
||||
}
|
||||
for (; i < 256; i++) {
|
||||
*pp++ = 0;
|
||||
*pp++ = 0;
|
||||
*pp++ = 0;
|
||||
*pp++ = 255;
|
||||
pp++;
|
||||
}
|
||||
|
||||
if (withAlpha) {
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
*/
|
||||
|
||||
#include "Imaging.h"
|
||||
#include "Convert.h"
|
||||
|
||||
#define R 0
|
||||
#define G 1
|
||||
|
@ -1238,6 +1239,12 @@ copy2(UINT8 *out, const UINT8 *in, int pixels) {
|
|||
memcpy(out, in, pixels * 2);
|
||||
}
|
||||
|
||||
static void
|
||||
copy3(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
/* BGR;24 */
|
||||
memcpy(out, in, pixels * 3);
|
||||
}
|
||||
|
||||
static void
|
||||
copy4(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
/* RGBA, CMYK quadruples */
|
||||
|
@ -1589,6 +1596,11 @@ static struct {
|
|||
{"RGB", "R;16B", 16, band016B},
|
||||
{"RGB", "G;16B", 16, band116B},
|
||||
{"RGB", "B;16B", 16, band216B},
|
||||
{"RGB", "CMYK", 32, cmyk2rgb},
|
||||
|
||||
{"BGR;15", "BGR;15", 16, copy2},
|
||||
{"BGR;16", "BGR;16", 16, copy2},
|
||||
{"BGR;24", "BGR;24", 24, copy3},
|
||||
|
||||
/* true colour w. alpha */
|
||||
{"RGBA", "LA", 16, unpackRGBALA},
|
||||
|
|
31
wheels/README.md
Normal file
31
wheels/README.md
Normal file
|
@ -0,0 +1,31 @@
|
|||
README
|
||||
------
|
||||
|
||||
This directory creates wheels for tagged versions of Pillow.
|
||||
|
||||
Archives
|
||||
--------
|
||||
|
||||
https://github.com/python-pillow/pillow-depends contains archives for libraries
|
||||
that will be built as part of the Pillow build.
|
||||
|
||||
In general, there is no need to put library archives there, because the
|
||||
`multibuild` scripts will download them from their respective URLs.
|
||||
|
||||
But, the build will look in that repository before downloading from the
|
||||
URL, so if there is a library that often fails to download, or you think might
|
||||
fail to download, then download it and add it to the Git repository.
|
||||
|
||||
See the `pre_build` in `config.sh` and the `fetch_unpack` routine in
|
||||
`multibuild/common_utils.sh` for the logic, and the build recipes in
|
||||
`multibuild/library_builders.sh` for the filename to give to the downloaded
|
||||
archive.
|
||||
|
||||
Wheels
|
||||
------
|
||||
|
||||
Wheels are
|
||||
[GitHub Actions artifacts created for tags, relevant changes or manual builds](https://github.com/python-pillow/Pillow/actions/workflows/wheels.yml).
|
||||
|
||||
Windows wheels are not created here. Instead, they are
|
||||
[GitHub Actions artifacts created on each run of the Windows workflow](https://github.com/python-pillow/Pillow/actions/workflows/test-windows.yml?query=branch%3Amain).
|
187
wheels/config.sh
Normal file
187
wheels/config.sh
Normal file
|
@ -0,0 +1,187 @@
|
|||
# Define custom utilities
|
||||
# Test for macOS with [ -n "$IS_MACOS" ]
|
||||
|
||||
ARCHIVE_SDIR=pillow-depends-main
|
||||
|
||||
# Package versions for fresh source builds
|
||||
FREETYPE_VERSION=2.13.2
|
||||
HARFBUZZ_VERSION=8.2.1
|
||||
LIBPNG_VERSION=1.6.40
|
||||
JPEGTURBO_VERSION=3.0.0
|
||||
OPENJPEG_VERSION=2.5.0
|
||||
XZ_VERSION=5.4.4
|
||||
TIFF_VERSION=4.6.0
|
||||
LCMS2_VERSION=2.15
|
||||
if [[ -n "$IS_MACOS" ]]; then
|
||||
GIFLIB_VERSION=5.1.4
|
||||
else
|
||||
GIFLIB_VERSION=5.2.1
|
||||
fi
|
||||
if [[ -n "$IS_MACOS" ]] || [[ "$MB_ML_VER" != 2014 ]]; then
|
||||
ZLIB_VERSION=1.3
|
||||
else
|
||||
ZLIB_VERSION=1.2.8
|
||||
fi
|
||||
LIBWEBP_VERSION=1.3.2
|
||||
BZIP2_VERSION=1.0.8
|
||||
LIBXCB_VERSION=1.16
|
||||
BROTLI_VERSION=1.1.0
|
||||
|
||||
if [[ -n "$IS_MACOS" ]] && [[ "$PLAT" == "x86_64" ]]; then
|
||||
function build_openjpeg {
|
||||
local out_dir=$(fetch_unpack https://github.com/uclouvain/openjpeg/archive/v${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)
|
||||
(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 pre_build {
|
||||
# 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
|
||||
|
||||
build_xz
|
||||
if [ -z "$IS_ALPINE" ] && [ -z "$IS_MACOS" ]; then
|
||||
yum remove -y zlib-devel
|
||||
fi
|
||||
build_new_zlib
|
||||
|
||||
if [ -n "$IS_MACOS" ]; then
|
||||
ORIGINAL_BUILD_PREFIX=$BUILD_PREFIX
|
||||
ORIGINAL_PKG_CONFIG_PATH=$PKG_CONFIG_PATH
|
||||
BUILD_PREFIX=`dirname $(dirname $(which python))`
|
||||
PKG_CONFIG_PATH="$BUILD_PREFIX/lib/pkgconfig"
|
||||
fi
|
||||
build_simple xcb-proto 1.16.0 https://xorg.freedesktop.org/archive/individual/proto
|
||||
if [ -n "$IS_MACOS" ]; then
|
||||
build_simple xorgproto 2023.2 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
|
||||
cp venv/share/pkgconfig/xcb-proto.pc venv/lib/pkgconfig/xcb-proto.pc
|
||||
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
|
||||
if [ -n "$IS_MACOS" ]; then
|
||||
BUILD_PREFIX=$ORIGINAL_BUILD_PREFIX
|
||||
PKG_CONFIG_PATH=$ORIGINAL_PKG_CONFIG_PATH
|
||||
fi
|
||||
|
||||
build_libjpeg_turbo
|
||||
if [[ -n "$IS_MACOS" ]]; then
|
||||
rm /usr/local/lib/libjpeg.dylib
|
||||
fi
|
||||
build_tiff
|
||||
build_libpng
|
||||
build_lcms2
|
||||
build_openjpeg
|
||||
|
||||
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
|
||||
|
||||
# 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
|
||||
}
|
||||
|
||||
function pip_wheel_cmd {
|
||||
local abs_wheelhouse=$1
|
||||
if [ -z "$IS_MACOS" ]; then
|
||||
CFLAGS="$CFLAGS --std=c99" # for Raqm
|
||||
fi
|
||||
python3 -m pip wheel $(pip_opts) \
|
||||
-C raqm=enable -C raqm=vendor -C fribidi=vendor \
|
||||
-w $abs_wheelhouse --no-deps .
|
||||
}
|
||||
|
||||
function run_tests_in_repo {
|
||||
# Run Pillow tests from within source repo
|
||||
python3 selftest.py
|
||||
python3 -m pytest
|
||||
}
|
||||
|
||||
EXP_CODECS="jpg jpg_2000 libtiff zlib"
|
||||
EXP_MODULES="freetype2 littlecms2 pil tkinter webp"
|
||||
EXP_FEATURES="fribidi harfbuzz libjpeg_turbo raqm transp_webp webp_anim webp_mux xcb"
|
||||
|
||||
function run_tests {
|
||||
if [ -n "$IS_MACOS" ]; then
|
||||
brew install fribidi
|
||||
export PKG_CONFIG_PATH="/usr/local/opt/openblas/lib/pkgconfig"
|
||||
elif [ -n "$IS_ALPINE" ]; then
|
||||
apk add curl fribidi
|
||||
else
|
||||
apt-get update
|
||||
apt-get install -y curl libfribidi0 libopenblas-dev pkg-config unzip
|
||||
fi
|
||||
if [ -z "$IS_ALPINE" ]; then
|
||||
python3 -m pip install numpy
|
||||
fi
|
||||
python3 -m pip install defusedxml olefile pyroma
|
||||
|
||||
curl -fsSL -o pillow-test-images.zip https://github.com/python-pillow/test-images/archive/main.zip
|
||||
untar pillow-test-images.zip
|
||||
mv test-images-main/* ../Tests/images
|
||||
|
||||
# Runs tests on installed distribution from an empty directory
|
||||
(cd .. && run_tests_in_repo)
|
||||
# Test against expected codecs, modules and features
|
||||
local ret=0
|
||||
local codecs=$(python3 -c 'from PIL.features import *; print(" ".join(sorted(get_supported_codecs())))')
|
||||
if [ "$codecs" != "$EXP_CODECS" ]; then
|
||||
echo "Codecs should be: '$EXP_CODECS'; but are '$codecs'"
|
||||
ret=1
|
||||
fi
|
||||
local modules=$(python3 -c 'from PIL.features import *; print(" ".join(sorted(get_supported_modules())))')
|
||||
if [ "$modules" != "$EXP_MODULES" ]; then
|
||||
echo "Modules should be: '$EXP_MODULES'; but are '$modules'"
|
||||
ret=1
|
||||
fi
|
||||
local features=$(python3 -c 'from PIL.features import *; print(" ".join(sorted(get_supported_features())))')
|
||||
if [ "$features" != "$EXP_FEATURES" ]; then
|
||||
echo "Features should be: '$EXP_FEATURES'; but are '$features'"
|
||||
ret=1
|
||||
fi
|
||||
return $ret
|
||||
}
|
19
wheels/dependency_licenses/BROTLI.txt
Normal file
19
wheels/dependency_licenses/BROTLI.txt
Normal file
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
42
wheels/dependency_licenses/BZIP2.txt
Normal file
42
wheels/dependency_licenses/BZIP2.txt
Normal file
|
@ -0,0 +1,42 @@
|
|||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
This program, "bzip2", the associated library "libbzip2", and all
|
||||
documentation, are copyright (C) 1996-2019 Julian R Seward. All
|
||||
rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
|
||||
3. Altered source versions must be plainly marked as such, and must
|
||||
not be misrepresented as being the original software.
|
||||
|
||||
4. The name of the author may not be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Julian Seward, jseward@acm.org
|
||||
bzip2/libbzip2 version 1.0.8 of 13 July 2019
|
||||
|
||||
--------------------------------------------------------------------------
|
40
wheels/dependency_licenses/FREETYPE2.txt
Normal file
40
wheels/dependency_licenses/FREETYPE2.txt
Normal file
|
@ -0,0 +1,40 @@
|
|||
The FreeType 2 font engine is copyrighted work and cannot be used
|
||||
legally without a software license. In order to make this project
|
||||
usable to a vast majority of developers, we distribute it under two
|
||||
mutually exclusive open-source licenses.
|
||||
|
||||
This means that *you* must choose *one* of the two licenses described
|
||||
below, then obey all its terms and conditions when using FreeType 2 in
|
||||
any of your projects or products.
|
||||
|
||||
- The FreeType License, found in the file `docs/FTL.TXT`, which is
|
||||
similar to the original BSD license *with* an advertising clause
|
||||
that forces you to explicitly cite the FreeType project in your
|
||||
product's documentation. All details are in the license file.
|
||||
This license is suited to products which don't use the GNU General
|
||||
Public License.
|
||||
|
||||
Note that this license is compatible to the GNU General Public
|
||||
License version 3, but not version 2.
|
||||
|
||||
- The GNU General Public License version 2, found in
|
||||
`docs/GPLv2.TXT` (any later version can be used also), for
|
||||
programs which already use the GPL. Note that the FTL is
|
||||
incompatible with GPLv2 due to its advertisement clause.
|
||||
|
||||
The contributed BDF and PCF drivers come with a license similar to
|
||||
that of the X Window System. It is compatible to the above two
|
||||
licenses (see files `src/bdf/README` and `src/pcf/README`). The same
|
||||
holds for the source code files `src/base/fthash.c` and
|
||||
`include/freetype/internal/fthash.h`; they were part of the BDF driver
|
||||
in earlier FreeType versions.
|
||||
|
||||
The gzip module uses the zlib license (see `src/gzip/zlib.h`) which
|
||||
too is compatible to the above two licenses.
|
||||
|
||||
The files `src/autofit/ft-hb.c` and `src/autofit/ft-hb.h` contain code
|
||||
taken almost verbatim from the HarfBuzz file `hb-ft.cc`, which uses
|
||||
the 'Old MIT' license, compatible to the above two licenses.
|
||||
|
||||
The MD5 checksum support (only used for debugging in development
|
||||
builds) is in the public domain.
|
42
wheels/dependency_licenses/HARFBUZZ.txt
Normal file
42
wheels/dependency_licenses/HARFBUZZ.txt
Normal file
|
@ -0,0 +1,42 @@
|
|||
HarfBuzz is licensed under the so-called "Old MIT" license. Details follow.
|
||||
For parts of HarfBuzz that are licensed under different licenses see individual
|
||||
files names COPYING in subdirectories where applicable.
|
||||
|
||||
Copyright © 2010-2022 Google, Inc.
|
||||
Copyright © 2015-2020 Ebrahim Byagowi
|
||||
Copyright © 2019,2020 Facebook, Inc.
|
||||
Copyright © 2012,2015 Mozilla Foundation
|
||||
Copyright © 2011 Codethink Limited
|
||||
Copyright © 2008,2010 Nokia Corporation and/or its subsidiary(-ies)
|
||||
Copyright © 2009 Keith Stribley
|
||||
Copyright © 2011 Martin Hosken and SIL International
|
||||
Copyright © 2007 Chris Wilson
|
||||
Copyright © 2005,2006,2020,2021,2022,2023 Behdad Esfahbod
|
||||
Copyright © 2004,2007,2008,2009,2010,2013,2021,2022,2023 Red Hat, Inc.
|
||||
Copyright © 1998-2005 David Turner and Werner Lemberg
|
||||
Copyright © 2016 Igalia S.L.
|
||||
Copyright © 2022 Matthias Clasen
|
||||
Copyright © 2018,2021 Khaled Hosny
|
||||
Copyright © 2018,2019,2020 Adobe, Inc
|
||||
Copyright © 2013-2015 Alexei Podtelezhnikov
|
||||
|
||||
For full copyright notices consult the individual files in the package.
|
||||
|
||||
|
||||
Permission is hereby granted, without written agreement and without
|
||||
license or royalty fees, to use, copy, modify, and distribute this
|
||||
software and its documentation for any purpose, provided that the
|
||||
above copyright notice and the following two paragraphs appear in
|
||||
all copies of this software.
|
||||
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
|
||||
THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
8
wheels/dependency_licenses/LCMS2.txt
Normal file
8
wheels/dependency_licenses/LCMS2.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
Little CMS
|
||||
Copyright (c) 1998-2020 Marti Maria Saguer
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
43
wheels/dependency_licenses/LIBJPEG.txt
Normal file
43
wheels/dependency_licenses/LIBJPEG.txt
Normal file
|
@ -0,0 +1,43 @@
|
|||
1. We don't promise that this software works. (But if you find any bugs,
|
||||
please let us know!)
|
||||
2. You can use this software for whatever you want. You don't have to pay us.
|
||||
3. You may not pretend that you wrote this software. If you use it in a
|
||||
program, you must acknowledge somewhere in your documentation that
|
||||
you've used the IJG code.
|
||||
|
||||
In legalese:
|
||||
|
||||
The authors make NO WARRANTY or representation, either express or implied,
|
||||
with respect to this software, its quality, accuracy, merchantability, or
|
||||
fitness for a particular purpose. This software is provided "AS IS", and you,
|
||||
its user, assume the entire risk as to its quality and accuracy.
|
||||
|
||||
This software is copyright (C) 1991-2020, Thomas G. Lane, Guido Vollbeding.
|
||||
All Rights Reserved except as specified below.
|
||||
|
||||
Permission is hereby granted to use, copy, modify, and distribute this
|
||||
software (or portions thereof) for any purpose, without fee, subject to these
|
||||
conditions:
|
||||
(1) If any part of the source code for this software is distributed, then this
|
||||
README file must be included, with this copyright and no-warranty notice
|
||||
unaltered; and any additions, deletions, or changes to the original files
|
||||
must be clearly indicated in accompanying documentation.
|
||||
(2) If only executable code is distributed, then the accompanying
|
||||
documentation must state that "this software is based in part on the work of
|
||||
the Independent JPEG Group".
|
||||
(3) Permission for use of this software is granted only if the user accepts
|
||||
full responsibility for any undesirable consequences; the authors accept
|
||||
NO LIABILITY for damages of any kind.
|
||||
|
||||
These conditions apply to any software derived from or based on the IJG code,
|
||||
not just to the unmodified library. If you use our work, you ought to
|
||||
acknowledge us.
|
||||
|
||||
Permission is NOT granted for the use of any IJG author's name or company name
|
||||
in advertising or publicity relating to this software or products derived from
|
||||
it. This software may be referred to only as "the Independent JPEG Group's
|
||||
software".
|
||||
|
||||
We specifically permit and encourage the use of this software as the basis of
|
||||
commercial products, provided that all warranty or liability claims are
|
||||
assumed by the product vendor.
|
63
wheels/dependency_licenses/LIBLZMA.txt
Normal file
63
wheels/dependency_licenses/LIBLZMA.txt
Normal file
|
@ -0,0 +1,63 @@
|
|||
XZ Utils Licensing
|
||||
==================
|
||||
|
||||
Different licenses apply to different files in this package. Here
|
||||
is a rough summary of which licenses apply to which parts of this
|
||||
package (but check the individual files to be sure!):
|
||||
|
||||
- liblzma is in the public domain.
|
||||
|
||||
- xz, xzdec, and lzmadec command line tools are in the public
|
||||
domain unless GNU getopt_long had to be compiled and linked
|
||||
in from the lib directory. The getopt_long code is under
|
||||
GNU LGPLv2.1+.
|
||||
|
||||
- The scripts to grep, diff, and view compressed files have been
|
||||
adapted from gzip. These scripts and their documentation are
|
||||
under GNU GPLv2+.
|
||||
|
||||
- All the documentation in the doc directory and most of the
|
||||
XZ Utils specific documentation files in other directories
|
||||
are in the public domain.
|
||||
|
||||
- Translated messages are in the public domain.
|
||||
|
||||
- The build system contains public domain files, and files that
|
||||
are under GNU GPLv2+ or GNU GPLv3+. None of these files end up
|
||||
in the binaries being built.
|
||||
|
||||
- Test files and test code in the tests directory, and debugging
|
||||
utilities in the debug directory are in the public domain.
|
||||
|
||||
- The extra directory may contain public domain files, and files
|
||||
that are under various free software licenses.
|
||||
|
||||
You can do whatever you want with the files that have been put into
|
||||
the public domain. If you find public domain legally problematic,
|
||||
take the previous sentence as a license grant. If you still find
|
||||
the lack of copyright legally problematic, you have too many
|
||||
lawyers.
|
||||
|
||||
As usual, this software is provided "as is", without any warranty.
|
||||
|
||||
If you copy significant amounts of public domain code from XZ Utils
|
||||
into your project, acknowledging this somewhere in your software is
|
||||
polite (especially if it is proprietary, non-free software), but
|
||||
naturally it is not legally required. Here is an example of a good
|
||||
notice to put into "about box" or into documentation:
|
||||
|
||||
This software includes code from XZ Utils <http://tukaani.org/xz/>.
|
||||
|
||||
The following license texts are included in the following files:
|
||||
- COPYING.LGPLv2.1: GNU Lesser General Public License version 2.1
|
||||
- COPYING.GPLv2: GNU General Public License version 2
|
||||
- COPYING.GPLv3: GNU General Public License version 3
|
||||
|
||||
Note that the toolchain (compiler, linker etc.) may add some code
|
||||
pieces that are copyrighted. Thus, it is possible that e.g. liblzma
|
||||
binary wouldn't actually be in the public domain in its entirety
|
||||
even though it contains no copyrighted code from the XZ Utils source
|
||||
package.
|
||||
|
||||
If you have questions, don't hesitate to ask the author(s) for more
|
||||
information.
|
134
wheels/dependency_licenses/LIBPNG.txt
Normal file
134
wheels/dependency_licenses/LIBPNG.txt
Normal file
|
@ -0,0 +1,134 @@
|
|||
COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
|
||||
=========================================
|
||||
|
||||
PNG Reference Library License version 2
|
||||
---------------------------------------
|
||||
|
||||
* Copyright (c) 1995-2022 The PNG Reference Library Authors.
|
||||
* Copyright (c) 2018-2022 Cosmin Truta.
|
||||
* Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
|
||||
* Copyright (c) 1996-1997 Andreas Dilger.
|
||||
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
|
||||
|
||||
The software is supplied "as is", without warranty of any kind,
|
||||
express or implied, including, without limitation, the warranties
|
||||
of merchantability, fitness for a particular purpose, title, and
|
||||
non-infringement. In no event shall the Copyright owners, or
|
||||
anyone distributing the software, be liable for any damages or
|
||||
other liability, whether in contract, tort or otherwise, arising
|
||||
from, out of, or in connection with the software, or the use or
|
||||
other dealings in the software, even if advised of the possibility
|
||||
of such damage.
|
||||
|
||||
Permission is hereby granted to use, copy, modify, and distribute
|
||||
this software, or portions hereof, for any purpose, without fee,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you
|
||||
must not claim that you wrote the original software. If you
|
||||
use this software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated, but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must
|
||||
not be misrepresented as being the original software.
|
||||
|
||||
3. This Copyright notice may not be removed or altered from any
|
||||
source or altered source distribution.
|
||||
|
||||
|
||||
PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are
|
||||
Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are
|
||||
derived from libpng-1.0.6, and are distributed according to the same
|
||||
disclaimer and license as libpng-1.0.6 with the following individuals
|
||||
added to the list of Contributing Authors:
|
||||
|
||||
Simon-Pierre Cadieux
|
||||
Eric S. Raymond
|
||||
Mans Rullgard
|
||||
Cosmin Truta
|
||||
Gilles Vollant
|
||||
James Yu
|
||||
Mandar Sahastrabuddhe
|
||||
Google Inc.
|
||||
Vadim Barkov
|
||||
|
||||
and with the following additions to the disclaimer:
|
||||
|
||||
There is no warranty against interference with your enjoyment of
|
||||
the library or against infringement. There is no warranty that our
|
||||
efforts or the library will fulfill any of your particular purposes
|
||||
or needs. This library is provided with all faults, and the entire
|
||||
risk of satisfactory quality, performance, accuracy, and effort is
|
||||
with the user.
|
||||
|
||||
Some files in the "contrib" directory and some configure-generated
|
||||
files that are distributed with libpng have other copyright owners, and
|
||||
are released under other open source licenses.
|
||||
|
||||
libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
|
||||
Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
|
||||
libpng-0.96, and are distributed according to the same disclaimer and
|
||||
license as libpng-0.96, with the following individuals added to the
|
||||
list of Contributing Authors:
|
||||
|
||||
Tom Lane
|
||||
Glenn Randers-Pehrson
|
||||
Willem van Schaik
|
||||
|
||||
libpng versions 0.89, June 1996, through 0.96, May 1997, are
|
||||
Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
|
||||
and are distributed according to the same disclaimer and license as
|
||||
libpng-0.88, with the following individuals added to the list of
|
||||
Contributing Authors:
|
||||
|
||||
John Bowler
|
||||
Kevin Bracey
|
||||
Sam Bushell
|
||||
Magnus Holmgren
|
||||
Greg Roelofs
|
||||
Tom Tanner
|
||||
|
||||
Some files in the "scripts" directory have other copyright owners,
|
||||
but are released under this license.
|
||||
|
||||
libpng versions 0.5, May 1995, through 0.88, January 1996, are
|
||||
Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
|
||||
|
||||
For the purposes of this copyright and license, "Contributing Authors"
|
||||
is defined as the following set of individuals:
|
||||
|
||||
Andreas Dilger
|
||||
Dave Martindale
|
||||
Guy Eric Schalnat
|
||||
Paul Schmidt
|
||||
Tim Wegner
|
||||
|
||||
The PNG Reference Library is supplied "AS IS". The Contributing
|
||||
Authors and Group 42, Inc. disclaim all warranties, expressed or
|
||||
implied, including, without limitation, the warranties of
|
||||
merchantability and of fitness for any purpose. The Contributing
|
||||
Authors and Group 42, Inc. assume no liability for direct, indirect,
|
||||
incidental, special, exemplary, or consequential damages, which may
|
||||
result from the use of the PNG Reference Library, even if advised of
|
||||
the possibility of such damage.
|
||||
|
||||
Permission is hereby granted to use, copy, modify, and distribute this
|
||||
source code, or portions hereof, for any purpose, without fee, subject
|
||||
to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented.
|
||||
|
||||
2. Altered versions must be plainly marked as such and must not
|
||||
be misrepresented as being the original source.
|
||||
|
||||
3. This Copyright notice may not be removed or altered from any
|
||||
source or altered source distribution.
|
||||
|
||||
The Contributing Authors and Group 42, Inc. specifically permit,
|
||||
without fee, and encourage the use of this source code as a component
|
||||
to supporting the PNG file format in commercial products. If you use
|
||||
this source code in a product, acknowledgment is not required but would
|
||||
be appreciated.
|
21
wheels/dependency_licenses/LIBTIFF.txt
Normal file
21
wheels/dependency_licenses/LIBTIFF.txt
Normal file
|
@ -0,0 +1,21 @@
|
|||
Copyright (c) 1988-1997 Sam Leffler
|
||||
Copyright (c) 1991-1997 Silicon Graphics, Inc.
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this software and
|
||||
its documentation for any purpose is hereby granted without fee, provided
|
||||
that (i) the above copyright notices and this permission notice appear in
|
||||
all copies of the software and related documentation, and (ii) the names of
|
||||
Sam Leffler and Silicon Graphics may not be used in any advertising or
|
||||
publicity relating to the software without the specific, prior written
|
||||
permission of Sam Leffler and Silicon Graphics.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
||||
ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
OF THIS SOFTWARE.
|
29
wheels/dependency_licenses/LIBWEBP.txt
Normal file
29
wheels/dependency_licenses/LIBWEBP.txt
Normal file
|
@ -0,0 +1,29 @@
|
|||
Copyright (c) 2010, Google Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
* Neither the name of Google nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
39
wheels/dependency_licenses/OPENJPEG.txt
Normal file
39
wheels/dependency_licenses/OPENJPEG.txt
Normal file
|
@ -0,0 +1,39 @@
|
|||
*
|
||||
* The copyright in this software is being made available under the 2-clauses
|
||||
* BSD License, included below. This software may be subject to other third
|
||||
* party and contributor rights, including patent rights, and no such rights
|
||||
* are granted under this license.
|
||||
*
|
||||
* Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
|
||||
* Copyright (c) 2002-2014, Professor Benoit Macq
|
||||
* Copyright (c) 2003-2014, Antonin Descampe
|
||||
* Copyright (c) 2003-2009, Francois-Olivier Devaux
|
||||
* Copyright (c) 2005, Herve Drolon, FreeImage Team
|
||||
* Copyright (c) 2002-2003, Yannick Verschueren
|
||||
* Copyright (c) 2001-2003, David Janssens
|
||||
* Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France
|
||||
* Copyright (c) 2012, CS Systemes d'Information, France
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
22
wheels/dependency_licenses/RAQM.txt
Normal file
22
wheels/dependency_licenses/RAQM.txt
Normal file
|
@ -0,0 +1,22 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright © 2015 Information Technology Authority (ITA) <foss@ita.gov.om>
|
||||
Copyright © 2016 Khaled Hosny <khaledhosny@eglug.org>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
21
wheels/dependency_licenses/XAU.txt
Normal file
21
wheels/dependency_licenses/XAU.txt
Normal file
|
@ -0,0 +1,21 @@
|
|||
Copyright 1988, 1993, 1994, 1998 The Open Group
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this software and its
|
||||
documentation for any purpose is hereby granted without fee, provided that
|
||||
the above copyright notice appear in all copies and that both that
|
||||
copyright notice and this permission notice appear in supporting
|
||||
documentation.
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of The Open Group shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from The Open Group.
|
30
wheels/dependency_licenses/XCB.txt
Normal file
30
wheels/dependency_licenses/XCB.txt
Normal file
|
@ -0,0 +1,30 @@
|
|||
Copyright (C) 2001-2006 Bart Massey, Jamey Sharp, and Josh Triplett.
|
||||
All Rights Reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute,
|
||||
sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall
|
||||
be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the names of the authors
|
||||
or their institutions shall not be used in advertising or
|
||||
otherwise to promote the sale, use or other dealings in this
|
||||
Software without prior written authorization from the
|
||||
authors.
|
23
wheels/dependency_licenses/XDMCP.txt
Normal file
23
wheels/dependency_licenses/XDMCP.txt
Normal file
|
@ -0,0 +1,23 @@
|
|||
Copyright 1989, 1998 The Open Group
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this software and its
|
||||
documentation for any purpose is hereby granted without fee, provided that
|
||||
the above copyright notice appear in all copies and that both that
|
||||
copyright notice and this permission notice appear in supporting
|
||||
documentation.
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of The Open Group shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from The Open Group.
|
||||
|
||||
Author: Keith Packard, MIT X Consortium
|
29
wheels/dependency_licenses/ZLIB.txt
Normal file
29
wheels/dependency_licenses/ZLIB.txt
Normal file
|
@ -0,0 +1,29 @@
|
|||
(C) 1995-2017 Jean-loup Gailly and Mark Adler
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Jean-loup Gailly Mark Adler
|
||||
jloup@gzip.org madler@alumni.caltech.edu
|
||||
|
||||
If you use the zlib library in a product, we would appreciate *not* receiving
|
||||
lengthy legal documents to sign. The sources are provided for free but without
|
||||
warranty of any kind. The library has been entirely written by Jean-loup
|
||||
Gailly and Mark Adler; it does not include third-party code.
|
||||
|
||||
If you redistribute modified sources, we would appreciate that you include in
|
||||
the file ChangeLog history information documenting your changes. Please read
|
||||
the FAQ for more information on the distribution of modified source versions.
|
1
wheels/multibuild
Submodule
1
wheels/multibuild
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 452dd2d1705f6b2375369a6570c415beb3163f70
|
|
@ -184,9 +184,9 @@ DEPS = {
|
|||
"libs": [r"output\release-static\{architecture}\lib\*.lib"],
|
||||
},
|
||||
"libtiff": {
|
||||
"url": "https://download.osgeo.org/libtiff/tiff-4.5.1.tar.gz",
|
||||
"filename": "tiff-4.5.1.tar.gz",
|
||||
"dir": "tiff-4.5.1",
|
||||
"url": "https://download.osgeo.org/libtiff/tiff-4.6.0.tar.gz",
|
||||
"filename": "tiff-4.6.0.tar.gz",
|
||||
"dir": "tiff-4.6.0",
|
||||
"license": "LICENSE.md",
|
||||
"patch": {
|
||||
r"libtiff\tif_lzma.c": {
|
||||
|
@ -228,12 +228,12 @@ DEPS = {
|
|||
"libs": [r"libpng16.lib"],
|
||||
},
|
||||
"brotli": {
|
||||
"url": "https://github.com/google/brotli/archive/refs/tags/v1.0.9.tar.gz",
|
||||
"filename": "brotli-1.0.9.tar.gz",
|
||||
"dir": "brotli-1.0.9",
|
||||
"url": "https://github.com/google/brotli/archive/refs/tags/v1.1.0.tar.gz",
|
||||
"filename": "brotli-1.1.0.tar.gz",
|
||||
"dir": "brotli-1.1.0",
|
||||
"license": "LICENSE",
|
||||
"build": [
|
||||
*cmds_cmake(("brotlicommon-static", "brotlidec-static")),
|
||||
*cmds_cmake(("brotlicommon", "brotlidec"), "-DBUILD_SHARED_LIBS:BOOL=OFF"),
|
||||
cmd_xcopy(r"c\include", "{inc_dir}"),
|
||||
],
|
||||
"libs": ["*.lib"],
|
||||
|
@ -254,7 +254,7 @@ DEPS = {
|
|||
"<UserDefines></UserDefines>": "<UserDefines>FT_CONFIG_OPTION_SYSTEM_ZLIB;FT_CONFIG_OPTION_USE_PNG;FT_CONFIG_OPTION_USE_HARFBUZZ;FT_CONFIG_OPTION_USE_BROTLI</UserDefines>", # noqa: E501
|
||||
"<UserIncludeDirectories></UserIncludeDirectories>": r"<UserIncludeDirectories>{dir_harfbuzz}\src;{inc_dir}</UserIncludeDirectories>", # noqa: E501
|
||||
"<UserLibraryDirectories></UserLibraryDirectories>": "<UserLibraryDirectories>{lib_dir}</UserLibraryDirectories>", # noqa: E501
|
||||
"<UserDependencies></UserDependencies>": "<UserDependencies>zlib.lib;libpng16.lib;brotlicommon-static.lib;brotlidec-static.lib</UserDependencies>", # noqa: E501
|
||||
"<UserDependencies></UserDependencies>": "<UserDependencies>zlib.lib;libpng16.lib;brotlicommon.lib;brotlidec.lib</UserDependencies>", # noqa: E501
|
||||
},
|
||||
r"src/autofit/afshaper.c": {
|
||||
# link against harfbuzz.lib
|
||||
|
@ -339,9 +339,9 @@ DEPS = {
|
|||
"libs": [r"imagequant.lib"],
|
||||
},
|
||||
"harfbuzz": {
|
||||
"url": "https://github.com/harfbuzz/harfbuzz/archive/8.2.0.zip",
|
||||
"filename": "harfbuzz-8.2.0.zip",
|
||||
"dir": "harfbuzz-8.2.0",
|
||||
"url": "https://github.com/harfbuzz/harfbuzz/archive/8.2.1.zip",
|
||||
"filename": "harfbuzz-8.2.1.zip",
|
||||
"dir": "harfbuzz-8.2.1",
|
||||
"license": "COPYING",
|
||||
"build": [
|
||||
*cmds_cmake(
|
||||
|
|
Loading…
Reference in New Issue
Block a user