pylibheif 1.21.2__cp312-cp312-macosx_14_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pylibheif might be problematic. Click here for more details.
- include/libheif/heif.h +41 -0
- include/libheif/heif_aux_images.h +182 -0
- include/libheif/heif_brands.h +376 -0
- include/libheif/heif_color.h +363 -0
- include/libheif/heif_context.h +329 -0
- include/libheif/heif_cxx.h +1390 -0
- include/libheif/heif_decoding.h +172 -0
- include/libheif/heif_encoding.h +395 -0
- include/libheif/heif_entity_groups.h +60 -0
- include/libheif/heif_error.h +304 -0
- include/libheif/heif_image.h +355 -0
- include/libheif/heif_image_handle.h +129 -0
- include/libheif/heif_items.h +260 -0
- include/libheif/heif_library.h +219 -0
- include/libheif/heif_metadata.h +136 -0
- include/libheif/heif_plugin.h +378 -0
- include/libheif/heif_properties.h +235 -0
- include/libheif/heif_regions.h +868 -0
- include/libheif/heif_security.h +107 -0
- include/libheif/heif_sequences.h +644 -0
- include/libheif/heif_tai_timestamps.h +202 -0
- include/libheif/heif_text.h +161 -0
- include/libheif/heif_tiling.h +137 -0
- include/libheif/heif_uncompressed.h +109 -0
- include/libheif/heif_version.h +38 -0
- lib/cmake/libheif/libheif-config-release.cmake +19 -0
- lib/cmake/libheif/libheif-config-version.cmake +83 -0
- lib/cmake/libheif/libheif-config.cmake +108 -0
- lib/libheif.a +0 -0
- lib/pkgconfig/libheif.pc +15 -0
- pylibheif-1.21.2.dist-info/METADATA +409 -0
- pylibheif-1.21.2.dist-info/RECORD +41 -0
- pylibheif-1.21.2.dist-info/WHEEL +5 -0
- pylibheif-1.21.2.dist-info/licenses/LICENSE +165 -0
- pylibheif.cpython-312-darwin.so +0 -0
- pylibheif.dylibs/libaom.3.13.1.dylib +0 -0
- pylibheif.dylibs/libdav1d.7.dylib +0 -0
- pylibheif.dylibs/libde265.0.dylib +0 -0
- pylibheif.dylibs/libopenjp2.2.5.4.dylib +0 -0
- pylibheif.dylibs/libvmaf.3.dylib +0 -0
- pylibheif.dylibs/libx265.215.dylib +0 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# This is a basic version file for the Config-mode of find_package().
|
|
2
|
+
# It is used by write_basic_package_version_file() as input file for configure_file()
|
|
3
|
+
# to create a version-file which can be installed along a config.cmake file.
|
|
4
|
+
#
|
|
5
|
+
# The created file sets PACKAGE_VERSION_EXACT if the current version string and
|
|
6
|
+
# the requested version string are exactly the same and it sets
|
|
7
|
+
# PACKAGE_VERSION_COMPATIBLE if the current version is equal to the requested version.
|
|
8
|
+
# The tweak version component is ignored.
|
|
9
|
+
# The variable CVF_VERSION must be set before calling configure_file().
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
if (PACKAGE_FIND_VERSION_RANGE)
|
|
13
|
+
message(AUTHOR_WARNING
|
|
14
|
+
"`find_package()` specify a version range but the version strategy "
|
|
15
|
+
"(ExactVersion) of the module `${PACKAGE_FIND_NAME}` is incompatible "
|
|
16
|
+
"with this request. Only the lower endpoint of the range will be used.")
|
|
17
|
+
endif()
|
|
18
|
+
|
|
19
|
+
set(PACKAGE_VERSION "1.21.2")
|
|
20
|
+
|
|
21
|
+
if("1.21.2" MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)") # strip the tweak version
|
|
22
|
+
set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}")
|
|
23
|
+
set(CVF_VERSION_MINOR "${CMAKE_MATCH_2}")
|
|
24
|
+
set(CVF_VERSION_PATCH "${CMAKE_MATCH_3}")
|
|
25
|
+
|
|
26
|
+
if(NOT CVF_VERSION_MAJOR VERSION_EQUAL 0)
|
|
27
|
+
string(REGEX REPLACE "^0+" "" CVF_VERSION_MAJOR "${CVF_VERSION_MAJOR}")
|
|
28
|
+
endif()
|
|
29
|
+
if(NOT CVF_VERSION_MINOR VERSION_EQUAL 0)
|
|
30
|
+
string(REGEX REPLACE "^0+" "" CVF_VERSION_MINOR "${CVF_VERSION_MINOR}")
|
|
31
|
+
endif()
|
|
32
|
+
if(NOT CVF_VERSION_PATCH VERSION_EQUAL 0)
|
|
33
|
+
string(REGEX REPLACE "^0+" "" CVF_VERSION_PATCH "${CVF_VERSION_PATCH}")
|
|
34
|
+
endif()
|
|
35
|
+
|
|
36
|
+
set(CVF_VERSION_NO_TWEAK "${CVF_VERSION_MAJOR}.${CVF_VERSION_MINOR}.${CVF_VERSION_PATCH}")
|
|
37
|
+
else()
|
|
38
|
+
set(CVF_VERSION_NO_TWEAK "1.21.2")
|
|
39
|
+
endif()
|
|
40
|
+
|
|
41
|
+
if(PACKAGE_FIND_VERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)") # strip the tweak version
|
|
42
|
+
set(REQUESTED_VERSION_MAJOR "${CMAKE_MATCH_1}")
|
|
43
|
+
set(REQUESTED_VERSION_MINOR "${CMAKE_MATCH_2}")
|
|
44
|
+
set(REQUESTED_VERSION_PATCH "${CMAKE_MATCH_3}")
|
|
45
|
+
|
|
46
|
+
if(NOT REQUESTED_VERSION_MAJOR VERSION_EQUAL 0)
|
|
47
|
+
string(REGEX REPLACE "^0+" "" REQUESTED_VERSION_MAJOR "${REQUESTED_VERSION_MAJOR}")
|
|
48
|
+
endif()
|
|
49
|
+
if(NOT REQUESTED_VERSION_MINOR VERSION_EQUAL 0)
|
|
50
|
+
string(REGEX REPLACE "^0+" "" REQUESTED_VERSION_MINOR "${REQUESTED_VERSION_MINOR}")
|
|
51
|
+
endif()
|
|
52
|
+
if(NOT REQUESTED_VERSION_PATCH VERSION_EQUAL 0)
|
|
53
|
+
string(REGEX REPLACE "^0+" "" REQUESTED_VERSION_PATCH "${REQUESTED_VERSION_PATCH}")
|
|
54
|
+
endif()
|
|
55
|
+
|
|
56
|
+
set(REQUESTED_VERSION_NO_TWEAK
|
|
57
|
+
"${REQUESTED_VERSION_MAJOR}.${REQUESTED_VERSION_MINOR}.${REQUESTED_VERSION_PATCH}")
|
|
58
|
+
else()
|
|
59
|
+
set(REQUESTED_VERSION_NO_TWEAK "${PACKAGE_FIND_VERSION}")
|
|
60
|
+
endif()
|
|
61
|
+
|
|
62
|
+
if(REQUESTED_VERSION_NO_TWEAK STREQUAL CVF_VERSION_NO_TWEAK)
|
|
63
|
+
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
|
64
|
+
else()
|
|
65
|
+
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
|
66
|
+
endif()
|
|
67
|
+
|
|
68
|
+
if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)
|
|
69
|
+
set(PACKAGE_VERSION_EXACT TRUE)
|
|
70
|
+
endif()
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it:
|
|
74
|
+
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "")
|
|
75
|
+
return()
|
|
76
|
+
endif()
|
|
77
|
+
|
|
78
|
+
# check that the installed version has the same 32/64bit-ness as the one which is currently searching:
|
|
79
|
+
if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "8")
|
|
80
|
+
math(EXPR installedBits "8 * 8")
|
|
81
|
+
set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)")
|
|
82
|
+
set(PACKAGE_VERSION_UNSUITABLE TRUE)
|
|
83
|
+
endif()
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Generated by CMake
|
|
2
|
+
|
|
3
|
+
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8)
|
|
4
|
+
message(FATAL_ERROR "CMake >= 2.8.12 required")
|
|
5
|
+
endif()
|
|
6
|
+
if(CMAKE_VERSION VERSION_LESS "2.8.12")
|
|
7
|
+
message(FATAL_ERROR "CMake >= 2.8.12 required")
|
|
8
|
+
endif()
|
|
9
|
+
cmake_policy(PUSH)
|
|
10
|
+
cmake_policy(VERSION 2.8.12...4.0)
|
|
11
|
+
#----------------------------------------------------------------
|
|
12
|
+
# Generated CMake target import file.
|
|
13
|
+
#----------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
# Commands may need to know the format version.
|
|
16
|
+
set(CMAKE_IMPORT_FILE_VERSION 1)
|
|
17
|
+
|
|
18
|
+
# Protect against multiple inclusion, which would fail when already imported targets are added once more.
|
|
19
|
+
set(_cmake_targets_defined "")
|
|
20
|
+
set(_cmake_targets_not_defined "")
|
|
21
|
+
set(_cmake_expected_targets "")
|
|
22
|
+
foreach(_cmake_expected_target IN ITEMS heif)
|
|
23
|
+
list(APPEND _cmake_expected_targets "${_cmake_expected_target}")
|
|
24
|
+
if(TARGET "${_cmake_expected_target}")
|
|
25
|
+
list(APPEND _cmake_targets_defined "${_cmake_expected_target}")
|
|
26
|
+
else()
|
|
27
|
+
list(APPEND _cmake_targets_not_defined "${_cmake_expected_target}")
|
|
28
|
+
endif()
|
|
29
|
+
endforeach()
|
|
30
|
+
unset(_cmake_expected_target)
|
|
31
|
+
if(_cmake_targets_defined STREQUAL _cmake_expected_targets)
|
|
32
|
+
unset(_cmake_targets_defined)
|
|
33
|
+
unset(_cmake_targets_not_defined)
|
|
34
|
+
unset(_cmake_expected_targets)
|
|
35
|
+
unset(CMAKE_IMPORT_FILE_VERSION)
|
|
36
|
+
cmake_policy(POP)
|
|
37
|
+
return()
|
|
38
|
+
endif()
|
|
39
|
+
if(NOT _cmake_targets_defined STREQUAL "")
|
|
40
|
+
string(REPLACE ";" ", " _cmake_targets_defined_text "${_cmake_targets_defined}")
|
|
41
|
+
string(REPLACE ";" ", " _cmake_targets_not_defined_text "${_cmake_targets_not_defined}")
|
|
42
|
+
message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_cmake_targets_defined_text}\nTargets not yet defined: ${_cmake_targets_not_defined_text}\n")
|
|
43
|
+
endif()
|
|
44
|
+
unset(_cmake_targets_defined)
|
|
45
|
+
unset(_cmake_targets_not_defined)
|
|
46
|
+
unset(_cmake_expected_targets)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# Compute the installation prefix relative to this file.
|
|
50
|
+
get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
|
51
|
+
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
|
|
52
|
+
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
|
|
53
|
+
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
|
|
54
|
+
if(_IMPORT_PREFIX STREQUAL "/")
|
|
55
|
+
set(_IMPORT_PREFIX "")
|
|
56
|
+
endif()
|
|
57
|
+
|
|
58
|
+
# Create imported target heif
|
|
59
|
+
add_library(heif STATIC IMPORTED)
|
|
60
|
+
|
|
61
|
+
set_target_properties(heif PROPERTIES
|
|
62
|
+
INTERFACE_COMPILE_DEFINITIONS "LIBHEIF_EXPORTS;HAVE_VISIBILITY"
|
|
63
|
+
INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"
|
|
64
|
+
INTERFACE_LINK_LIBRARIES "/opt/homebrew/Cellar/x265/4.1/lib/libx265.dylib;/opt/homebrew/Cellar/libde265/1.0.16/lib/libde265.dylib;/opt/homebrew/Cellar/dav1d/1.5.3/lib/libdav1d.dylib;\$<LINK_ONLY:AOM::aom>;\$<LINK_ONLY:AOM::aom>;\$<LINK_ONLY:openjp2>;\$<LINK_ONLY:openjp2>"
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
# Load information for each installed configuration.
|
|
68
|
+
file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/libheif-config-*.cmake")
|
|
69
|
+
foreach(_cmake_config_file IN LISTS _cmake_config_files)
|
|
70
|
+
include("${_cmake_config_file}")
|
|
71
|
+
endforeach()
|
|
72
|
+
unset(_cmake_config_file)
|
|
73
|
+
unset(_cmake_config_files)
|
|
74
|
+
|
|
75
|
+
# Cleanup temporary variables.
|
|
76
|
+
set(_IMPORT_PREFIX)
|
|
77
|
+
|
|
78
|
+
# Loop over all imported files and verify that they actually exist
|
|
79
|
+
foreach(_cmake_target IN LISTS _cmake_import_check_targets)
|
|
80
|
+
if(CMAKE_VERSION VERSION_LESS "3.28"
|
|
81
|
+
OR NOT DEFINED _cmake_import_check_xcframework_for_${_cmake_target}
|
|
82
|
+
OR NOT IS_DIRECTORY "${_cmake_import_check_xcframework_for_${_cmake_target}}")
|
|
83
|
+
foreach(_cmake_file IN LISTS "_cmake_import_check_files_for_${_cmake_target}")
|
|
84
|
+
if(NOT EXISTS "${_cmake_file}")
|
|
85
|
+
message(FATAL_ERROR "The imported target \"${_cmake_target}\" references the file
|
|
86
|
+
\"${_cmake_file}\"
|
|
87
|
+
but this file does not exist. Possible reasons include:
|
|
88
|
+
* The file was deleted, renamed, or moved to another location.
|
|
89
|
+
* An install or uninstall procedure did not complete successfully.
|
|
90
|
+
* The installation package was faulty and contained
|
|
91
|
+
\"${CMAKE_CURRENT_LIST_FILE}\"
|
|
92
|
+
but not all the files it references.
|
|
93
|
+
")
|
|
94
|
+
endif()
|
|
95
|
+
endforeach()
|
|
96
|
+
endif()
|
|
97
|
+
unset(_cmake_file)
|
|
98
|
+
unset("_cmake_import_check_files_for_${_cmake_target}")
|
|
99
|
+
endforeach()
|
|
100
|
+
unset(_cmake_target)
|
|
101
|
+
unset(_cmake_import_check_targets)
|
|
102
|
+
|
|
103
|
+
# This file does not depend on other imported targets which have
|
|
104
|
+
# been exported from the same project but in a separate export set.
|
|
105
|
+
|
|
106
|
+
# Commands beyond this point should not need to know the version.
|
|
107
|
+
set(CMAKE_IMPORT_FILE_VERSION)
|
|
108
|
+
cmake_policy(POP)
|
lib/libheif.a
ADDED
|
Binary file
|
lib/pkgconfig/libheif.pc
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
prefix=/var/folders/xx/pgt1mtfn3xx3hdys7czt35bh0000gn/T/tmpcsjdgqu7/wheel/platlib
|
|
2
|
+
exec_prefix=${prefix}
|
|
3
|
+
libdir=${exec_prefix}/lib
|
|
4
|
+
includedir=${prefix}/include
|
|
5
|
+
|
|
6
|
+
Name: libheif
|
|
7
|
+
Description: HEIF image codec.
|
|
8
|
+
URL: https://github.com/strukturag/libheif
|
|
9
|
+
Version: 1.21.2
|
|
10
|
+
Requires:
|
|
11
|
+
Requires.private: libde265 x265 aom dav1d libopenjp2
|
|
12
|
+
Libs: -L${libdir} -lheif
|
|
13
|
+
Libs.private: -lc++
|
|
14
|
+
Cflags: -I${includedir}
|
|
15
|
+
Cflags.private: -DLIBHEIF_STATIC_BUILD
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: pylibheif
|
|
3
|
+
Version: 1.21.2
|
|
4
|
+
Summary: Python bindings for libheif - HEIC/AVIF/JPEG2000 image codec
|
|
5
|
+
Keywords: heif,heic,avif,jpeg2000,image,codec,libheif
|
|
6
|
+
Author-Email: Curry Tang <twn39@163.com>
|
|
7
|
+
License: LGPL-3.0-or-later
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Classifier: Programming Language :: C++
|
|
18
|
+
Classifier: Topic :: Multimedia :: Graphics
|
|
19
|
+
Classifier: Topic :: Multimedia :: Graphics :: Graphics Conversion
|
|
20
|
+
Project-URL: Homepage, https://github.com/twn39/pylibheif
|
|
21
|
+
Project-URL: Repository, https://github.com/twn39/pylibheif
|
|
22
|
+
Project-URL: Documentation, https://github.com/twn39/pylibheif#readme
|
|
23
|
+
Project-URL: Issues, https://github.com/twn39/pylibheif/issues
|
|
24
|
+
Requires-Python: >=3.11
|
|
25
|
+
Requires-Dist: numpy>=1.26.0
|
|
26
|
+
Provides-Extra: test
|
|
27
|
+
Requires-Dist: pytest>=7.4.0; extra == "test"
|
|
28
|
+
Requires-Dist: pytest-benchmark>=5.0.0; extra == "test"
|
|
29
|
+
Requires-Dist: pillow-heif>=0.20.0; extra == "test"
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# pylibheif
|
|
33
|
+
|
|
34
|
+
Python bindings for [libheif](https://github.com/strukturag/libheif) using pybind11.
|
|
35
|
+
|
|
36
|
+
## Features
|
|
37
|
+
|
|
38
|
+
- **HEIC/HEIF Support**: Read and write HEIC images (HEVC/H.265 encoded)
|
|
39
|
+
- **AVIF Support**: Read and write AVIF images (AV1 encoded)
|
|
40
|
+
- **JPEG2000 Support**: Read and write JPEG2000 images in HEIF container
|
|
41
|
+
- **NumPy Integration**: Zero-copy access to image data via Python Buffer Protocol
|
|
42
|
+
- **Metadata Support**: Read EXIF and XMP metadata from images
|
|
43
|
+
- **RAII Resource Management**: Automatic resource cleanup with context managers
|
|
44
|
+
|
|
45
|
+
## Supported Formats
|
|
46
|
+
|
|
47
|
+
| Format | Decoding | Encoding | Codec |
|
|
48
|
+
|--------|----------|----------|-------|
|
|
49
|
+
| HEIC (HEVC/H.265) | ✅ | ✅ | libde265 / x265 |
|
|
50
|
+
| AVIF (AV1) | ✅ | ✅ | DAV1D + AOM |
|
|
51
|
+
| JPEG2000 | ✅ | ✅ | OpenJPEG |
|
|
52
|
+
|
|
53
|
+
## Requirements
|
|
54
|
+
|
|
55
|
+
- Python >= 3.12
|
|
56
|
+
- NumPy >= 1.26.0
|
|
57
|
+
- CMake >= 3.15
|
|
58
|
+
- C++17 compatible compiler
|
|
59
|
+
|
|
60
|
+
### System Dependencies
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# macOS
|
|
64
|
+
brew install openjpeg
|
|
65
|
+
|
|
66
|
+
# Ubuntu/Debian
|
|
67
|
+
sudo apt install libopenjp2-7-dev
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Installation
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
pip install pylibheif
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Or with uv:
|
|
77
|
+
```bash
|
|
78
|
+
uv pip install pylibheif
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Building from Source
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Clone with submodules
|
|
85
|
+
git clone --recursive https://github.com/twn39/pylibheif.git
|
|
86
|
+
cd pylibheif
|
|
87
|
+
|
|
88
|
+
# Install
|
|
89
|
+
uv pip install -e .
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Usage
|
|
93
|
+
|
|
94
|
+
### Reading HEIC/AVIF Images
|
|
95
|
+
|
|
96
|
+
**Using context manager (recommended):**
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
import pylibheif
|
|
100
|
+
import numpy as np
|
|
101
|
+
|
|
102
|
+
# Open HEIC file with context manager
|
|
103
|
+
with pylibheif.HeifContext() as ctx:
|
|
104
|
+
ctx.read_from_file('image.heic')
|
|
105
|
+
|
|
106
|
+
# Get primary image handle
|
|
107
|
+
handle = ctx.get_primary_image_handle()
|
|
108
|
+
print(f'Image size: {handle.width}x{handle.height}')
|
|
109
|
+
print(f'Has alpha: {handle.has_alpha}')
|
|
110
|
+
|
|
111
|
+
# Decode to RGB
|
|
112
|
+
img = handle.decode(pylibheif.HeifColorspace.RGB,
|
|
113
|
+
pylibheif.HeifChroma.InterleavedRGB)
|
|
114
|
+
|
|
115
|
+
# Get as NumPy array (zero-copy)
|
|
116
|
+
plane = img.get_plane(pylibheif.HeifChannel.Interleaved, False)
|
|
117
|
+
arr = np.asarray(plane) # shape: (height, width, 3)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Explicit creation (for more control):**
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
import pylibheif
|
|
124
|
+
import numpy as np
|
|
125
|
+
|
|
126
|
+
# Create context explicitly
|
|
127
|
+
ctx = pylibheif.HeifContext()
|
|
128
|
+
ctx.read_from_file('image.heic')
|
|
129
|
+
|
|
130
|
+
handle = ctx.get_primary_image_handle()
|
|
131
|
+
img = handle.decode(pylibheif.HeifColorspace.RGB,
|
|
132
|
+
pylibheif.HeifChroma.InterleavedRGB)
|
|
133
|
+
plane = img.get_plane(pylibheif.HeifChannel.Interleaved, False)
|
|
134
|
+
arr = np.asarray(plane)
|
|
135
|
+
|
|
136
|
+
# Resources are automatically freed when objects go out of scope
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Writing HEIC/AVIF Images
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
import pylibheif
|
|
143
|
+
import numpy as np
|
|
144
|
+
|
|
145
|
+
# Create image from NumPy array
|
|
146
|
+
width, height = 1920, 1080
|
|
147
|
+
img = pylibheif.HeifImage(width, height,
|
|
148
|
+
pylibheif.HeifColorspace.RGB,
|
|
149
|
+
pylibheif.HeifChroma.InterleavedRGB)
|
|
150
|
+
img.add_plane(pylibheif.HeifChannel.Interleaved, width, height, 8)
|
|
151
|
+
|
|
152
|
+
# Fill with data
|
|
153
|
+
plane = img.get_plane(pylibheif.HeifChannel.Interleaved, True)
|
|
154
|
+
arr = np.asarray(plane)
|
|
155
|
+
arr[:] = your_image_data # your RGB data
|
|
156
|
+
|
|
157
|
+
# Encode and save
|
|
158
|
+
ctx = pylibheif.HeifContext()
|
|
159
|
+
|
|
160
|
+
# For HEIC (HEVC)
|
|
161
|
+
encoder = pylibheif.HeifEncoder(pylibheif.HeifCompressionFormat.HEVC)
|
|
162
|
+
# For AVIF (AV1)
|
|
163
|
+
# encoder = pylibheif.HeifEncoder(pylibheif.HeifCompressionFormat.AV1)
|
|
164
|
+
# For JPEG2000
|
|
165
|
+
# encoder = pylibheif.HeifEncoder(pylibheif.HeifCompressionFormat.JPEG2000)
|
|
166
|
+
|
|
167
|
+
encoder.set_lossy_quality(85)
|
|
168
|
+
encoder.encode_image(ctx, img)
|
|
169
|
+
ctx.write_to_file('output.heic')
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Converting HEIC to JPEG
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
import pylibheif
|
|
176
|
+
import numpy as np
|
|
177
|
+
from PIL import Image
|
|
178
|
+
|
|
179
|
+
# Decode HEIC
|
|
180
|
+
ctx = pylibheif.HeifContext()
|
|
181
|
+
ctx.read_from_file('input.heic')
|
|
182
|
+
handle = ctx.get_primary_image_handle()
|
|
183
|
+
img = handle.decode(pylibheif.HeifColorspace.RGB,
|
|
184
|
+
pylibheif.HeifChroma.InterleavedRGB)
|
|
185
|
+
|
|
186
|
+
# Get NumPy array
|
|
187
|
+
plane = img.get_plane(pylibheif.HeifChannel.Interleaved, False)
|
|
188
|
+
arr = np.asarray(plane)
|
|
189
|
+
|
|
190
|
+
# Save as JPEG using PIL
|
|
191
|
+
pil_img = Image.fromarray(arr)
|
|
192
|
+
pil_img.save('output.jpg', 'JPEG', quality=85)
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Reading Metadata
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
import pylibheif
|
|
199
|
+
|
|
200
|
+
ctx = pylibheif.HeifContext()
|
|
201
|
+
ctx.read_from_file('image.heic')
|
|
202
|
+
handle = ctx.get_primary_image_handle()
|
|
203
|
+
|
|
204
|
+
# Get metadata block IDs
|
|
205
|
+
exif_ids = handle.get_metadata_block_ids('Exif')
|
|
206
|
+
for id in exif_ids:
|
|
207
|
+
metadata_type = handle.get_metadata_block_type(id)
|
|
208
|
+
metadata_bytes = handle.get_metadata_block(id)
|
|
209
|
+
print(f'Metadata type: {metadata_type}, size: {len(metadata_bytes)}')
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## API Reference
|
|
213
|
+
|
|
214
|
+
### class `pylibheif.HeifContext`
|
|
215
|
+
|
|
216
|
+
Manages the valid lifetime of libheif context. It is the main entry point (root object) for high-level API.
|
|
217
|
+
|
|
218
|
+
#### Methods
|
|
219
|
+
|
|
220
|
+
**`__init__()`**
|
|
221
|
+
Creates a new empty context.
|
|
222
|
+
|
|
223
|
+
**`read_from_file(filename: str) -> None`**
|
|
224
|
+
Reads a HEIF file from the given filename.
|
|
225
|
+
- `filename`: Path to the HEIF file.
|
|
226
|
+
|
|
227
|
+
**`read_from_memory(data: bytes) -> None`**
|
|
228
|
+
Reads a HEIF file from a bytes object.
|
|
229
|
+
- `data`: Bytes containing the file content.
|
|
230
|
+
|
|
231
|
+
**`write_to_file(filename: str) -> None`**
|
|
232
|
+
Writes the current context to a file.
|
|
233
|
+
- `filename`: Destination path.
|
|
234
|
+
|
|
235
|
+
**`write_to_bytes() -> bytes`**
|
|
236
|
+
Writes the current context to a bytes object.
|
|
237
|
+
- Returns: `bytes` object containing the encoded file data.
|
|
238
|
+
|
|
239
|
+
**`get_primary_image_handle() -> HeifImageHandle`**
|
|
240
|
+
Gets the handle for the primary image in the file.
|
|
241
|
+
- Returns: `HeifImageHandle` for the primary image.
|
|
242
|
+
|
|
243
|
+
**`get_image_handle(id: int) -> HeifImageHandle`**
|
|
244
|
+
Gets the handle for a specific image ID.
|
|
245
|
+
- `id`: The ID of the image (see `get_list_of_top_level_image_IDs`).
|
|
246
|
+
- Returns: `HeifImageHandle`.
|
|
247
|
+
|
|
248
|
+
**`get_list_of_top_level_image_IDs() -> List[int]`**
|
|
249
|
+
Gets a list of IDs of all top-level images in the file.
|
|
250
|
+
- Returns: List of integer IDs.
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
### class `pylibheif.HeifImageHandle`
|
|
255
|
+
|
|
256
|
+
Represents a compressed image within the HEIF file.
|
|
257
|
+
|
|
258
|
+
#### Properties
|
|
259
|
+
|
|
260
|
+
- **`width`** *(int)*: The width of the image.
|
|
261
|
+
- **`height`** *(int)*: The height of the image.
|
|
262
|
+
- **`has_alpha`** *(bool)*: True if the image has an alpha channel.
|
|
263
|
+
|
|
264
|
+
#### Methods
|
|
265
|
+
|
|
266
|
+
**`decode(colorspace: HeifColorspace = HeifColorspace.RGB, chroma: HeifChroma = HeifChroma.InterleavedRGB) -> HeifImage`**
|
|
267
|
+
Decodes the image handle into an uncompressed `HeifImage`.
|
|
268
|
+
- `colorspace`: Target colorspace (default: RGB).
|
|
269
|
+
- `chroma`: Target chroma format (default: InterleavedRGB).
|
|
270
|
+
- Returns: Decoded `HeifImage`.
|
|
271
|
+
|
|
272
|
+
**`get_metadata_block_ids(type_filter: str = "") -> List[str]`**
|
|
273
|
+
Gets a list of metadata block IDs attached to this image.
|
|
274
|
+
- `type_filter`: Optional filter string (e.g. "Exif", "XMP").
|
|
275
|
+
- Returns: List of metadata ID strings.
|
|
276
|
+
|
|
277
|
+
**`get_metadata_block_type(id: str) -> str`**
|
|
278
|
+
Gets the type string of a specific metadata block.
|
|
279
|
+
- `id`: Metadata ID.
|
|
280
|
+
- Returns: Type string (e.g. "Exif").
|
|
281
|
+
|
|
282
|
+
**`get_metadata_block(id: str) -> bytes`**
|
|
283
|
+
Gets the raw data of a metadata block.
|
|
284
|
+
- `id`: Metadata ID.
|
|
285
|
+
- Returns: `bytes` object containing the metadata.
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
### class `pylibheif.HeifImage`
|
|
290
|
+
|
|
291
|
+
Represents an uncompressed image containing pixel data. Supports the Python Buffer Protocol for zero-copy access with NumPy.
|
|
292
|
+
|
|
293
|
+
#### Properties
|
|
294
|
+
|
|
295
|
+
- **`width`** *(int)*: The width of the image.
|
|
296
|
+
- **`height`** *(int)*: The height of the image.
|
|
297
|
+
|
|
298
|
+
#### Methods
|
|
299
|
+
|
|
300
|
+
**`__init__(width: int, height: int, colorspace: HeifColorspace, chroma: HeifChroma)`**
|
|
301
|
+
Creates a new empty image.
|
|
302
|
+
- `width`: Image width.
|
|
303
|
+
- `height`: Image height.
|
|
304
|
+
- `colorspace`: Image colorspace.
|
|
305
|
+
- `chroma`: Image chroma format.
|
|
306
|
+
|
|
307
|
+
**`add_plane(channel: HeifChannel, width: int, height: int, bit_depth: int) -> None`**
|
|
308
|
+
Adds a new plane to the image.
|
|
309
|
+
- `channel`: The channel type (e.g. `HeifChannel.Interleaved`).
|
|
310
|
+
- `width`: Width of the plane.
|
|
311
|
+
- `height`: Height of the plane.
|
|
312
|
+
- `bit_depth`: Bit depth (e.g. 8).
|
|
313
|
+
|
|
314
|
+
**`get_plane(channel: HeifChannel, writeable: bool = False) -> HeifPlane`**
|
|
315
|
+
Gets a plane object that supports the buffer protocol.
|
|
316
|
+
- `channel`: The channel to retrieve.
|
|
317
|
+
- `writeable`: Whether the buffer should be writable.
|
|
318
|
+
- Returns: `HeifPlane` object (wrappable with `np.asarray()`).
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
### class `pylibheif.HeifEncoder`
|
|
323
|
+
|
|
324
|
+
Controls the encoding process.
|
|
325
|
+
|
|
326
|
+
#### Methods
|
|
327
|
+
|
|
328
|
+
**`__init__(format: HeifCompressionFormat)`**
|
|
329
|
+
Creates a new encoder for the specified format.
|
|
330
|
+
- `format`: Compression format (e.g. `HeifCompressionFormat.HEVC`).
|
|
331
|
+
|
|
332
|
+
**`set_lossy_quality(quality: int) -> None`**
|
|
333
|
+
Sets the quality for lossy compression.
|
|
334
|
+
- `quality`: Integer between 0 (lowest) and 100 (highest).
|
|
335
|
+
|
|
336
|
+
**`set_parameter(name: str, value: str) -> None`**
|
|
337
|
+
Sets a low-level encoder parameter.
|
|
338
|
+
- `name`: Parameter name (e.g. "speed" for AV1).
|
|
339
|
+
- `value`: Parameter value.
|
|
340
|
+
|
|
341
|
+
**`encode_image(context: HeifContext, image: HeifImage) -> None`**
|
|
342
|
+
Encodes the given image and appends it to the context.
|
|
343
|
+
- `context`: The destination `HeifContext`.
|
|
344
|
+
- `image`: The source `HeifImage` to encode.
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
### Enums
|
|
349
|
+
|
|
350
|
+
#### `pylibheif.HeifColorspace`
|
|
351
|
+
- `RGB`, `YCbCr`, `Monochrome`, `Undefined`
|
|
352
|
+
|
|
353
|
+
#### `pylibheif.HeifChroma`
|
|
354
|
+
- `InterleavedRGB`: Interleaved R, G, B bytes.
|
|
355
|
+
- `InterleavedRGBA`: Interleaved R, G, B, A bytes.
|
|
356
|
+
- `C420`: YUV 4:2:0 planar.
|
|
357
|
+
- `C422`: YUV 4:2:2 planar.
|
|
358
|
+
- `C444`: YUV 4:4:4 planar.
|
|
359
|
+
- `Monochrome`.
|
|
360
|
+
|
|
361
|
+
#### `pylibheif.HeifChannel`
|
|
362
|
+
- `Interleaved`: For interleaved RGB/RGBA.
|
|
363
|
+
- `Y`, `Cb`, `Cr`: For YUV planar.
|
|
364
|
+
- `R`, `G`, `B`: For RGB planar.
|
|
365
|
+
- `Alpha`: For Alpha channel.
|
|
366
|
+
|
|
367
|
+
#### `pylibheif.HeifCompressionFormat`
|
|
368
|
+
- `HEVC`: H.265 (libx265).
|
|
369
|
+
- `AV1`: AV1 (AOM/RAV1E/SVT).
|
|
370
|
+
- `JPEG`: JPEG.
|
|
371
|
+
- `JPEG2000`: JPEG 2000 (OpenJPEG).
|
|
372
|
+
|
|
373
|
+
## Building from Source
|
|
374
|
+
|
|
375
|
+
```bash
|
|
376
|
+
# Clone with submodules
|
|
377
|
+
git clone --recursive https://github.com/your-username/pylibheif.git
|
|
378
|
+
cd pylibheif
|
|
379
|
+
|
|
380
|
+
# Build
|
|
381
|
+
uv pip install -e .
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
## Performance
|
|
385
|
+
|
|
386
|
+
Benchmarks on 1920x1080 RGB image (Apple Silicon):
|
|
387
|
+
|
|
388
|
+
| Operation | pylibheif | pillow-heif | Note |
|
|
389
|
+
|:---|:---:|:---:|:---|
|
|
390
|
+
| HEVC Decode | 25 ms | 25 ms | ~39 FPS |
|
|
391
|
+
| HEVC Encode | 279 ms | 272 ms | Quality 80 |
|
|
392
|
+
| AV1 Encode | 91 ms | - | Speed 50 |
|
|
393
|
+
|
|
394
|
+
`pylibheif` offers performance comparable to `pillow-heif` (both wrapper libheif), but exposes a lower-level C++ API for fine-grained control.
|
|
395
|
+
|
|
396
|
+
Run benchmarks yourself:
|
|
397
|
+
```bash
|
|
398
|
+
uv pip install pillow-heif pytest-benchmark
|
|
399
|
+
uv run pytest tests/test_benchmark.py --benchmark-only
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
## License
|
|
403
|
+
|
|
404
|
+
This project is licensed under the LGPL-3.0 License - see the [LICENSE](LICENSE) file for details.
|
|
405
|
+
|
|
406
|
+
## Acknowledgments
|
|
407
|
+
|
|
408
|
+
- [libheif](https://github.com/strukturag/libheif) - HEIF/AVIF codec library
|
|
409
|
+
- [pybind11](https://github.com/pybind/pybind11) - C++/Python bindings
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
pylibheif.cpython-312-darwin.so,sha256=IJMgV_e5efb5PGbvVMhr1zsFDHczUphNkSZb2ZtcM9I,1429504
|
|
2
|
+
pylibheif-1.21.2.dist-info/RECORD,,
|
|
3
|
+
pylibheif-1.21.2.dist-info/WHEEL,sha256=H9cl2y6LaR-sUUsOloOqKUDVWa7pMgj9mhj7ak1x39k,114
|
|
4
|
+
pylibheif-1.21.2.dist-info/METADATA,sha256=Z_dXp-vdVqFWiP3sfmyxtr5VNSD-GnGoIfEuQyH3-hA,11672
|
|
5
|
+
pylibheif-1.21.2.dist-info/licenses/LICENSE,sha256=fDdTdPxIYzjisSIHtLHWfwdQjCB1YbnGO14a-rg3M7s,7636
|
|
6
|
+
include/libheif/heif_error.h,sha256=buuv0fMvYb1NU_r7rPeHkcFMYIOzG-DH-7mOQI-xl2M,8765
|
|
7
|
+
include/libheif/heif_plugin.h,sha256=phh6v7n8qs9XpZhR7tx1U1qSD2HkaBD9ZsX2dZ8OluI,13118
|
|
8
|
+
include/libheif/heif.h,sha256=lttx6Y--O6YMPgA442G3CyDbCrjHoQ76rHgJMkCSnDI,1351
|
|
9
|
+
include/libheif/heif_entity_groups.h,sha256=x4U5pwoD1BmdNYRkzqPD5Yr6A-82hgC9o9w2DG-Ie_A,1895
|
|
10
|
+
include/libheif/heif_text.h,sha256=4_gegjTlEhG8YsLuyikP76xhk4VLUKWNn3q4jeKbSyg,5502
|
|
11
|
+
include/libheif/heif_tiling.h,sha256=kLI4NA3u_uFdN_s-GKYS200yu5w7dp45qnl2f1f3jMg,5453
|
|
12
|
+
include/libheif/heif_color.h,sha256=F0kvmt5GOkgJP5iHPeuGJUCCETJtd0O0GS8R-1VZgFQ,14427
|
|
13
|
+
include/libheif/heif_cxx.h,sha256=tdB9fHtbxuVb2KILP2LUJ-w5c013X0kZLVnnVB4IMnE,41357
|
|
14
|
+
include/libheif/heif_metadata.h,sha256=fse7pHVkgYzjBY36cY4P4qtCeWB73Rca-7j87L5xrVo,6225
|
|
15
|
+
include/libheif/heif_version.h,sha256=IKoUgW9mIJDLbZyy5HK7AkR9J0oivP96RX7lSpQwkPU,1275
|
|
16
|
+
include/libheif/heif_brands.h,sha256=JeOWoR7YAG3akn_NsrDelL4uAMRSHbsaQzaDLHfMHUk,10586
|
|
17
|
+
include/libheif/heif_encoding.h,sha256=Eqz-RkGubU34WBvFA0J5JgbnJ8RhWnBKdgrtywko1Uw,16574
|
|
18
|
+
include/libheif/heif_library.h,sha256=xu0O9sYUz5D70eARJLuJ5wj_PcJFq1-Mpw6AHsvHF6M,7943
|
|
19
|
+
include/libheif/heif_regions.h,sha256=qUiOn9Q8tidWjNFWRQB3j2gVwtz_NMScaKiBiYM8mYQ,38812
|
|
20
|
+
include/libheif/heif_security.h,sha256=BfyBApRa2ly_fNeuTd9B4k9579ZLNigDWH2YXG2_-N4,3316
|
|
21
|
+
include/libheif/heif_tai_timestamps.h,sha256=1FDjZmwkJXMsKYcBKoRcWKuESEWUKaC5UWlKDicWeH0,7798
|
|
22
|
+
include/libheif/heif_items.h,sha256=zDci6_hSvJ0BTPiOEIJ9XGfMq73LgzvvjuGVPbHA8m4,9849
|
|
23
|
+
include/libheif/heif_aux_images.h,sha256=ZWIRPKs07k9-HOaKt6AQYrgAAPNdt-ji-_EHILxasr4,7258
|
|
24
|
+
include/libheif/heif_sequences.h,sha256=_H6zhko2pELq-DfVMO8BVk1VyDNzCBiw0SutYs4RhA4,22789
|
|
25
|
+
include/libheif/heif_decoding.h,sha256=lfIrX1wb-eYkf5zkBB2mWNlhWpPLTrOFL7ieV5zNlZw,6332
|
|
26
|
+
include/libheif/heif_properties.h,sha256=ZFN9A_9Jnq6_fICy7Ew_10oZAAyiOxN38i9yO-6QIyM,10721
|
|
27
|
+
include/libheif/heif_image.h,sha256=X888K_zjlJutbnmNX5lglU-vi8prFgdiKIQPL8QAKQQ,13681
|
|
28
|
+
include/libheif/heif_image_handle.h,sha256=7iFydgGAdY6WzAGECrSXHMpuIhnYvHGzyppgNIF3c-c,5134
|
|
29
|
+
include/libheif/heif_uncompressed.h,sha256=TQKIEDnly7GjolFdoI492vhma28V96Gex5FWsKZ2zGk,3868
|
|
30
|
+
include/libheif/heif_context.h,sha256=FfIGQVcB1-M1e8Bde8FTVQbcM0UxSAO5vYoew0v_3-Y,13014
|
|
31
|
+
pylibheif.dylibs/libvmaf.3.dylib,sha256=lcTjGz9G1hkeuh-Ev0VOEOzXstTUOzjdLjAr9ClgcW0,748064
|
|
32
|
+
pylibheif.dylibs/libdav1d.7.dylib,sha256=tjhJqwA_EqyChtFvKLRuYvdvyVNc2XGaUFPiqUbUJaw,798624
|
|
33
|
+
pylibheif.dylibs/libopenjp2.2.5.4.dylib,sha256=H5iNXa_UvIHu8ttzJYCEgo3BX6QHoBtK7uAqerKZjhU,325968
|
|
34
|
+
pylibheif.dylibs/libde265.0.dylib,sha256=mw2Bp02q-Rmf0lOr0Gdihj2j-UuWD6ndUhDQRIef9d0,422608
|
|
35
|
+
pylibheif.dylibs/libx265.215.dylib,sha256=0HBo8OEcH0SKUdOpcON3korZdB1ncqiyb6Rkiu1CQBY,4923728
|
|
36
|
+
pylibheif.dylibs/libaom.3.13.1.dylib,sha256=-slvol0iSmqGkxMbc0-sca04zA6UlGjhHkHY9N6_Z0Y,3924256
|
|
37
|
+
lib/libheif.a,sha256=k-s2aGM9dNFeoauuqShinMys59aublWDVAokXmNqVkw,3735136
|
|
38
|
+
lib/pkgconfig/libheif.pc,sha256=il_NeGoW3GKes6png-UYh-J-cA2tPj5-YKzWjuB28iY,435
|
|
39
|
+
lib/cmake/libheif/libheif-config.cmake,sha256=_1uT_b1lQ4pbn0nbCgN-x2AN3TBcdxobnnwbNiCwz9E,4421
|
|
40
|
+
lib/cmake/libheif/libheif-config-release.cmake,sha256=NmefsNyqv-yyAObfvRLShZEKExbE98P2Cd28eroyejw,789
|
|
41
|
+
lib/cmake/libheif/libheif-config-version.cmake,sha256=r0Rw3uKsVEzNcMMg60edTBAr9df_-NWIXMYIdIy51Og,3252
|