# NativeImageDemo **Repository Path**: scenario-samples/native-image-demo ## Basic Information - **Project Name**: NativeImageDemo - **Description**: 【鸿蒙 Harmony Next 示例 代码】本示例基于OpenGL渲染实现Lut滤镜相机场景 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 4 - **Forks**: 1 - **Created**: 2025-03-28 - **Last Updated**: 2025-09-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 基于OpenGL渲染实现Lut滤镜相机 ### 介绍 C++侧录制渲染,ArkTs侧UI展示和接口功能 1. 预览:NDKCamera() 2. 渲染:RenderThread() 3. 取帧:glReadPixels() ### 效果预览 ![image](entry/src/main/resources/base/media/demo_LutCamera.gif) ### 约束限制 1. 本示例仅支持标准系统上运行,支持设备:华为手机。 2. HarmonyOS系统:HarmonyOS NEXT Release及以上。 3. DevEco Studio版本:DevEco Studio 5.0.0 Release及以上。 4. HarmonyOS SDK版本:HarmonyOS 5.0.0 Release SDK及以上。 ### 使用说明 1. 预览:相机、设备、渲染器、管理器、窗口、初始化并开启 2. 渲染:渲染线程进入渲染主循环,额外线程开启lut上传、任务信号、绑定纹理、输出滤镜 3. 录制:渲染线程进入渲染主循环,录制线程进入录制循环 4. 拍照:渲染线程进入渲染主循环,额外线程开启帧输出 5. 保存:photoAccessHelper保存,SaveButton获取权限 ### 权限申请 1. ohos.permission.CAMERA ### 实现思路 1. 初始化: 1) 获取环境XComponent对象和id,绑定nativeXComponent、render,注册回调,暴露接口 2. 预览程序主流程: 1) 获取render实例,渲染线程获取到nativeImageSurfaceid后,相机配置初始化并开启预览流 3. 渲染程序主流程: 1) 渲染线程初始化开启进入渲染主循环,初始化eglcontext、垂直同步、帧画面nativeimage生成并监听,根据条件封锁等待唤醒信号,主线程继续执行,nativexcomponent注册回调,回调自动获取window,window初始化eglsurface,eglsurface关联eglcontext,可获取eglsurfaceid,eglcontext配置egl渲染程序、矩阵 4. 录制程序主流程: 1) 获取render实例,配置视频格式,创建编码Surface,开始录制,进入录制主循环 5. 获取渲染帧图像: 1) glReadPixels获取帧数据 2) 线程间获取图片先后顺序:渲染获取图片顺序后于执行任务顺序,导致当前任务无法获得当前渲染图,需要设置条件锁(线程和锁解决当前图片为最新获取图片) 3) 图片数据、宽高可以获取到,但传回arkts侧一直接收不到(去除解码再编码步骤,image.createPixelMap直接把arraybufer转pixelmap解决) 4) 图像上下颠倒、重复多次、花屏(数据上下倒转解决) 5) 图片能正常获取到,渲染颜色混乱,滤镜之外带有额外滤镜颜色偏蓝紫(rb通道互换解决) 6) 图片右侧部分空白,图片宽高倒转(原为屏幕宽高,录制宽高对调为录制高宽解决) ### 参考项目 1. 预览渲染支持算法:https://gitee.com/scenario-samples/open-gl 2. 视频录制和播放:https://gitee.com/harmonyos_samples/AVCodecVideo 3. 安卓lut滤镜文件转换纹理途径:https://blog.csdn.net/wangyantaozzu/article/details/103768611 4. LUT滤镜算法解析:https://blog.csdn.net/katherine_qj/article/details/112666379 5. 图片(lut)数据加载纹理:https://blog.csdn.net/s12117719679/article/details/144869409 6. 图像加载器:https://blog.csdn.net/github_27263697/article/details/143647456 ### 工程结构 ``` ├─entry/src/main/cpp │ ├─camera │ │ ├─ndk_camera.cpp // 相机功能页 │ │ └─ndk_camera.h │ ├─capbilities │ │ ├─include │ │ │ ├─demuxer.h │ │ │ ├─muxer.h │ │ │ ├─video_decoder.h │ │ │ └─video_encoder.h │ │ ├─demuxer.cpp // 解复用器功能页 │ │ ├─muxer.cpp // 复用器功能页 │ │ ├─video_decoder.cpp // 解码功能页 │ │ └─video_encoder.cpp // 编码功能页 │ ├─common │ │ ├─dfx │ │ │ ├─error │ │ │ │ └─av_codec_sample_error.h // 错误页 │ │ │ └─log │ │ │ └─av_codec_sample_log.h // 日志页 │ │ ├─common.h // 作用域配置页 │ │ ├─sample_callback.cpp // 回调功能页 │ │ ├─sample_callback.h │ │ └─sample_info.h // 回调信息页 │ ├─manager │ │ ├─plugin_manager.cpp // 管理器功能页 │ │ └─plugin_manager.h │ ├─render │ │ ├─egl_render_context.cpp // 渲染内容页 │ │ ├─egl_render_context.h │ │ ├─plugin_render.cpp // 渲染器功能页 │ │ ├─plugin_render.h │ │ ├─render_thread.cpp // 渲染线程功能页 │ │ ├─render_thread.h │ │ ├─shader_program.cpp // 渲染程序功能页 │ │ └─shader_program.h │ ├─sample │ │ ├─player │ │ │ ├─Player.cpp // 播放功能页 │ │ │ └─Player.h │ │ └─recorder │ │ ├─Recorder.cpp // 录制功能页 │ │ └─Recorder.h │ ├─types │ │ └─libentry │ │ ├─index.d.ets │ │ └─oh-package.json5 // 依赖配置页 │ ├─CMakeLists.txt // 构建配置页 │ └─main.cpp // 接口配置页 │ ├─entry/src/main/ets │ ├─common │ │ ├─Constants.ets // 常量页 │ │ └─DisplayCalculator.ets // 设备页 │ ├─components │ │ └─KComponentView.ets // 功能页 │ ├─entryability │ │ └─EntryAbility.ets // 启动页 │ ├─interface │ │ └─XComponentContext.ets // 接口页 │ └─pages │ └─Index.ets // 主页 ├─entry/src/main │ └─module.json5 // 模块权限配置信息 ``` ### 项目依赖 无 ### ChangeLog 1. 修改内容(时间):初始版本(2025.3.19) 2. 修改内容(时间):大小写和方法规范,使用安全控件,参考项目和实现思路拆分和完善(2025.3.24) 3. 内存释放、闪退、异常相关: 1)闪退:lut滤镜上传渲染两分钟左右程序崩溃,删除每次新生成纹理ID:GLuint texture,更换为固定纹理ID:glGenTextures(1, &lutTexId_),更改后渲染五分钟程序未出现崩溃(25.4.1) 2)内存释放:arkts侧new对象,初始化创建对象只生成一次,方法调用创建对象,正常情况下,当前对象需要使用,之前对象会失去引用被垃圾回收 3)内存释放:native侧new对象,初始化创建对象,实例绑定id,根据id增删改查实例,线程循环内创建对象同初始化创建对象一致,创建唯一变量绑定,避免循环生成速度大于垃圾回收速度造成崩溃 4)空指针异常:DestroyEglSurface新增判断条件,避免多线程前销毁后空指针异常 5)拍照卡顿:耗时操作阻塞渲染线程,考虑主线程继续渲染帧画面,耗时操作移交任务线程处理即arkts端传来取帧信号的此任务线程,数据最后获取到返回arkts侧及后续操作(25.5.22) ## 一份简单的问卷反馈 亲爱的Harmony Next开发者,您好!
为了协助您高效开发,提高鸿蒙场景化示例的质量,希望您在浏览或使用后抽空填写一份简单的问卷,我们将会收集您的宝贵意见进行优化:heart: [:arrow_right: **点击此处填写问卷** ](https://wj.qq.com/s2/19042938/95ab/)