opencv Mat To Heif
高效率图像文件格式(英语:High Efficiency Image File Format, HEIF;也称高效图像文件格式)是一个用于单张图像或图像序列的文件格式。它由运动图像专家组(MPEG)开发,并在MPEG-H Part 12(ISO/IEC 23008-12)中定义。
HEIF规范也定义了高效率视频编码(HEVC)编码的内嵌图像和HEVC编码的图像序列的存储方式,其中以受约束的方式应用帧间预测。
HEIF文件与ISO基本媒体文件格式(ISOBMFF,ISO/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 libheif
Linux/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 --preset=release .../configuremake
功能:cv::Mat 转 HEIF文件, HEIF文件转cv::Mat
```cpp
#include <libheif/heif.h>
#include <opencv2/opencv.hpp>
#include <iostream>bool 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_cast<size_t>(y) * stride;// // 将偏移量转换为 char* 类型的指针偏移 // char* rowPtr = reinterpret_cast<char*>(p) + rowOffset;// // 使用 memcpy 复制数据 // memcpy(rowPtr, mat.ptr<uchar>(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;
}
相关文章:
opencv Mat To Heif
高效率图像文件格式(英语:High Efficiency Image File Format, HEIF;也称高效图像文件格式)是一个用于单张图像或图像序列的文件格式。它由运动图像专家组(MPEG)开发,并在MPEG-H Part 12&#x…...
二刷代码随想录第24天
93. 复原 IP 地址 确定函数is_ip的实现细节,start不能超过end,没有0开头的非0数字,每个字符都在0-9之间,每段字符小于255在原字符串s上做操作会更简单一些 class Solution { public:vector<string> result;vector<string> rest…...
Java设计模式之状态模式架构高扩展的订单状态管理
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c=1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编程,高并发设计,Springboot和微服务,熟悉Linux,ESXI虚拟化以及云原生Docker和K8s…...

Yagmail邮件发送库:如何用Python实现自动化邮件营销?
目录 一、Yagmail简介 二、安装Yagmail 三、基本使用示例 1. 发送简单文本邮件 2. 发送HTML邮件 3. 发送带有附件的邮件 4. 多收件人处理 5. 自定义邮件头 四、高级功能 1. SMTP配置 2. 邮件模板 3. OAuth2认证 五、自动化邮件营销案例 六、错误处理和调试 七、…...
李宏毅深度学习-Pytorch Tutorial2
什么是张量? 张量(Tensor)是深度学习和机器学习中一个非常基础且重要的概念。在数学上,张量可以被看作是向量和矩阵的泛化。简单来说,张量是一种多维数组,它可以表示标量(0维)、向量…...

SaaS财务软件:赋能企业数字化转型
在数字化浪潮的推动下,企业财务管理正逐步迈向智能化、高效化的新阶段。在这个过程中,SaaS财务软件应运而生,成为许多企业的首选。以易舟云财务软件为例,这款软件不仅集成了众多先进的财务管理功能,而且在用户体验上做…...

FPGA实战篇(按键控制LDE实验)
1.按键简介 按键开关是一种电子开关,属于电子元器件类。我们的开发板上有两种按键开关:第一种是本实验所使用的轻触式按键开关,简称轻触开关。使用时以向开关的操作方向施加压力使内部电路闭合接通,当撤销压力时开关断开ÿ…...

在Ubuntu-22.04 [WSL2]中配置Docker
文章目录 0. 进入Ubuntu-22.041. 更新系统软件包2. 安装Docker相关依赖包3. 添加Docker官方GPG密钥4. 添加Docker软件源5. 安装Docker Engine5.1 更新软件包列表5.2 安装Docker相关软件包 6. 验证Docker安装是否成功6.1 查看Docker版本信息6.2 启动Docker6.3 配置镜像加速器6.4…...

ACM:均分纸牌
主要思路 整体思路概述: 本题旨在解决给定N堆纸牌(纸牌总数是N的倍数),通过按照特定移牌规则移动纸牌,找出用最少移动次数使每堆纸牌数量相等的方法。程序采用了一种逐步调整的思路,先计算出每堆纸牌应有的…...
ThreadFactory
ThreadFactory 是 Java 中一个用于创建线程的接口,它可以自定义线程的创建过程,例如线程的名称、优先级、是否为守护线程等。它是 java.util.concurrent 包的一部分,通常与线程池(ThreadPoolExecutor)一起使用。 线程…...

WEB开发: Node.js路由之由浅入深(一) - 全栈工程师入门
作为一个使用Node.js多年的开发者,我已经习惯于用Node.js写一些web应用来为工作服务,因为实现快速、部署简单、自定义强。今天我们一起来学习一个全栈工程师必备技能:web路由。(观看此文的前提是默认你已经装好nonde.js了…...

NES游戏机项目制作笔记(未完成)
24年12月1日晚记——在网上找项目学习的时候发现一个有意思的项目,准备靠这个应用一些STM32的高级功能。值得提醒的是——目的在于学习不可贪杯,注意效率 01 根据项目需求分析 为确保充分考虑每一个细节,并且让自己高效的完成项目制作&#…...

云服务器部署upload-labs-docker(文件上传靶场)环境 以及相关报错问题
环境的搭建 准备:云服务器(本地的linux服务器(版本最好不要是老的不然不兼容docker)) f8x配置docker环境: https://github.com/ffffffff0x/f8x 一键配置 docker拉取file-labs靶场 https://github.com…...

Elasticsearch入门之HTTP基础操作
RESTful REST 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是 RESTful。Web 应用程序最重要的 REST 原则是,客户端和服务器之间的交互在请求之间是无状态的。从客户端到服务器的每个请求都必须包含理解请求所必需的信息。如果服务器在…...

maven聚合项目部署到tomcat上
目录 一.聚合项目 1.检查无误后将项目打包 2.将这四个拷贝到tomcat的webapp下 二.启动tomcat 1.双击startup.bat 2.页面访问http://localhost:8080 3.打开webapp文件夹,发现多了三个文件夹 4.点进去才有要访问的index页面 5.再进行访问 解决: …...

基于Matlab生育模型和年龄别死亡率的未来人口预测与结构动态分析
人口预测在社会经济发展、政策规划以及资源分配中扮演着至关重要的角色,特别是在全球人口老龄化、少子化趋势日益显著的背景下,对人口增长规律及结构变化的研究愈发重要。人口结构的变化不仅直接影响劳动力供给和经济增长潜力,还对医疗、教育…...
公共服务 kkFileView 4.1 文件预览 Docker 一键部署
官方文档 https://kkview.cn/zh-cn/docs/production.html 镜像导入 # 网络环境方便访问docker中央仓库 docker pull keking/kkfileview:4.1.0# 网络环境不方便访问docker中央仓库 wget https://kkview.cn/resource/kkFileView-4.1.0-docker.tar docker load -i kkFileView-4…...

福昕PDF低代码平台
福昕PDF低代码平台简介 福昕PDF 低代码平台是一款创新的工具,旨在简化PDF处理和管理的流程。通过这个平台,用户可以通过简单的拖拽界面上的按钮,轻松完成对Cloud API的调用工作流,而无需编写复杂的代码。这使得即使没有编程经验的…...

Ubuntu环境安装RabbitMQ
1.安装Erlang RabbitMq需要Erlang语⾔的⽀持,在安装rabbitMq之前需要安装erlang # 更新软件包 sudo apt-get update # 安装 erlang sudo apt-get install erlang 查看erlang版本 : erl 退出命令:halt(). 2. 安装RabbitMQ # 更新软件包 sudo apt-get update # 安装 …...

集合ArrayList
黑马程序员Java的个人笔记 BV17F411T7Ao p111~p115 目录 集合存储数据类型的特点 创建对象 ArrayList 成员方法 .add 增加元素 .remove 删除元素 .set 修改元素 .get 查询元素 .size 获取长度 基本数据类型对应的包装类 Character 练习 返回多个数据 集合存储…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...

边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...

Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...

算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...

push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...