郑州网站建设hnqfu,10元备案域名购买,免费设计网,今天热点新闻高效率图像文件格式#xff08;英语#xff1a;High Efficiency Image File Format, HEIF#xff1b;也称高效图像文件格式#xff09;是一个用于单张图像或图像序列的文件格式。它由运动图像专家组#xff08;MPEG#xff09;开发#xff0c;并在MPEG-H Part 12#x…高效率图像文件格式英语High Efficiency Image File Format, HEIF也称高效图像文件格式是一个用于单张图像或图像序列的文件格式。它由运动图像专家组MPEG开发并在MPEG-H Part 12ISO/IEC 23008-12中定义。 HEIF规范也定义了高效率视频编码HEVC编码的内嵌图像和HEVC编码的图像序列的存储方式其中以受约束的方式应用帧间预测。 HEIF文件与ISO基本媒体文件格式ISOBMFFISO/IEC 14496-12兼容并且还可以包括其他媒体流例如定时的文本和音频。 环境配置 相关资源https://github.com/strukturag/libheif Windows最简单、快捷方式自行编译容易出错 You can build and install libheif using the vcpkg dependency manager:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.bat
./vcpkg integrate install
./vcpkg install libheifLinux/macOS(或参考上述相关资源链接) 1. Install dependencies with Homebrew brew install cmake make pkg-config x265 libde265 libjpeg libtool 2. Configure and build project (–preset argument needs CMake 3.21): mkdir buildcd buildcmake --presetrelease .../configuremake功能cv::Mat 转 HEIF文件 HEIF文件转cv::Mat cpp
#include libheif/heif.h
#include opencv2/opencv.hpp
#include iostreambool RGBMatToHeif(cv::Mat mat, const char* filename)
{if (mat.empty() || mat.type() ! CV_8UC3){std::cerr Invalid Mat format. Expected 8UC3. std::endl;return false;}struct heif_image* image;struct heif_context* ctx heif_context_alloc();struct heif_error err;int width mat.cols;int height mat.rows;// 创建HEIF图像err heif_image_create(width, height, heif_colorspace_RGB, heif_chroma_interleaved_RGB, image);if (err.code ! heif_error_Ok){std::cerr Error adding plane to HEIF image err.message std::endl;heif_image_release(image);heif_context_free(ctx);return false;}// 添加一个用于交错 RGB 通道的图像平面err heif_image_add_plane(image, heif_channel_interleaved, width, height, 8);if (err.code ! heif_error_Ok) {std::cerr Error adding plane to HEIF image: err.message std::endl;heif_image_release(image);heif_context_free(ctx);return false;}// 获取指向HEIF图像数据的指针int stride;uint8_t* p heif_image_get_plane(image, heif_channel_interleaved, stride);// 将 cv::Mat 数据复制到 HEIF 图像中for (int y 0; y height; y) {memcpy(p y * stride, mat.ptr(y), width * 3); // 每行的像素数据都是 width * 3 个字节}//for (int y 0; y height; y) {// // 使用 size_t 来安全地计算偏移量 // size_t rowOffset static_castsize_t(y) * stride;// // 将偏移量转换为 char* 类型的指针偏移 // char* rowPtr reinterpret_castchar*(p) rowOffset;// // 使用 memcpy 复制数据 // memcpy(rowPtr, mat.ptruchar(y), width * 3); // 注意这里假设 mat.ptr 返回 uchar* // // 注意如果 mat.ptr 实际上返回的是其他类型的指针如 RGB 像素的 struct 或类 // // 你可能需要调整 memcpy 的第三个参数来匹配实际的字节大小。 //}创建并初始化heif_encoding_options结构体//struct heif_encoding_options encoding_options { 0 };//encoding_options.version 0;//encoding_options.save_alpha_channel false;//encoding_options.image_orientation heif_orientation_normal; // 例如设置图像方向为正常// 创建HEIF编码器struct heif_encoder* encoder;err heif_context_get_encoder_for_format(ctx, heif_compression_HEVC, encoder);if (err.code ! heif_error_Ok){std::cerr Error getting HEIF encoder: err.message std::endl;heif_image_release(image);heif_context_free(ctx);return false;}heif_encoder_set_lossy_quality(encoder, 80); //0-100 压缩比例heif_encoder_set_lossless(encoder, true); // True / Falseheif_encoder_set_logging_level(encoder, 4); // log信息详细程度0-4err heif_context_encode_image(ctx, image, encoder, nullptr, nullptr);if (err.code ! heif_error_Ok) {std::cerr Error encoding HEIF image: err.message std::endl;heif_encoder_release(encoder);heif_image_release(image);heif_context_free(ctx);return false;}err heif_context_write_to_file(ctx, filename);if (err.code ! heif_error_Ok) {std::cerr Error writing HEIF file: err.message std::endl;heif_encoder_release(encoder);heif_image_release(image);heif_context_free(ctx);return false;}heif_encoder_release(encoder);heif_image_release(image);heif_context_free(ctx);return true;
}bool GRAYMatToHeif(cv::Mat mat, const char* filename)
{// 确保输入的cv::Mat 是8位深度单通道的灰度图if (mat.empty() || mat.type() ! CV_8UC1) {std::cerr Invalid Mat format. Expected 8UC1. std::endl;return false;}struct heif_image* image;struct heif_context* ctx heif_context_alloc();struct heif_error err;int width mat.cols;int height mat.rows;// 创建HEIF图像err heif_image_create(width, height, heif_colorspace_monochrome, heif_chroma_monochrome, image);if (err.code ! heif_error_Ok) {std::cerr Error creating HEIF image: err.message std::endl;heif_context_free(ctx);return false;}// 添加一个用于灰度通道的图像平面err heif_image_add_plane(image, heif_channel_Y, width, height, 8);if (err.code ! heif_error_Ok) {std::cerr Error adding plane to HEIF image: err.message std::endl;heif_image_release(image);heif_context_free(ctx);return false;}// 获取指向HEIF图像灰度数据的指针int stride;uint8_t* p heif_image_get_plane(image, heif_channel_Y, stride);// 将cv::Mat 的灰度数据复制到HEIF图像中for (int y 0; y height; y) {memcpy(p y * stride, mat.ptr(y), width); // 每行的像素数据是 width 个字节}// 创建HEIF编码器struct heif_encoder* encoder;err heif_context_get_encoder_for_format(ctx, heif_compression_HEVC, encoder);if (err.code ! heif_error_Ok) {std::cerr Error getting HEIF encoder: err.message std::endl;heif_image_release(image);heif_context_free(ctx);return false;}heif_encoder_set_lossy_quality(encoder, 80); //0-100 压缩比例heif_encoder_set_lossless(encoder, true); // True / Falseheif_encoder_set_logging_level(encoder, 4); // log信息详细程度0-4err heif_context_encode_image(ctx, image, encoder, nullptr, nullptr);if (err.code ! heif_error_Ok) {std::cerr Error encoding HEIF image: err.message std::endl;heif_encoder_release(encoder);heif_image_release(image);heif_context_free(ctx);return false;}err heif_context_write_to_file(ctx, filename);if (err.code ! heif_error_Ok) {std::cerr Error writing HEIF file: err.message std::endl;heif_encoder_release(encoder);heif_image_release(image);heif_context_free(ctx);return false;}heif_encoder_release(encoder);heif_image_release(image);heif_context_free(ctx);return true;}cv::Mat HeifToRGBMat(const char* filename)
{// 创建HEIF上下文heif_context* ctx heif_context_alloc();heif_error error heif_context_read_from_file(ctx, filename, nullptr);if (error.code ! heif_error_Ok){std::cerr 读取heif文件失败 error.message std::endl;heif_context_free(ctx);return cv::Mat();}// 获取图像句柄heif_image_handle* handle;error heif_context_get_primary_image_handle(ctx, handle);if (error.code ! heif_error_Ok){std::cerr 获取图像句柄失败 error.message std::endl;heif_context_free(ctx);return cv::Mat();}// 解码图像heif_image* image;error heif_decode_image(handle, image, heif_colorspace_RGB, heif_chroma_interleaved_RGB, nullptr);if (error.code ! heif_error_Ok){std::cerr 解码图像失败 error.message std::endl;heif_image_handle_release(handle);heif_context_free(ctx);return cv::Mat();}// 获取图像宽度、高度和数据int width heif_image_get_width(image, heif_channel_interleaved);int height heif_image_get_height(image, heif_channel_interleaved);int stride;const uint8_t* data heif_image_get_plane_readonly(image, heif_channel_interleaved, stride);// 将图像数据复制到cv::Matcv::Mat mat(height, width, CV_8UC3);for (int y 0; y height; y) {memcpy(mat.ptr(y), data y * stride, width * 3);}cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB);//释放资源heif_image_release(image);heif_image_handle_release(handle);heif_context_free(ctx);return mat;
}cv::Mat HeifToGRAYMat(const char* filename)
{// 创建HEIF上下文heif_context* ctx heif_context_alloc();heif_error error heif_context_read_from_file(ctx, filename, nullptr);if (error.code ! heif_error_Ok) {std::cerr 读取HEIF文件失败: error.message std::endl;heif_context_free(ctx);return cv::Mat();}// 获取第一个图像句柄heif_image_handle* handle;error heif_context_get_primary_image_handle(ctx, handle);if (error.code ! heif_error_Ok) {std::cerr 获取图像句柄失败 error.message std::endl;heif_context_free(ctx);return cv::Mat();}// 解码图像heif_image* image;error heif_decode_image(handle, image, heif_colorspace_monochrome, heif_chroma_monochrome, nullptr);if (error.code ! heif_error_Ok) {std::cerr 解码图像失败: error.message std::endl;heif_image_handle_release(handle);heif_context_free(ctx);return cv::Mat();}// 获取图像宽度、高度和数据int width heif_image_get_width(image, heif_channel_Y);int height heif_image_get_height(image, heif_channel_Y);int stride;const uint8_t* data heif_image_get_plane_readonly(image, heif_channel_Y, stride);// 将图像数据复制到 cv::Matcv::Mat mat(height, width, CV_8UC1);for (int y 0; y height; y) {memcpy(mat.ptr(y), data y * stride, width);}cv::imwrite(C:\\Users\\Lenovo\\Desktop\\opencv_decode.png, mat);// 释放资源heif_image_release(image);heif_image_handle_release(handle);heif_context_free(ctx);return mat;
}int main()
{// RGBcv::Mat matRGB;cv::Mat matBGR cv::imread(C:\\Users\\Lenovo\\Desktop\\opencv.png);const char* rgbFilename C:\\Users\\Lenovo\\Desktop\\opencv.heif;const char* dstRgbFilename C:\\Users\\Lenovo\\Desktop\\opencv_decode.png;cv::cvtColor(matBGR, matRGB, cv::COLOR_BGR2RGB);bool isRGB RGBMatToHeif(matRGB, rgbFilename);matBGR HeifToRGBMat(rgbFilename);cv::imwrite(dstRgbFilename, matBGR);// GRAYcv::Mat matGRAY cv::imread(C:\\Users\\Lenovo\\Desktop\\opencv_gray.png, cv::IMREAD_GRAYSCALE);const char* grayFilename C:\\Users\\Lenovo\\Desktop\\opencv_gray.heif;const char* dstGrayFilename C:\\Users\\Lenovo\\Desktop\\opencv_gray_decode.png;bool isGRAY GRAYMatToHeif(matGRAY, grayFilename);cv::Mat dstMatGRAY HeifToGRAYMat(grayFilename);cv::imwrite(dstGrayFilename, dstMatGRAY);return 0;
}