Keepsake——拾刻相机的鸿蒙原生影像实践

3640 字
18 分钟
Keepsake——拾刻相机的鸿蒙原生影像实践

Keepsake 的中文名是“拾刻相机”。它是一款面向 HarmonyOS 的原生影像应用,目标不是做一个只负责按下快门的相机,而是把拍摄、色彩、票根排版、动态照片和本地整理放进同一条创作链路。

这类应用的难点不只在 UI。相机预览需要和设备能力、屏幕方向、镜头切换保持一致;拍摄结果需要在应用自己的图库中稳定保存;票根和色卡要同时作用于静态图片和动态照片;用户还希望在导出前继续编辑,而不是每次都重新拍摄。Keepsake 的工程结构正是围绕这些边界拆开的。

技术栈概览#

方向项目实现
运行平台HarmonyOS,兼容 SDK 6.1.0(23),目标 SDK 6.1.1(24)
开发语言ArkTS / ETS
应用模型Stage 模型,入口为 EntryAbility
UI 框架ArkUI 声明式 UI、HdsNavigation、系统 Symbol、半模态面板
相机能力@kit.CameraKit,预览流、拍照、镜头位置、变焦和相机状态管理
影像能力@kit.ImageKit、@kit.MediaLibraryKit、PixelMap 与图像资源读写
本地数据@kit.ArkData preferences,保存设置、色卡和图库轻量元数据
文件管理应用沙箱 filesDir/gallery,照片本体与元数据分开处理
动态照片Moving Photo 导出与 native transcoding bridge

项目入口模块是 entry。源码主要分成页面、模型、组件和数据存储四层:页面负责交互,模型负责相机和影像流程,组件负责票根与预览的组合渲染,Store 类负责把可恢复的数据写入本地。

应用定位:从拍摄到成片#

拾刻相机的核心链路可以概括为:

相机预览
↓
拍摄静态照片或动态照片
↓
实时色卡与影像参数
↓
票根模板、地点、时间和设备信息
↓
应用内图库
↓
编辑、调色、保存或导出

这个流程把“拍摄”和“整理”连接起来。拍完的照片先进入应用自己的图库,用户可以稍后重新选择票根、修改调色、调整分享背景,再决定是否写入系统相册。

核心模块#

1. CameraPage:统一承载拍摄工作台#

CameraPage.ets 是应用最复杂的页面,它同时管理取景、拍摄、底部控制栏、票根预览、色卡面板和图库入口。页面没有把每个功能拆成互不相关的页面,而是用面板模式区分 CONTROLS、COLOR_PRESETS、COLOR_EDITOR 和 TEMPLATES,让用户在同一取景上下文中完成调整。

CameraModel.ets 则把相机生命周期从页面中抽出来,负责创建相机输入、预览输出和拍照输出,并向页面提供当前镜头、变焦范围和运行状态。这样做的好处是:页面只关心“当前能不能拍”和“用户选择了什么”,相机资源的创建、释放和异常处理集中在模型层。

项目在模块配置中声明了相机、麦克风、定位和网络权限。定位能力用于补充票根中的地点信息,麦克风权限用于动态照片相关的声音场景;具体权限仍然由系统在运行时授予,应用不能绕过用户授权。

2. 色卡系统:把参数化调色变成可保存配置#

色卡不是几张静态滤镜图片。ColorCardProfile 中保存了色温、色调、饱和度、强度、对比度、褪色、颗粒和暗角等参数,同时还包含色卡分类、配方编号和预览资源。

ColorCardStore 负责内置色卡和用户自定义色卡的读取、校验、归一化与持久化。应用启动时会过滤已经退役的旧预设,避免历史 preferences 中的旧数据被误认为是用户自定义内容重新出现。这是一个很小但很重要的数据迁移细节:资源版本变化时,持久化数据也必须跟着升级。

取景阶段使用 ColorTextureOverlay 等组件呈现实时效果,导出阶段则把相同的调色参数传给图片或动态视频处理流程。预览参数与最终结果共用一份配置,能够减少“预览看起来是一个效果,保存后变成另一个效果”的偏差。

3. 票根模板:结构化生成,而不是把文字画死#

TicketTemplate.ets 用数据结构描述票根:图片区域、画布比例、标题、页脚、条码、打孔线、颜色和圆角都由模板字段定义。模板包括横版票根、竖版旅行邮票、拍立得、地图和液态玻璃等风格。

模板渲染时,应用会把城市、日期、时间、序列号、设备型号和自定义文字组装成 TicketVariables,再交给 TicketOverlay 或 PhotoPrintOverlay 绘制。这样一来,模板本身是可复用的,动态信息也不会被写死在图片资源里。

票根编辑页和取景页共用模板注册表,因此用户可以在设置页指定默认票根,也可以在拍摄现场临时切换。对于不同画幅,项目还维护了照片槽的裁切比例和输出比例,避免照片被简单拉伸。

4. 动态照片:静态封面与视频轨道一起处理#

动态照片是 Keepsake 中最有工程挑战的一部分。静态封面可以直接生成票根图层,但视频部分需要逐帧叠加相同的图片槽、色彩参数和透明票根层。

MovingPhotoVideoComposer.ets 的处理流程大致如下:

  1. 读取动态照片封面、票根透明图层和视频输入文件。
  2. 把封面和叠加层解码为统一尺寸的 RGBA 像素数据。
  3. 将照片区域、票根区域、圆角、色温、饱和度、颗粒等参数传入 native transcoding bridge。
  4. 输出新的 MP4,并检查文件是否真实生成且大小大于零。
  5. 关闭文件、释放 ImageSource 和 PixelMap,避免长时间使用相机后出现资源泄漏。

代码中还对动态照片的图片路径、视频路径和 URI 做了区分。应用沙箱文件路径用于写入内容,fileUri 用于资源引用,二者不能混用。这个边界处理直接影响动态照片能否被正确导出。

5. 应用内图库:元数据与文件本体分离#

GalleryStore.ets 的设计是“轻量元数据 + 应用沙箱文件”。图库记录会保存照片路径、是否为动态照片、票根模板、地点、时间、设备型号、调色参数、分享背景和导出状态;照片本体则复制到 filesDir/gallery,避免把重要文件放在可能被系统清理的 cache 目录里。

图库页面支持预览、编辑、重新调色、删除和保存到系统相册。对于动态照片,页面需要同时管理静态封面和视频资源,播放时再根据记录中的参数还原对应的预览效果。

数据流与模块边界#

CameraPage
├─ CameraModel 相机输入、预览输出、拍照输出
├─ ColorCardStore 内置色卡与用户色卡
├─ TicketTemplate 票根模板与动态变量
├─ TicketOverlay ArkUI 票根图层
└─ GalleryStore 文件路径、元数据、导出状态
├─ Preferences 设置与色卡数据
└─ filesDir/gallery 照片与动态照片文件

这个边界让影像链路更容易维护:相机模型不需要知道图库列表如何显示,图库也不需要重新创建相机会话;色卡只负责描述参数,模板只负责描述版式,最终由页面或导出器把它们组合起来。

项目中用到的华为开发者文档#

下面的链接对应项目实际使用到的 HarmonyOS 能力。文档链接优先指向华为开发者官网,API 版本和设备支持范围应以打开页面时的最新说明为准。

CameraPage.etsCameraModel.ets

相机管理、预览、拍照、镜头与对焦

photoAccessHelperMovingPhoto

相册访问、媒体资产和动态照片

HdsNavigationHdsTabs

页面导航、系统组件和移动端交互

ColorCardStoreGalleryStore

Preferences、本地文件与图片处理

界面展示#

下面的图片来自拾刻相机的项目素材。它们按功能拆成横向卡片,桌面端可以横向滚动,移动端可以左右滑动查看。

01 / 拍摄

随手拍,实时生成专属票根

拍摄页把取景、变焦、拍照和票根预览放在同一工作台中。底部保留图库与镜头切换入口,用户可以先确定构图,再决定是否套用票根。

拾刻相机拍摄页和票根预览
图片 1:拍摄页、取景框、变焦与票根预览
02 / 调色

XIMAGE 风格卡片

色卡被设计成可直接点选的成像配方,而不是单纯的滤镜名称。原色、自然、明艳、明快等预设可以在取景阶段即时切换。

拾刻相机 XIMAGE 风格调色界面
图片 2:XIMAGE 风格与实时色彩预览
03 / 模板

多款票根样式

票根模板通过统一数据结构描述照片槽、比例、文字、条码和装饰。这样既可以保留统一的编辑体验,也能持续增加新的旅行票、拍立得和胶片风格。

拾刻相机多款票根样式选择界面
图片 3:横版票根、模板预览和选中状态
04 / 图库

先保存到应用图库,再决定是否导出

应用图库承接拍摄后的照片和动态照片,提供编辑、调色、删除和保存入口。作品不会因为还没有导出到系统相册就失去后续编辑能力。

拾刻相机应用图库界面
图片 4:拾刻图库与作品操作栏
05 / 设置

把常用拍摄偏好集中管理

相机设置页可以指定默认票根、默认焦段、色卡入口和自拍镜像行为。设置被持久化后,下一次打开相机即可恢复常用工作方式。

拾刻相机设置页
图片 5:默认票根、焦段和自拍镜像设置
06 / 色卡编辑

实时预览并保存自己的色卡

用户可以在预览图上观察色温、饱和度等参数的变化,并把一套调整结果保存为个人色卡。预设和自定义配置共用同一套数据模型。

拾刻相机自定义色卡界面
图片 6:自定义色卡与实时预览

技术总结#

拾刻相机的技术特点,不是把多个系统能力简单堆在一个页面里,而是给每种能力划定了清晰的边界:Camera Kit 负责采集,色卡负责参数,票根模板负责版式,图库负责生命周期,导出器负责把它们合成为最终作品。

项目还体现了鸿蒙原生开发的几个典型问题:权限需要在合适的时机申请;设备能力不能假设所有机型都相同;预览、拍照和导出要考虑方向与画幅;文件路径和 URI 需要区分;长时间使用相机和图片资源时必须主动释放对象。

对于个人影像应用来说,本地优先的设计也很合适。照片和动态照片保存在应用沙箱,设置和色卡保存为本地 preferences,用户不需要注册服务器账号就能完成完整的拍摄和整理流程。

拾刻相机把拍摄、调色和记录生活的过程,收进了一个可以继续生长的原生应用里。

一张照片按下快门的时间很短,真正留下来的,却是那一刻的光线、地点和心情。愿每次打开图库时,旧日的风也还能从画面里吹出来。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Keepsake——拾刻相机的鸿蒙原生影像实践
https://lifepeace.cloud/posts/keepsake-harmonyos-native-camera/
作者
Pinero
发布于
2026-09-24
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
Pinero
一个2.5次元的菠萝不吹雪
公告
带我去些你所爱的时刻
分类
标签
站点统计
文章
4
分类
2
标签
5
总字数
25,140
运行时长
0 天
最后活动
0 天前

文章目录