随着软硬件技术的不断升级,相机像素越来越高、人们对照片细节的要求越来越多,高压缩率、低损失率的编码格式,heic 越来越多地出现在人们的生活中,现在 iOS 相机已经默认保存 heic 格式的图片了。而通常情况下,FFmpeg 是不支持对 heif 解析的。
无法解析 heic 格式的 FFmpeg
当第一次遇到 HEIC 格式的图片时,遇到了 FFmpeg 的报错,av_format_open_input() 这个接口的调用就失败了,也就是说,FFmpeg 对 HEIC 这种封装格式没法解析。
简单了解了一下 HEIC 相关的知识点,它是使用 hevc,也就是 h265 编码格式压缩的。因此,解码其实并不是问题的所在,heic 的封装格式才是。
自带示例 demo 的 libheif
通过查资料发现,一个比较常见的 C++ 解析解码 heic 格式图片的开源库是 libheif,而这个库对 h265 的解码过程又依赖于另一个开源 C++ 库 libde265。
同时从 github 上下载了这两个开源库。根据 github 上两个库 readme.md 的内容,依次编译通过 libde265 和 libheif 之后,就可以参考 libheif/examples/heif_convert.cc 来完成一个简单的对 HEIC 格式图片的解析、解码的过程。主要调用的函数如下:
#include <libheif/heif.h>
bool decodeheif(string filename) {
heif_context* heif_ctx_ = heif_context_alloc();
if (!heif_ctx_) return false;
heif_error error = heif_context_read_from_file(heif_ctx_, filename.c_str(), nullptr);
if (error.code != heif_error_Ok) return false;
heif_image_handle *heif_handle_ = nullptr;
error = heif_context_get_primary_image_handle(heif_ctx_, &heif_handle_);
if (error.code != heif_error_Ok) return false;
width_ = heif_image_handle_get_width(heif_handle_);
height_ = heif_image_handle_get_height(heif_handle_);
heif_image* heif_img_ = nullptr;
error = heif_decode_image(heif_handle_, &heif_img_, heif_colorspace_RGB, heif_chroma_interleaved_RGBA, nullptr);
if (error.code != heif_error_Ok) return false;
int stride;
const uint8_t *data = heif_image_get_plane_readonly(heif_img_, heif_channel_interleaved, &stride);
if (data == nullptr) return false;
}
对 libheif 相关环境变量内存的释放也很简单:
if (heif_ctx_) {
heif_context_free(heif_ctx_);
heif_ctx_ = nullptr;
}
if (heif_handle_) {
heif_image_handle_release(heif_handle_);
heif_handle_ = nullptr;
}
if (heif_img_) {
heif_image_release(heif_img_);
heif_img_ = nullptr;
}
|