Skip to content

Commit

Permalink
chore: Update dependencies, including libavif to 1.0.1 (#27)
Browse files Browse the repository at this point in the history
* chore: Update dependencies, including libavif to 1.0.1

* feat: Use new libavif quality encoder option

This replaces the (now deprecated) qmin and qmax options in libavif 1.x

* Update windows libavif dependency

* re-add python 2.7 test workflow

* Use patch for static local builds
  • Loading branch information
fdintino authored Sep 24, 2023
1 parent ff739ec commit 382119a
Show file tree
Hide file tree
Showing 13 changed files with 283 additions and 154 deletions.
14 changes: 12 additions & 2 deletions .github/workflows/linux-install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,23 @@

set -eo pipefail

aptget()
{
if [ $(id -u) == 0 ]; then
apt-get "$@"
else
sudo apt-get "$@"
fi
}

aptget_update()
{
if [ ! -z $1 ]; then
echo ""
echo "Retrying apt-get update..."
echo ""
fi
output=`sudo apt-get update 2>&1`
output=`aptget update 2>&1`
echo "$output"
if [[ $output == *[WE]:\ * ]]; then
return 1
Expand All @@ -19,11 +28,12 @@ aptget_update || aptget_update retry || aptget_update retry

set -e

sudo apt-get -qq install zlib1g-dev libpng-dev libjpeg-dev \
aptget -qq install zlib1g-dev libpng-dev libjpeg-dev sudo \
libxml2-dev libffi-dev libxslt-dev cmake ninja-build nasm

if [ "$GHA_PYTHON_VERSION" == "2.7" ]; then
python2 -m pip install tox tox-gh-actions
aptget install -y python3-pip
else
python3 -m pip install 'tox<4' tox-gh-actions
fi
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/macos-install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

set -e

brew install dav1d aom rav1e cmake
brew reinstall cmake
brew install dav1d aom rav1e

if [ "$GHA_PYTHON_VERSION" == "2.7" ]; then
python2 -m pip install -U tox tox-gh-actions
Expand Down
101 changes: 48 additions & 53 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ jobs:
"3.7",
"2.7",
]
libavif-version: [ "0.11.0" ]
include:
- python-version: "3.9"
os: "ubuntu-20.04"
libavif-version: "1.0.1"
- python-version: "3.7"
PYTHONOPTIMIZE: 1
- python-version: "3.8"
Expand All @@ -30,17 +34,23 @@ jobs:
codecov-flag: GHA_Ubuntu
- os: macos-11
codecov-flag: GHA_macOS
exclude:
- python-version: "2.7"
os: "macos-11"

runs-on: ${{ matrix.os }}
name: ${{ matrix.os }} Python ${{ matrix.python-version }}
name: ${{ matrix.os }} Python ${{ matrix.python-version }} (libavif ${{ matrix.libavif-version }})
container:
image: ${{ matrix.python-version == '2.7' && 'python:2.7-buster' || null }}

env:
LIBAVIF_VERSION: 0.11.0
LIBAVIF_VERSION: ${{ matrix.libavif-version }}

steps:
- uses: actions/checkout@v3

- name: Set up Python ${{ matrix.python-version }}
if: matrix.python-version != '2.7'
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
Expand Down Expand Up @@ -75,7 +85,6 @@ jobs:
if: failure()
run: |
mkdir -p tests/errors
shell: pwsh
- name: Upload errors
uses: actions/upload-artifact@v3
Expand All @@ -90,83 +99,69 @@ jobs:
CODECOV_NAME: ${{ matrix.os }} Python ${{ matrix.python-version }}

- name: Upload coverage
run: tox -e codecov -- -F ${{ matrix.codecov-flag }}
env:
CODECOV_NAME: ${{ matrix.os }} Python ${{ matrix.python-version }}
uses: codecov/codecov-action@v3
with:
file: ./coverage.xml

msys:
runs-on: windows-2019

strategy:
fail-fast: false
matrix:
msystem: [ "mingw32", "mingw64" ]
python-version: ["2", "3"]
include:
- msystem: "mingw32"
name: "MSYS2 MinGW 32-bit"
package: "mingw-w64-i686"
env: i686
- msystem: "mingw64"
name: "MSYS2 MinGW 64-bit"
package: "mingw-w64-x86_64"
env: x86_64
exclude:
- msystem: "mingw32"
python-version: "2"
runs-on: windows-latest

name: ${{ matrix.name }} python ${{ matrix.python-version }}
name: MinGW

defaults:
run:
shell: msys2 {0}
shell: bash.exe --login -eo pipefail "{0}"

env:
MSYSTEM: ${{ matrix.msystem }}
MSYSTEM: MINGW64
CHERE_INVOKING: 1
SETUPTOOLS_USE_DISTUTILS: stdlib

timeout-minutes: 30

steps:
- uses: actions/checkout@v3

- uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.msystem }}
update: true
install: >-
base-devel
git
${{ matrix.package }}-toolchain
${{ matrix.package }}-python${{ matrix.python-version }}-pip
${{ matrix.package }}-python${{ matrix.python-version }}-setuptools
${{ matrix.package }}-libjpeg-turbo
${{ matrix.package }}-libtiff
${{ matrix.package }}-libpng
${{ matrix.package }}-openjpeg2
${{ matrix.package }}-libavif
- name: Set up shell
run: echo "C:\msys64\usr\bin\" >> $env:GITHUB_PATH
shell: pwsh

- name: Install dependencies
run: |
pacman -S --noconfirm \
base-devel \
git \
mingw-w64-x86_64-gcc \
mingw-w64-x86_64-toolchain \
mingw-w64-x86_64-python3-pip \
mingw-w64-x86_64-python3-setuptools \
mingw-w64-x86_64-libjpeg-turbo \
mingw-w64-x86_64-libtiff \
mingw-w64-x86_64-libpng \
mingw-w64-x86_64-openjpeg2 \
mingw-w64-x86_64-zlib \
mingw-w64-x86_64-libavif
- name: Install Dependencies
run: |
python${{ matrix.python-version }} -m pip install pytest pytest-cov pillow mock
python3 -m pip install pytest pytest-cov pillow mock
- name: Build pillow-avif-plugin
run: CFLAGS="-coverage" python${{ matrix.python-version }} setup.py build_ext install
run: CFLAGS="-coverage" python3 -m pip install .

- name: Test pillow-avif-plugin
run: |
python${{ matrix.python-version }} -m pytest -vx --cov pillow_avif --cov tests --cov-report term --cov-report xml tests
python3 -m pytest -vx --cov pillow_avif --cov tests --cov-report term --cov-report xml tests
- name: Upload coverage
run: |
python${{ matrix.python-version }} -m pip install codecov
bash <(curl -s https://codecov.io/bash) -F GHA_Windows
env:
CODECOV_NAME: ${{ matrix.name }}

uses: codecov/codecov-action@v3
with:
file: ./coverage.xml
flags: GHA_Windows
name: "MSYS2 MinGW"
success:
needs: [build, msys]
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
name: Test Successful
steps:
- name: Success
Expand Down
23 changes: 3 additions & 20 deletions .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,19 @@ jobs:
matrix:
os: [ "ubuntu-20.04", "macos-11" ]
python: [ "2.7", "3.7", "3.8", "3.9", "3.10", "3.11" ]
platform: [ "x86_64", "i686" ]
manylinux-version: [ "1", "2010" ]
platform: [ "x86_64" ]
manylinux-version: [ "2010" ]
macos-target: [ "10.10" ]
mb-ml-libc: [ "manylinux" ]
multibuild-sha: [ "34e970c4bc448b73af0127615fc4583b4f247369" ]
exclude:
- os: "macos-11"
platform: "i686"
- os: "macos-11"
manylinux-version: "1"
- python: "3.10"
manylinux-version: "1"
- python: "3.11"
manylinux-version: "1"
- python: "3.11"
manylinux-version: "2010"
- python: "3.11"
multibuild-sha: "34e970c4bc448b73af0127615fc4583b4f247369"
include:
- os: "macos-11"
os-name: "osx"
- os: "ubuntu-20.04"
manylinux-version: "1"
os-name: "manylinux1"
- os: "ubuntu-20.04"
manylinux-version: "2010"
os-name: "manylinux2010"
Expand Down Expand Up @@ -136,12 +125,6 @@ jobs:
os-name: "manylinux2014"
manylinux-version: "2014"
multibuild-sha: "bb32cfec4f755cb146332a0490abcf3187ce61d1"
- python: "3.11"
platform: "i686"
os: "ubuntu-20.04"
os-name: "manylinux2014"
manylinux-version: "2014"
multibuild-sha: "bb32cfec4f755cb146332a0490abcf3187ce61d1"
env:
BUILD_COMMIT: HEAD
PLAT: ${{ matrix.platform }}
Expand Down Expand Up @@ -222,7 +205,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["2.7", "3.7", "3.8", "3.9", "3.10", "3.11"]
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
architecture: ["x64"]
include:
- architecture: "x64"
Expand Down
6 changes: 6 additions & 0 deletions depends/install_libavif.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ else
PREFIX=/usr
fi

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"

PKGCONFIG=${PKGCONFIG:-pkg-config}

export CFLAGS="-fPIC -O3 $CFLAGS"
Expand All @@ -26,6 +28,10 @@ curl -sLo - \
pushd libavif-$LIBAVIF_VERSION
echo "::endgroup::"

if [ "$LIBAVIF_VERSION" == "1.0.1" ]; then
patch -p1 < "${SCRIPT_DIR}/../wheelbuild/libavif-1.0.1-local-static.patch"
fi

HAS_DECODER=0
HAS_ENCODER=0

Expand Down
3 changes: 2 additions & 1 deletion src/pillow_avif/AvifImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ def _save(im, fp, filename, save_all=False):
# - qmax is 0 for quality=100, then qmax increases linearly relative to
# quality decreasing, until it flattens out at quality=37.
quality = info.get("quality", 75)
if not isinstance(quality, int):
if not isinstance(quality, int) or quality < 0 or quality > 100:
raise ValueError("Invalid quality setting")
qmin = max(0, min(64 - quality, 63))
qmax = max(0, min(100 - quality, 63))
Expand Down Expand Up @@ -186,6 +186,7 @@ def _save(im, fp, filename, save_all=False):
subsampling,
qmin,
qmax,
quality,
speed,
codec,
range_,
Expand Down
10 changes: 9 additions & 1 deletion src/pillow_avif/_avif.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ typedef struct {
avifPixelFormat subsampling;
int qmin;
int qmax;
int quality;
int speed;
avifCodecChoice codec;
avifRange range;
Expand Down Expand Up @@ -205,6 +206,7 @@ AvifEncoderNew(PyObject *self_, PyObject *args) {
char *subsampling = "4:2:0";
int qmin = AVIF_QUANTIZER_BEST_QUALITY; // =0
int qmax = 10; // "High Quality", but not lossless
int quality = 75;
int speed = 8;
PyObject *icc_bytes;
PyObject *exif_bytes;
Expand All @@ -221,12 +223,13 @@ AvifEncoderNew(PyObject *self_, PyObject *args) {

if (!PyArg_ParseTuple(
args,
"IIsiiissiiOOSSSO",
"IIsiiiissiiOOSSSO",
&width,
&height,
&subsampling,
&qmin,
&qmax,
&quality,
&speed,
&codec,
&range,
Expand Down Expand Up @@ -256,6 +259,7 @@ AvifEncoderNew(PyObject *self_, PyObject *args) {

enc_options.qmin = normalize_quantize_value(qmin);
enc_options.qmax = normalize_quantize_value(qmax);
enc_options.quality = quality;

if (speed < AVIF_SPEED_SLOWEST) {
speed = AVIF_SPEED_SLOWEST;
Expand Down Expand Up @@ -321,8 +325,12 @@ AvifEncoderNew(PyObject *self_, PyObject *args) {
}

encoder->maxThreads = max_threads;
#if AVIF_VERSION >= 1000000
encoder->quality = enc_options.quality;
#else
encoder->minQuantizer = enc_options.qmin;
encoder->maxQuantizer = enc_options.qmax;
#endif
encoder->codecChoice = enc_options.codec;
encoder->speed = enc_options.speed;
encoder->timescale = (uint64_t)1000;
Expand Down
11 changes: 6 additions & 5 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ envlist = py{27,37,38,39,310,py37}
minversion = 1.9

[gh-actions]
problem_matcher = False
python =
2.7: py27
3.7: py37
Expand All @@ -29,10 +30,10 @@ commands =
{envpython} setup.py clean
{envpython} setup.py build_ext --build-lib {envdir}/src --build-temp {envdir} develop
{envpython} -m pytest -W always {posargs: -vv --cov pillow_avif --cov tests --cov-report term}
- gcovr -r {toxinidir} --object-directory {envdir} -k
{envpython} -c "import os; os.path.exists('{toxworkdir}/coverage') or os.makedirs('{toxworkdir}/coverage')"
- gcovr -r {toxinidir} --object-directory {envdir} -k --xml \
-o {toxworkdir}/coverage/gcov_coverage.{envname}.xml
- gcovr -r {toxinidir} --object-directory {envdir} -k \
--gcov-ignore-errors=no_working_dir_found \
-o {toxworkdir}/coverage/.gcov_coverage.{envname}
deps =
gcovr
pytest
Expand All @@ -50,7 +51,7 @@ changedir = {toxworkdir}/coverage
commands =
coverage combine
coverage report
coverage xml
coverage xml -o {toxinidir}/coverage.xml

[testenv:codecov]
skip_install = true
Expand All @@ -59,4 +60,4 @@ depends = coverage-report
passenv = CODECOV_TOKEN
changedir = {toxinidir}
commands =
codecov -X gcov --file {toxworkdir}/coverage/*.xml {posargs}
codecov -X gcov --file {toxinidir}/coverage.xml {posargs}
Loading

0 comments on commit 382119a

Please sign in to comment.