Skip to content

Commit

Permalink
Enable Libheif Plugin System (#205)
Browse files Browse the repository at this point in the history
* DENABLE_PLUGIN_LOADING=ON
* CI runners: macos-11 -> macos-12

Signed-off-by: Alexander Piskun <[email protected]>

---------

Signed-off-by: Alexander Piskun <[email protected]>
  • Loading branch information
bigcat88 authored Feb 1, 2024
1 parent a45f845 commit 5859b29
Show file tree
Hide file tree
Showing 16 changed files with 157 additions and 31 deletions.
8 changes: 6 additions & 2 deletions .github/workflows/analysis-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ jobs:
run: python3 -c "import pillow_heif; print(pillow_heif.libheif_info())"

- name: Generate coverage report
run: coverage run -m pytest && coverage xml && coverage html
run: |
TEST_PLUGIN_LOAD="$(whereis libheif | awk '{print $2}')/plugins/libheif-x265.so" coverage run -m pytest
coverage xml && coverage html
- name: HTML coverage to artifacts
uses: actions/upload-artifact@v3
Expand Down Expand Up @@ -104,7 +106,9 @@ jobs:
run: python3 -c "import pillow_heif; print(pillow_heif.libheif_info())"

- name: Generate coverage report
run: coverage run -m pytest && coverage xml && coverage html
run: |
TEST_PLUGIN_LOAD="$(whereis libheif | awk '{print $2}')/plugins/libheif-x265.so" coverage run -m pytest
coverage xml && coverage html
- name: HTML coverage to artifacts
uses: actions/upload-artifact@v3
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/test-src-build-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ concurrency:
cancel-in-progress: true

jobs:
full_macos_11:
name: macOS:11-x86_64
runs-on: macos-11
full_macos_12:
name: macOS:12-x86_64
runs-on: macos-12
env:
TEST_DECODE_THREADS: 0 # This test fails on GitHub on macOS. We have such enabled test on Cirrus.
PH_FULL_ACTION: 1
Expand All @@ -52,9 +52,9 @@ jobs:
- name: Perform tests
run: python3 -m pytest

lite_macos_11:
name: macOS:11-x86_64(Pi-Heif)
runs-on: macos-11
lite_macos_12:
name: macOS:12-x86_64(Pi-Heif)
runs-on: macos-12
env:
TEST_DECODE_THREADS: 0
PH_LIGHT_ACTION: 1
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test-wheels-pi_heif.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ jobs:
cd .. && python3 -m pytest pillow_heif
macos-wheels:
name: macOS • 11 • ${{ matrix.python-version }}
runs-on: macos-11
name: macOS • 12 • ${{ matrix.python-version }}
runs-on: macos-12
strategy:
fail-fast: false
matrix:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test-wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ jobs:
run: cd .. && python3 -m pytest pillow_heif

macos-wheels:
name: macOS • 11 • ${{ matrix.python-version }}
runs-on: macos-11
name: macOS • 12 • ${{ matrix.python-version }}
runs-on: macos-12
strategy:
matrix:
python-version: ["pypy-3.8", "pypy-3.9", "pypy-3.10", "3.8", "3.9", "3.10", "3.11", "3.12"]
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/wheels-pi_heif.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ jobs:

wheels_macos:
name: macosx • x86_64
runs-on: macos-11
runs-on: macos-12

steps:
- uses: actions/checkout@v4
Expand All @@ -109,6 +109,7 @@ jobs:
env:
CIBW_ARCHS: "x86_64"
CIBW_ENVIRONMENT_MACOS: PH_LIGHT_ACTION=1 TEST_DECODE_THREADS=0
MACOSX_DEPLOYMENT_TARGET: "10.10"

- name: Checking built wheels
run: |
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/wheels-pillow_heif.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ jobs:

wheels_macos:
name: macosx • x86_64
runs-on: macos-11
runs-on: macos-12

steps:
- uses: actions/checkout@v4
Expand All @@ -100,6 +100,7 @@ jobs:
env:
CIBW_ARCHS: "x86_64"
CIBW_ENVIRONMENT_MACOS: PH_FULL_ACTION=1 TEST_DECODE_THREADS=0
MACOSX_DEPLOYMENT_TARGET: "10.10"

- name: Check built wheels
run: |
Expand Down
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
All notable changes to this project will be documented in this file.

## [0.15.0 - 2024-0x-xx]
## [0.15.0 - 2024-02-02]

### Added

- `libheif_info` function: added `encoders` and `decoders` keys to the result, for future libheif plugins support. #189
- `options.PREFERRED_ENCODER` - to use `encoder` different from the default one. #192
- `options.PREFERRED_DECODER` - to use `decoder` different from the default one. #193
- New `load_plugin` function. `ENABLE_PLUGIN_LOADING` option now is `ON` in the libheif configuration. #154

### Changed

Expand Down
25 changes: 23 additions & 2 deletions libheif/linux_build_libs.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,29 @@ def build_lib_linux(url: str, name: str):
cmake_args += ["-DCMAKE_BUILD_TYPE=Release"]
if name == "libheif":
cmake_args += (
"-DWITH_EXAMPLES=OFF -DWITH_RAV1E=OFF -DWITH_DAV1D=OFF -DWITH_SvtEnc=OFF"
" -DWITH_LIBSHARPYUV=OFF -DENABLE_PLUGIN_LOADING=OFF".split()
"-DWITH_LIBDE265=ON "
"-DWITH_LIBDE265_PLUGIN=OFF "
"-DWITH_X265=ON "
"-DWITH_X265_PLUGIN=OFF "
"-DWITH_AOM_DECODER=ON "
"-DWITH_AOM_DECODER_PLUGIN=OFF "
"-DWITH_AOM_ENCODER=ON "
"-DWITH_AOM_ENCODER_PLUGIN=OFF "
"-DWITH_RAV1E=OFF "
"-DWITH_RAV1E_PLUGIN=OFF "
"-DWITH_DAV1D=OFF "
"-DWITH_DAV1D_PLUGIN=OFF "
"-DWITH_SvtEnc=OFF "
"-DWITH_SvtEnc_PLUGIN=OFF "
"-DWITH_KVAZAAR=OFF "
"-DWITH_KVAZAAR_PLUGIN=OFF "
"-DWITH_JPEG_DECODER=OFF "
"-DWITH_JPEG_ENCODER=OFF "
"-DWITH_OpenJPEG_DECODER=OFF "
"-DWITH_OpenJPEG_ENCODER=OFF "
"-DENABLE_PLUGIN_LOADING=ON "
"-DWITH_LIBSHARPYUV=OFF "
"-DWITH_EXAMPLES=OFF".split()
)
_hide_build_process = False
if is_musllinux():
Expand Down
19 changes: 17 additions & 2 deletions libheif/macos/libheif.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,30 @@ class Libheif < Formula

def install
args = %W[
-DWITH_LIBDE265=ON
-DWITH_LIBDE265_PLUGIN=OFF
-DWITH_X265=ON
-DWITH_X265_PLUGIN=OFF
-DWITH_AOM_DECODER=ON
-DWITH_AOM_DECODER_PLUGIN=OFF
-DWITH_AOM_ENCODER=ON
-DWITH_AOM_ENCODER_PLUGIN=OFF
-DWITH_RAV1E=OFF
-DWITH_RAV1E_PLUGIN=OFF
-DWITH_DAV1D=OFF
-DWITH_DAV1D_PLUGIN=OFF
-DWITH_SvtEnc=OFF
-DWITH_LIBSHARPYUV=OFF
-DENABLE_PLUGIN_LOADING=OFF
-DWITH_SvtEnc_PLUGIN=OFF
-DWITH_KVAZAAR=OFF
-DWITH_KVAZAAR_PLUGIN=OFF
-DWITH_FFMPEG_DECODER=OFF
-DWITH_FFMPEG_DECODER_PLUGIN=OFF
-DWITH_JPEG_DECODER=OFF
-DWITH_JPEG_ENCODER=OFF
-DWITH_OpenJPEG_DECODER=OFF
-DWITH_OpenJPEG_ENCODER=OFF
-DENABLE_PLUGIN_LOADING=ON
-DWITH_LIBSHARPYUV=OFF
-DCMAKE_INSTALL_RPATH=#{rpath}
]
system "cmake", "-S", ".", "-B", "build", *args, *std_cmake_args
Expand Down
20 changes: 18 additions & 2 deletions libheif/windows/mingw-w64-libheif/PKGBUILD
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,31 @@ build() {
-DCMAKE_INSTALL_PREFIX=${MINGW_PREFIX} \
"${extra_config[@]}" \
-DBUILD_SHARED_LIBS=ON \
-DWITH_LIBDE265=ON \
-DWITH_LIBDE265_PLUGIN=OFF \
-DWITH_X265=ON \
-DWITH_X265_PLUGIN=OFF \
-DWITH_AOM_DECODER=ON \
-DWITH_AOM_DECODER_PLUGIN=OFF \
-DWITH_AOM_ENCODER=ON \
-DWITH_AOM_ENCODER_PLUGIN=OFF \
-DWITH_RAV1E=OFF \
-DWITH_RAV1E_PLUGIN=OFF \
-DWITH_DAV1D=OFF \
-DWITH_DAV1D_PLUGIN=OFF \
-DWITH_SvtEnc=OFF \
-DWITH_LIBSHARPYUV=OFF \
-DENABLE_PLUGIN_LOADING=OFF \
-DWITH_SvtEnc_PLUGIN=OFF \
-DWITH_KVAZAAR=OFF \
-DWITH_KVAZAAR_PLUGIN=OFF \
-DWITH_FFMPEG_DECODER=OFF \
-DWITH_FFMPEG_DECODER_PLUGIN=OFF \
-DWITH_JPEG_DECODER=OFF \
-DWITH_JPEG_ENCODER=OFF \
-DWITH_OpenJPEG_DECODER=OFF \
-DWITH_OpenJPEG_ENCODER=OFF \
-DENABLE_PLUGIN_LOADING=ON \
-DWITH_LIBSHARPYUV=OFF \
-DWITH_EXAMPLES=OFF \
-DX265_CFLAGS="-DX265_API_IMPORTS" \
../${_realname}-${pkgver}

Expand Down
22 changes: 18 additions & 4 deletions pi-heif/libheif/macos/libheif.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,31 @@ class Libheif < Formula

def install
args = %W[
-DWITH_LIBDE265=ON
-DWITH_LIBDE265_PLUGIN=OFF
-DWITH_X265=OFF
-DWITH_X265_PLUGIN=OFF
-DWITH_AOM_DECODER=OFF
-DWITH_AOM_DECODER_PLUGIN=OFF
-DWITH_AOM_ENCODER=OFF
-DWITH_AOM_ENCODER_PLUGIN=OFF
-DWITH_RAV1E=OFF
-DWITH_RAV1E_PLUGIN=OFF
-DWITH_DAV1D=OFF
-DWITH_DAV1D_PLUGIN=OFF
-DWITH_SvtEnc=OFF
-DWITH_AOM=OFF
-DWITH_X265=OFF
-DWITH_LIBSHARPYUV=OFF
-DENABLE_PLUGIN_LOADING=OFF
-DWITH_SvtEnc_PLUGIN=OFF
-DWITH_KVAZAAR=OFF
-DWITH_KVAZAAR_PLUGIN=OFF
-DWITH_FFMPEG_DECODER=OFF
-DWITH_FFMPEG_DECODER_PLUGIN=OFF
-DWITH_JPEG_DECODER=OFF
-DWITH_JPEG_ENCODER=OFF
-DWITH_OpenJPEG_DECODER=OFF
-DWITH_OpenJPEG_ENCODER=OFF
-DENABLE_PLUGIN_LOADING=ON
-DWITH_LIBSHARPYUV=OFF
-DWITH_EXAMPLES=OFF
-DCMAKE_INSTALL_RPATH=#{rpath}
]
system "cmake", "-S", ".", "-B", "build", *args, *std_cmake_args
Expand Down
22 changes: 18 additions & 4 deletions pi-heif/libheif/windows/mingw-w64-libheif/PKGBUILD
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,31 @@ build() {
-DCMAKE_INSTALL_PREFIX=${MINGW_PREFIX} \
"${extra_config[@]}" \
-DBUILD_SHARED_LIBS=ON \
-DWITH_LIBDE265=ON \
-DWITH_LIBDE265_PLUGIN=OFF \
-DWITH_X265=OFF \
-DWITH_X265_PLUGIN=OFF \
-DWITH_AOM_DECODER=OFF \
-DWITH_AOM_DECODER_PLUGIN=OFF \
-DWITH_AOM_ENCODER=OFF \
-DWITH_AOM_ENCODER_PLUGIN=OFF \
-DWITH_RAV1E=OFF \
-DWITH_RAV1E_PLUGIN=OFF \
-DWITH_DAV1D=OFF \
-DWITH_AOM=OFF \
-DWITH_X265=OFF \
-DWITH_DAV1D_PLUGIN=OFF \
-DWITH_SvtEnc=OFF \
-DWITH_LIBSHARPYUV=OFF \
-DENABLE_PLUGIN_LOADING=OFF \
-DWITH_SvtEnc_PLUGIN=OFF \
-DWITH_KVAZAAR=OFF \
-DWITH_KVAZAAR_PLUGIN=OFF \
-DWITH_FFMPEG_DECODER=OFF \
-DWITH_FFMPEG_DECODER_PLUGIN=OFF \
-DWITH_JPEG_DECODER=OFF \
-DWITH_JPEG_ENCODER=OFF \
-DWITH_OpenJPEG_DECODER=OFF \
-DWITH_OpenJPEG_ENCODER=OFF \
-DENABLE_PLUGIN_LOADING=ON \
-DWITH_LIBSHARPYUV=OFF \
-DWITH_EXAMPLES=OFF \
../${_realname}-${pkgver}

${MINGW_PREFIX}/bin/cmake --build .
Expand Down
2 changes: 1 addition & 1 deletion pillow_heif/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@
open_heif,
read_heif,
)
from .misc import get_file_mimetype, set_orientation
from .misc import get_file_mimetype, load_plugin, set_orientation
27 changes: 27 additions & 0 deletions pillow_heif/_pillow_heif.c
Original file line number Diff line number Diff line change
Expand Up @@ -1328,12 +1328,39 @@ static PyObject* _get_lib_info(PyObject* self) {
return lib_info_dict;
}

static PyObject* _load_plugins(PyObject* self, PyObject* args) {
const char *plugins_directory;
if (!PyArg_ParseTuple(args, "s", &plugins_directory))
return NULL;

struct heif_error error = heif_load_plugins(plugins_directory, NULL, NULL, 0);
if (check_error(error)) {
return NULL;
}
RETURN_NONE
}

static PyObject* _load_plugin(PyObject* self, PyObject* args) {
const char *plugin_path;
if (!PyArg_ParseTuple(args, "s", &plugin_path))
return NULL;

const struct heif_plugin_info* info = NULL;
struct heif_error error = heif_load_plugin(plugin_path, &info);
if (check_error(error)) {
return NULL;
}
RETURN_NONE
}

/* =========== Module =========== */

static PyMethodDef heifMethods[] = {
{"CtxWrite", (PyCFunction)_CtxWrite, METH_VARARGS},
{"load_file", (PyCFunction)_load_file, METH_VARARGS},
{"get_lib_info", (PyCFunction)_get_lib_info, METH_NOARGS},
{"load_plugins", (PyCFunction)_load_plugins, METH_VARARGS},
{"load_plugin", (PyCFunction)_load_plugin, METH_VARARGS},
{NULL, NULL}
};

Expand Down
7 changes: 6 additions & 1 deletion pillow_heif/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from math import ceil
from pathlib import Path
from struct import pack, unpack
from typing import List, Optional
from typing import List, Optional, Union

from PIL import Image

Expand Down Expand Up @@ -446,3 +446,8 @@ def size_mode(self):
def bit_depth(self) -> int:
"""Return bit-depth based on image mode."""
return MODE_INFO[self.mode][1]


def load_plugin(plugin_path: Union[str, Path]) -> None:
"""Load specified LibHeif plugin."""
_pillow_heif.load_plugin(plugin_path)
7 changes: 7 additions & 0 deletions tests/basic_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,10 @@ def test_light_build():
expected_version = os.getenv("EXP_PH_LIBHEIF_VERSION", "1.17.6")
if expected_version:
assert info["libheif"] == expected_version


@pytest.mark.skipif(not os.getenv("TEST_PLUGIN_LOAD"), reason="Only when plugins present")
def test_load_plugin():
pillow_heif.load_plugin(os.environ["TEST_PLUGIN_LOAD"])
with pytest.raises(RuntimeError):
pillow_heif.load_plugin("invalid path")

0 comments on commit 5859b29

Please sign in to comment.