strukturag/libheif
GitHub: strukturag/libheif
libheif 是一个支持 HEIF、AVIF 等多种现代图像格式的编解码库,提供统一的 API 来实现高效图像的读取、写入与转换。
Stars: 2253 | Forks: 382
# libheif
[](https://github.com/strukturag/libheif/actions) [](https://ci.appveyor.com/project/strukturag/libheif) [](https://scan.coverity.com/projects/strukturag-libheif)
libheif 是一个 ISO/IEC 23008-12 HEIF 和 AVIF(AV1 图像文件格式)文件格式的解码器和编码器。
HEIC 和 AVIF 是新的图像文件格式,分别采用 HEVC (H.265) 或 AV1 图像编码,以实现目前可能的最佳压缩率。
在 HEIC 和 AVIF 的基础上,libheif 还支持使用 VVC、AVC、JPEG、JPEG-2000 和 ISO/IEC 23001-17 编码的 HEIF 图像。
ISO/IEC 23001-17 编解码器内置于 libheif 中,允许以许多不同的格式存储无损图像和视频。
libheif 利用各种编解码器库来实现每种压缩格式。
对于 HEIC,默认使用 [libde265](https://github.com/strukturag/libde265) 进行解码,使用 x265 进行编码。
对于 AVIF,使用 libaom、dav1d、svt-av1 或 rav1e 作为编解码器。
libheif 可以使用所支持的编解码器的子集进行构建,以保持较小的体积和较少的依赖项数量。
或者,libheif 编解码器也可以构建为单独的插件,以便在使用时动态安装和加载。
## 支持的功能
libheif 支持:
* HEIC、AVIF、VVC、AVC、JPEG-in-HEIF、JPEG2000、未压缩(ISO/IEC 23001-17:2024)编解码器
* alpha 通道、深度图、缩略图、辅助图像
* 单个文件中的多张图像
* HEIF 图像序列和 MP4 视频,包括 alpha 通道
* 分块图像,支持单个图块解码以及通过逐个添加图块来编码分块图像
* HDR 图像,根据嵌入的颜色配置文件进行正确的颜色转换
* 图像变换(裁剪、镜像、旋转)、叠加图像
* 用于添加备用编解码器的插件接口
* 读取 EXIF 和 XMP 元数据
* 区域注释和遮罩图像
* 通过 data-reader 接口从网络请求数据来实现图像和视频的流式传输
支持的编解码器:
| 格式 | 解码器 | 编码器 |
|:-------------|:-------------------:|:----------------------------:|
| HEIC | libde265, ffmpeg | x265, kvazaar |
| AVIF | libaom, dav1d | libaom, rav1e, svt-av1 |
| VVC | vvdec | vvenc, uvg266 |
| AVC | openh264, ffmpeg | x264 |
| JPEG | libjpeg(-turbo) | libjpeg(-turbo) |
| JPEG2000 | OpenJPEG | OpenJPEG |
| HTJ2K | OpenJPEG | OpenJPH |
| uncompressed | 内置 | 内置 |
## 编程 API
该库提供了一个 C API,以便于集成和提供广泛的语言支持。
解码器通过相同的 API 自动支持 HEIF 和 AVIF(以及其他压缩格式)。相同的解码代码可用于解码其中任何一种。
只需将 `heif_compression_HEVC` 或 `heif_compression_AV1` 设置为
`heif_context_get_encoder_for_format()`,或使用任何其他压缩格式,即可在 HEIF 和 AVIF 之间轻松切换编码器。
### 从 HEIF 文件加载主图像
```
heif_context* ctx = heif_context_alloc();
heif_context_read_from_file(ctx, input_filename, nullptr);
// get a handle to the primary image
heif_image_handle* handle;
heif_context_get_primary_image_handle(ctx, &handle);
// decode the image and convert colorspace to RGB, saved as 24bit interleaved
heif_image* img;
heif_decode_image(handle, &img, heif_colorspace_RGB, heif_chroma_interleaved_RGB, nullptr);
int stride;
const uint8_t* data = heif_image_get_plane_readonly(img, heif_channel_interleaved, &stride);
// ... process data as needed ...
// clean up resources
heif_image_release(img);
heif_image_handle_release(handle);
heif_context_free(ctx);
```
### 写入 HEIF 文件
```
heif_context* ctx = heif_context_alloc();
// get the default encoder
heif_encoder* encoder;
heif_context_get_encoder_for_format(ctx, heif_compression_HEVC, &encoder);
// set the encoder parameters
heif_encoder_set_lossy_quality(encoder, 50);
// encode the image
heif_image* image; // code to fill in the image omitted in this example
heif_context_encode_image(ctx, image, encoder, nullptr, nullptr);
heif_encoder_release(encoder);
heif_context_write_to_file(ctx, "output.heic");
heif_context_free(ctx);
```
### 从 HEIF 文件获取 EXIF 数据
```
heif_item_id exif_id;
int n = heif_image_handle_get_list_of_metadata_block_IDs(image_handle, "Exif", &exif_id, 1);
if (n==1) {
size_t exifSize = heif_image_handle_get_metadata_size(image_handle, exif_id);
uint8_t* exifData = malloc(exifSize);
struct heif_error error = heif_image_handle_get_metadata(image_handle, exif_id, exifData);
}
```
### 图像序列,MP4 视频
请参阅[图像序列 API 文档](https://github.com/strukturag/libheif/wiki/Reading-and-Writing-Sequences)。
由于 HEIF 图像序列与 MP4 视频非常相似,libheif 也可以使用所有支持的编解码器读取和写入 MP4 视频(无音频)。
### 高分辨率分块图像
对于非常大分辨率的图像,处理整张图像并不总是可行的。
在这种情况下,`libheif` 可以逐块处理图像。
请参阅[图像分块 API 文档](https://github.com/strukturag/libheif/wiki/Reading-and-Writing-Tiled-Images)。
### 更多文档
有关完整的 C API,请参阅头文件。
还有一个 C++ API,它是 C API 的仅头文件包装器。
因此,您可以使用 C++ API 并仍然保持二进制兼容性。
使用 C++ API 的代码比直接使用 C API 的代码要简洁得多。
## 编译
该库使用 CMake 构建系统(早期的 autotools 构建文件已在 v1.16.0 版本中删除)。
对于最小化配置,我们建议在 HEIC 中使用 libde265 和 x265 编解码器,并在 AVIF 中使用 AOM。
请确保首先编译并安装 [libde265](https://github.com/strukturag/libde265),以便配置脚本能够找到它。
如果您想使用 HEIF 编码,还要安装 x265 及其开发文件,但请注意 x265 是 GPL 许可的。
x265 的一个替代方案是 kvazaar (BSD)。
基本构建步骤如下(--preset 参数需要 CMake >= 3.21):
```
mkdir build
cd build
cmake --preset=release ..
make
```
CMake presets 涵盖了最常见的用例。
* `release`:首选 preset,它将所有编解码器编译为单独的插件。
如果您不想分发其中某些插件(例如 HEIC),可以省略这些插件的打包。
* `release-noplugins`:这是一个较小且自包含的 libheif 构建,不使用插件系统。
构建的单个库支持 HEIC 和 AVIF。
* `testing`:用于构建和执行单元测试。同时还会暴露内部库符号。请勿用于分发。
* `fuzzing`:包含与 release 构建中一样的所有编解码器,但配置为带有启用 fuzzer 的自包含库。该库不应被分发。
您可以根据需要选择性地调整这些标准配置。
例如,可以通过在 `build` 目录中调用 `ccmake .` 来完成此操作。
### CMake 配置变量
libheif 支持许多不同的编解码器。为了减少依赖项数量和库大小,您可以选择包含其中哪些编解码器。每个编解码器既可以作为硬依赖项内置到库中,也可以编译为单独的插件文件进行动态加载。
对于每个编解码器,有两个配置变量:
* `WITH_{codec}`:启用该编解码器
* `WITH_{codec}_PLUGIN`:启用后,该编解码器将被编译为单独的插件。
为了使用动态插件,还要确保启用了 `ENABLE_PLUGIN_LOADING`。
占位符 `{codec}` 可以是以下值:`LIBDE265`、`X265`、`AOM_DECODER`、`AOM_ENCODER`、`SvtEnc`、`DAV1D`、`OpenH264`、`X264`、`FFMPEG_DECODER`、`JPEG_DECODER`、`JPEG_ENCODER`、`KVAZAAR`、`OpenJPEG_DECODER`、`OpenJPEG_ENCODER`、`OPENJPH_ENCODER`、`VVDEC`、`VVENC`、`UVG266`、`WEBCODECS`。
其他选项包括:
* `WITH_UNCOMPRESSED_CODEC`:启用对 ISO/IEC 23001-17:2024 标准下未压缩图像的支持。这是*实验性*的,
并且不能作为动态插件使用。启用后,它会增加对 `zlib` 的依赖,并可选择使用 `brotli`。
* `WITH_HEADER_COMPRESSION`:启用对压缩元数据的支持。启用后,它会增加对 `zlib` 的依赖。
请注意,header compression 目前尚未得到广泛支持。
* `WITH_LIBSHARPYUV`:启用高质量的 YCbCr/RGB 颜色空间转换算法(需要 `libsharpyuv`,
例如来自 `third-party` 目录)。
* `ENABLE_EXPERIMENTAL_FEATURES`:启用当前正在开发中且 API 尚不稳定的功能,
并且可能包含安全风险。启用此项后,将安装一个包含此不稳定 API 的头文件 `heif_experimental.h`。
发行版不应在 release 或 production 构建中启用此项。
* `ENABLE_MULTITHREADING_SUPPORT`:可用于禁用任何多线程支持,例如对于嵌入式平台。
* `ENABLE_PARALLEL_TILE_DECODING`:启用后,libheif 将并行解码分块图像以加快编译速度。
* `PLUGIN_DIRECTORY`:当未设置环境变量 `LIBHEIF_PLUGIN_PATH` 时,libheif 搜索动态插件的目录。
* `WITH_REDUCED_VISIBILITY`:仅将作为公共 API 的符号导出到库中。
运行某些测试时必须关闭此项。
### macOS
1. 使用 Homebrew 安装依赖项
brew install cmake make pkg-config x265 libde265 libjpeg libtool
2. 配置并构建项目(--preset 参数需要 CMake >= 3.21):
mkdir build
cd build
cmake --preset=release ..
./configure
make
### Windows
您可以使用 [vcpkg](https://github.com/Microsoft/vcpkg/) 依赖管理器构建和安装 libheif:
```
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.bat
./vcpkg integrate install
./vcpkg install libheif
```
vcpkg 中的 libheif port 由 Microsoft 团队成员和社区贡献者保持最新。如果版本已过期,请在 vcpkg 仓库中[创建 issue 或 pull request](https://github.com/Microsoft/vcpkg)。
### 为 AVIF 添加 libaom 编码器/解码器
* 运行 `third-party` 目录中的 `aom.cmd` 脚本,以下载 libaom 并进行编译。
在运行 `cmake` 或 `configure` 时,请确保环境变量
`PKG_CONFIG_PATH` 包含指向 `third-party/aom/dist/lib/pkgconfig` 的绝对路径。
### 为 AVIF 添加 rav1e 编码器
* 安装 `cargo`。
* 通过执行以下命令安装 `cargo-c`
```
cargo install --force cargo-c
```
* 运行 `third-party` 目录中的 `rav1e.cmd` 脚本,以下载 rav1e 并进行编译。
在运行 `cmake` 时,请确保环境变量
`PKG_CONFIG_PATH` 包含指向 `third-party/rav1e/dist/lib/pkgconfig` 的绝对路径。
### 为 AVIF 添加 dav1d 解码器
* 安装 [`meson`](https://mesonbuild.com/)。
* 运行 `third-party` 目录中的 `dav1d.cmd` 脚本,以下载 dav1d 并进行编译。
在运行 `cmake` 时,请确保环境变量
`PKG_CONFIG_PATH` 包含指向 `third-party/dav1d/dist/lib/x86_64-linux-gnu/pkgconfig` 的绝对路径。
### 为 AVIF 添加 SVT-AV1 编码器
您可以使用系统中安装的 SVT-AV1 编码器库,也可以使用自行编译的当前版本。
如果您想自行编译 SVT-AV1,
* 运行 `third-party` 目录中的 `svt.cmd` 脚本,以下载 SVT-AV1 并进行编译。
您必须使用 CMake 启用 SVT-AV1。
在运行 `cmake` 时,请确保环境变量
`PKG_CONFIG_PATH` 包含指向 `third-party/SVT-AV1/Build/linux/install/lib/pkgconfig` 的绝对路径。
您可能需要将此路径中的 `linux` 替换为您的系统标识符。
## 编解码器插件
从 v1.14.0 版本开始,每个编解码器后端都可以静态编译到 libheif 中,或者作为动态加载的插件。
您可以在 CMake 设置中使用 `WITH_{codec}_PLUGIN` 选项为每个编解码器后端单独进行选择。
将编解码器后端编译为动态插件将生成一个共享库,该库将与 libheif 一起安装到系统中。
这样做的好处是只需安装所需的插件,并且 libheif 的依赖项更少。
这些插件将从存储在环境变量 `LIBHEIF_PLUGIN_PATH` 中的以冒号分隔(Windows 上以分号分隔)的目录列表中加载。
如果此变量为空,则从 CMake 配置中指定的目录加载它们。
您也可以通过编程方式添加插件目录。
### 编解码器特定说明
* FFMPEG 解码插件可以利用 h265 硬件解码器。但是,它目前(v1.17.0,ffmpeg v4.4.2)并不能在所有流上
正常工作。因此,如果 libde265 解码器可用,libheif 仍然优先使用它。
* “webcodecs” HEVC 解码器只能在 emscripten 构建中使用,因为它使用 Web 浏览器的 API。出于同样的原因,它不能作为插件使用。
## 用法
libheif 附带了一套命令行工具:
* `heif-dec` 用于将 HEIF 图像解码为 JPEG 或 PNG。它还可以解码图像序列或4 视频。
* `heif-enc` 用于将 JPEG、PNG、TIFF 或 Y4M 图像编码为 HEIF 图像、图像序列或 MP4 视频。
* `heif-info` 用于获取有关 HEIF 文件的一些概览信息,或者(使用 `-d` 选项)转储文件的完整 box 结构。
* `heif-view` 用于显示 HEIF 图像序列
### `heif-enc` 命令行工具
您可以在[Wiki 页面](https://github.com/strukturag/libheif/wiki/heif%E2%80%90enc-Command-Line-Tool)上找到有关 `heif-enc` 工具的更多文档。
### 安全限制
libheif 定义了一些安全限制,以防止非常大的图像耗尽可用内存或防止恶意输入文件被用于拒绝服务攻击。
当您在使用 libheif API 进行编程并且需要处理非常大的图像时,可以单独设置 `heif_security_limits`。
使用 `heif-dec` 时,可以通过 `--disable-limits` 选项关闭安全限制。
如果第三方软件正在使用 libheif,但没有为您提供关闭限制的方法,您可以设置环境变量 `LIBHEIF_SECURITY_LIMITS=off` 以全局关闭它。
显然,只有在您知道自己在做什么并且确定不处理恶意文件时,才执行此操作。
## 编码器基准测试
有关 AVIF 编码器的最新基准测试(截至 2022 年 10 月 14 日),可以在 Wiki 页面
[AVIF 编码基准测试](https://github.com/strukturag/libheif/wiki/AVIF-Encoder-Benchmark)上找到。
## 语言绑定
* .NET 平台(C#、F# 和其他语言):[libheif-sharp](https://github.com/0xC0000054/libheif-sharp)
* C++:libheif 的一部分
* Go:[libheif-go](https://github.com/strukturag/libheif-go),随 libheif 分发的 wrapper 已弃用
* JavaScript:通过使用 emscripten 编译(见下文)
* NodeJS 模块:[libheif-js](https://www.npmjs.com/package/libheif-js)
* Python:[pyheif](https://pypi.org/project/pyheif/),[pillow_heif](https://pypi.org/project/pillow-heif/)
* Rust:[libheif-sys](https://github.com/Cykooz/libheif-sys)
* Swift:[libheif-Xcode](https://swiftpackageregistry.com/SDWebImage/libheif-Xcode)
* JavaFX:[LibHeifFx](https://github.com/lanthale/LibHeifFX)
能够直接与 C 库接口的语言(例如 Swift、C#)应该可以直接开箱即用。
## 编译为 JavaScript / WASM
libheif 也可以使用
[emscripten](http://kripken.github.io/emscripten-site/) 编译为 JavaScript。
可以像这样构建它(在 libheif 目录中):
```
mkdir buildjs
cd buildjs
USE_WASM=0 ../build-emscripten.sh ..
```
设置 `USE_WASM=1` 以构建 WASM 输出。
有关更多选项,请参阅 `build-emscripten.sh` 脚本。
## 在线演示
查看这个[在线演示](https://strukturag.github.io/libheif/)。
这是在您的浏览器中以 JavaScript 运行的 `libheif`。
## 示例程序
`examples` 目录中提供了一些示例程序。
程序 `heif-dec` 将存储在 HEIF/AVIF 文件中的所有图像转换为 JPEG 或 PNG。
`heif-enc` 允许您将 JPEG 文件转换为 HEIF/AVIF。
程序 `heif-info` 是一个简单、最小化的解码器,可将文件结构转储到控制台。
例如,将 `example.heic` 转换为 JPEG,并将其中一张 JPEG 转换回 HEIF:
```
cd examples/
./heif-dec example.heic example.jpeg
./heif-enc example-1.jpeg -o example.heif
```
要将 `example-1.jpeg` 转换为 AVIF,请使用:
```
./heif-enc example-1.jpeg -A -o example.avif
```
在[这里](https://github.com/strukturag/heif-gimp-plugin)还有一个使用 libheif 的 GIMP 插件。
## Gnome 桌面的 HEIF/AVIF 缩略图
`heif-thumbnailer` 程序可用作 Gnome 桌面的 HEIF/AVIF 缩略图生成器。
匹配的 Gnome 配置文件位于 `gnome` 目录中。
将文件 `heif.xml` 和 `avif.xml` 放入 `/usr/share/mime/packages`,并将 `heif.thumbnailer` 放入 `/usr/share/thumbnailers`。
您可能需要运行 `update-mime-database /usr/share/mime` 来更新已知 MIME 类型的列表。
## gdk-pixbuf 加载器
libheif 还包含一个用于 HEIF/AVIF 图像的 gdk-pixbuf 加载器。'make install' 会将插件
复制到系统目录中。但是,您仍然需要运行 `gdk-pixbuf-query-loaders --update-cache`
来更新 gdk-pixbuf 加载器数据库。
## 使用 libheif 的软件
* [GIMP](https://www.gimp.org/)
* [Krita](https://krita.org)
* [ImageMagick](https://imagemagick.org/)
* [GraphicsMagick](http://www.graphicsmagick.org/)
* [darktable](https://www.darktable.org)
* [digiKam 7.0.0](https://www.digikam.org/)
* [libvips](https://github.com/libvips/libvips)
* [kImageFormats](https://api.kde.org/frameworks/kimageformats/html/index.html)
* [libGD](https://libgd.github.io/)
* [Kodi HEIF 图像解码插件](https://kodi.wiki/view/Add-on:HEIF_image_decoder)
* [bimg](https://github.com/h2non/bimg)
* [GDAL](https://gdal.org/drivers/raster/heif.html)
* [OpenImageIO](https://sites.google.com/site/openimageio/)
* [XnView](https://www.xnview.com)
## 打包状态
[](https://repology.org/project/libheif/versions)
## 赞助商
由于我是一名独立开发者,我需要您的支持以便能够为 libheif 分配时间。
您可以使用右侧列中的链接[赞助](https://github.com/sponsors/farindk)开发工作。
非常感谢这些主要赞助商对 libheif 开发的支持:
* AOMedia
* OGC (Open Geospatial Consortium)
* Pinterest
* Shopify
* StrukturAG
## 许可证
libheif 根据 GNU Lesser General Public License 的条款分发。
示例应用程序根据 MIT 许可证的条款分发。
有关更多详细信息,请参阅 COPYING。
版权所有 (c) 2017-2020 Struktur AG
版权所有 (c) 2017-2026 Dirk Farin
联系方式:Dirk Farin
标签:AVIF, Bash脚本, C++, HEIF, 图像处理, 多媒体编解码, 开发库, 数据擦除