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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/63270.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

内存管理面试常问

为什么要有虚拟内存&#xff1f; 虚拟内存 如果你是电⼦相关专业的&#xff0c;肯定在⼤学⾥捣⿎过单⽚机。 单⽚机是没有操作系统的&#xff0c;所以每次写完代码&#xff0c;都需要借助⼯具把程序烧录进去&#xff0c;这样程序才能跑起来。 另外&#xff0c; 单⽚机的 CPU …

PostgreSQL DISTINCT 关键字的使用与优化

PostgreSQL DISTINCT 关键字的使用与优化 PostgreSQL 是一种功能强大的开源对象关系数据库管理系统,广泛用于各种应用场景。在处理数据库查询时,我们经常需要从表中检索唯一的记录集合,这时就会用到 DISTINCT 关键字。本文将详细介绍 PostgreSQL 中 DISTINCT 关键字的使用方…

LSM Tree 底层设计理念

场景&#xff1a;设计一个海量读写的的kv数据库&#xff0c;优先保证写入速度&#xff0c;但是读取速度也不能很慢 因为海量数据存储&#xff0c;不能使用内存&#xff0c;得存到文件里。 Q&#xff1a;对已经落盘的文件&#xff0c;怎么根据key修改value A&#xff1a;读取文件…

Debezium日常分享系列之:Debezium Engine

Debezium日常分享系列之&#xff1a;Debezium Engine 依赖打包项目在代码中输出消息格式消息转换消息转换谓词高级记录使用引擎属性异步引擎属性数据库模式历史属性处理故障 Debezium连接器通常通过部署到Kafka Connect服务来运行&#xff0c;并配置一个或多个连接器来监视上游…

MongoDB分片集群搭建及扩容

分片集群搭建及扩容 整体架构 环境准备 3台Linux虚拟机&#xff0c;准备MongoDB环境&#xff0c;配置环境变量。一定要版本一致&#xff08;重点&#xff09;&#xff0c;当前使用 version4.4.9 配置域名解析 在3台虚拟机上执行以下命令&#xff0c;注意替换实际 IP 地址 e…

Pynsist 打包应用 和 PyWebIO 构建Web 应用

Pynsist&#xff1a;一键打包Python 应用代码为Windows 安装程序。 项目地址&#xff1a; https://github.com/takluyver/pynsist PyWebIO&#xff1a;为Python 开发者提供了一种快速、简洁的方式来创建Web 应用&#xff0c;无需学习前端技术 项目地址&#xff1a;https://g…

【HarmonyOS】层级轮播卡片效果

【HarmonyOS】层级轮播卡片效果 一、功能效果&#xff1a; 1.上下堆叠由大到小的卡片层叠效果。 2.上层卡片可手势左右滑动&#xff0c;自动左滑动。 3.三层卡片随滑动&#xff0c;内容进行依次切换。 二、开发思路 【完整代码见章节三】 1.最上层使用swiper进行轮播效果…

Python_Flask02

所有人都不许学Java了&#xff0c;都来学Python&#xff01; 如果不来学的话请网爆我的老师 连接前的准备 安装pymysql 和 flask_sqlalchemy&#xff0c;安装第三下面两个所需要的包才能连接上数据库 pip install pymysql pip install flask_sqlalchemy pymysql是一个Pyth…

实验13 使用预训练resnet18实现CIFAR-10分类

1.数据预处理 首先利用函数transforms.Compose定义了一个预处理函数transform&#xff0c;里面定义了两种操作&#xff0c;一个是将图像转换为Tensor&#xff0c;一个是对图像进行标准化。然后利用函数torchvision.datasets.CIFAR10下载数据集&#xff0c;这个函数有四个常见的…

区块链概念 Web 3.0 实操

1. Web 3.0 概述 1.1 定义与背景 Web 3.0&#xff0c;也称为第三代互联网&#xff0c;是一个新兴的概念&#xff0c;它代表着互联网的未来发展和演进方向。Web 3.0的核心理念是去中心化、用户主权和智能化。这一概念的提出&#xff0c;旨在解决Web 2.0时代中用户数据隐私泄露…

linux下使用gdb运行程序,查看程序崩溃原因

1.什么是gdb? gdb 是 GNU Debugger 的缩写&#xff0c;是一个功能强大的用于调试程序的开源调试器工具。它可以帮助开发人员诊断和解决程序中的错误、跟踪程序执行过程、查看变量的值等。gdb 支持多种编程语言&#xff0c;包括 C、C、Objective-C、Fortran 等&#xff0c;并可…

鸿蒙arkts怎么打印一个方法的调用堆栈

做鸿蒙开发的时候&#xff0c;也想看一下一个方法到底是哪里调用的&#xff0c;工程太大&#xff0c;断点太麻烦&#xff0c;可以加堆栈日志。 在你的方法中加上这两句&#xff0c;就可以跟到堆栈日志 let err new Error() console.log(>>>>>>err.stack) …

Elasticsearch scroll 之滚动查询

Elasticsearch scroll 之滚动查询 Elasticsearch 的 Scroll API 是一种用于处理大规模数据集的机制&#xff0c;特别是在需要从索引中检索大量数据时。通常情况下&#xff0c;Elasticsearch 的搜索请求会有一个结果集大小的限制 (fromsize 的检索数量默认是 10,000 条记录)&am…

【漏洞复现】网动统一通信平台(ActiveUC)接口iactiveEnterMeeting存在信息泄露漏洞

🏘️个人主页: 点燃银河尽头的篝火(●’◡’●) 如果文章有帮到你的话记得点赞👍+收藏💗支持一下哦 @TOC 一、漏洞概述 1.1漏洞简介 漏洞名称:网动统一通信平台(ActiveUC)接口iactiveEnterMeeting存在信息泄露漏洞漏洞编号:无漏洞类型:信息泄露漏洞威胁等级:高危影…

掌握小程序地理位置服务插件,让用户体验再升级

在小程序开发中&#xff0c;地理位置服务插件扮演着至关重要的角色&#xff0c;它们不仅能够帮助开发者轻松获取用户的地理位置信息&#xff0c;还能够基于位置数据提供丰富的功能&#xff0c;如地图展示、周边搜索、路径规划等。 一、插件的基本概念与引入 插件定义&#xf…

IDE如何安装插件实现Go to Definition

项目背景 框架&#xff1a;Cucumber Cypress 语言&#xff1a;Javascript IDE&#xff1a;vscode 需求 项目根目录cypress-automation的cypress/integration是测试用例的存放路径&#xff0c;按照不同模块不同功能创建了很多子目录&#xff0c;cucumber测试用例.feature文…

如何通过 Windows 自带的启动管理功能优化电脑启动程序

在日常使用电脑的过程中&#xff0c;您可能注意到开机后某些程序会自动运行。这些程序被称为“自启动”或“启动项”&#xff0c;它们可以在系统启动时自动加载并开始运行&#xff0c;有时甚至在后台默默工作。虽然一些启动项可能是必要的&#xff08;如杀毒软件&#xff09;&a…

探索自然语言处理奥秘(NLP)

摘要 自然语言处理&#xff08;NLP&#xff09;是人工智能领域的一个重要分支&#xff0c;它致力于使计算机能够理解、解释和生成人类语言。这项技术让机器能够阅读文本、听懂语音&#xff0c;并与人类进行基本的对话交流。 通俗理解 自然语言处理&#xff08;NLP&#xff09…

html ul li 首页渲染多条数据 但只展示八条,其余的数据全部隐藏,通过icon图标 进行展示

<div style"float: left;" id"showMore"> 展开 </div> <div style"float: left;“id"hideLess"> 收起 </div> var data document.querySelectorAll(.allbox .item h3 a); const list document.querySelectorAl…

# issue 8 TCP内部原理和UDP编程

TCP 通信三大步骤&#xff1a; 1 三次握手建立连接; 2 开始通信&#xff0c;进行数据交换; 3 四次挥手断开连接&#xff1b; 一、TCP内部原理--三次握手 【第一次握手】套接字A∶"你好&#xff0c;套接字B。我这儿有数据要传给你&#xff0c;建立连接吧。" 【第二次…