首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

鸿蒙HarmonyOS开发实战—多媒体开发(相机开发 二)

  • 25-02-22 03:41
  • 2404
  • 10056
blog.csdn.net
相机帧捕获

Camera操作类,包括相机预览、录像、拍照等功能接口。

接口名

描述

triggerSingleCapture​(FrameConfig frameConfig)

启动相机帧的单帧捕获。

triggerMultiCapture​(List frameConfigs)

启动相机帧的多帧捕获。

configure​(CameraConfig config)

配置相机。

flushCaptures​()

停止并清除相机帧的捕获,包括循环帧/单帧/多帧捕获。

getCameraConfigBuilder​()

获取相机配置构造器对象。

getCameraId​()

获取当前相机的ID。

getFrameConfigBuilder​(int type)

获取指定类型的相机帧配置构造器对象。

release​()

释放相机对象及资源。

triggerLoopingCapture​(FrameConfig frameConfig)

启动或者更新相机帧的循环捕获。

stopLoopingCapture​()

停止当前相机帧的循环捕获。

启动预览(循环帧捕获)

用户一般都是先看见预览画面才执行拍照或者其他功能,所以对于一个普通的相机应用,预览是必不可少的。启动预览的建议步骤如下:

1. 通过getFrameConfigBuilder(FRAME_CONFIG_PREVIEW)方法获取预览配置模板,常用帧配置项见下表,更多的帧配置项以及详细使用方法请参考API接口说明的FrameConfig.Builder部分。

接口名

描述

是否必选

addSurface(Surface surface)

配置预览surface和帧的绑定。

是

setAfMode(int afMode, Rect rect)

配置对焦模式。

否

setAeMode(int aeMode, Rect rect)

配置曝光模式。

否

setZoom(float value)

配置变焦值。

否

setFlashMode(int flashMode)

配置闪光灯模式。

否

setFaceDetection(int type, boolean isEnable)

配置人脸检测或者笑脸检测。

否

setParameter(Key key, T value)

配置其他属性(如自拍镜像等)。

否

setMark(Object mark)

配置一个标签,后续可以从FrameConfig中通过Object getMark()拿到标签,判断两个是否相等,相等就说明是同一个配置。

否

setCoordinateSurface(Surface surface)

配置坐标系基准Surface,后续计算Ae/Af等区域都会基于此Surface为基本的中心坐标系,不设置默认使用添加的第一个Surface。

否

2. 通过triggerLoopingCapture(FrameConfig)方法实现循环帧捕获(如预览/录像)。

  1. private final class CameraStateCallbackImpl extends CameraStateCallback {
  2. @Override
  3. public void onConfigured(Camera camera) {
  4. // 获取预览配置模板
  5. frameConfigBuilder = camera.getFrameConfigBuilder(FRAME_CONFIG_PREVIEW);
  6. // 配置预览Surface
  7. frameConfigBuilder.addSurface(previewSurface);
  8. previewFrameConfig = frameConfigBuilder.build();
  9. try {
  10. // 启动循环帧捕获
  11. int triggerId = camera.triggerLoopingCapture(previewFrameConfig);
  12. } catch (IllegalArgumentException e) {
  13. HiLog.error(LABEL, "Argument Exception");
  14. } catch (IllegalStateException e) {
  15. HiLog.error(LABEL, "State Exception");
  16. }
  17. }
  18. }

复制

经过以上的操作,相机应用已经可以正常进行实时预览了。在预览状态下,开发者还可以执行其他操作,比如:

当预览帧配置更改时,可以通过triggerLoopingCapture(FrameConfig)方法实现预览帧配置的更新;

  1. // 预览帧变焦值变更
  2. frameConfigBuilder.setZoom(1.2f);
  3. // 调用triggerLoopingCapture方法实现预览帧配置更新
  4. triggerLoopingCapture(frameConfigBuilder.build());

复制

通过stopLoopingCapture()方法停止循环帧捕获(停止预览)。

  1. // 停止预览帧捕获
  2. camera.stopLoopingCapture()

复制

实现拍照(单帧捕获)

拍照功能属于相机应用的最重要功能之一,而且照片质量对用户至关重要。相机模块基于相机复杂的逻辑,从应用接口层到器件驱动层都已经默认的做好了最适合用户的配置,这些默认配置尽可能地保证用户拍出的每张照片的质量。发起拍照的建议步骤如下:

1. 通过getFrameConfigBuilder(FRAME_CONFIG_PICTURE)方法获取拍照配置模板,并且设置拍照帧配置,如下表

接口名

描述

是否必选

FrameConfig.Builder addSurface(Surface)

实现拍照Surface和帧的绑定。

必选

FrameConfig.Builder setImageRotation(int)

设置图片旋转角度。

可选

FrameConfig.Builder setLocation(Location)

设置图片地理位置信息。

可选

FrameConfig.Builder setParameter(Key, T)

配置其他属性(如自拍镜像等)。

可选

2. 拍照前准备图像帧数据的接收实现

  1. // 图像帧数据接收处理对象
  2. private ImageReceiver imageReceiver;
  3. // 执行回调的EventHandler
  4. private EventHandler eventHandler = new EventHandler(EventRunner.create("CameraCb"));
  5. // 拍照支持分辨率
  6. private Size pictureSize;
  7. // 单帧捕获生成图像回调Listener
  8. private final ImageReceiver.IImageArrivalListener imageArrivalListener = new ImageReceiver.IImageArrivalListener() {
  9. @Override
  10. public void onImageArrival(ImageReceiver imageReceiver) {
  11. StringBuffer fileName = new StringBuffer("picture_");
  12. fileName.append(UUID.randomUUID()).append(".jpg"); // 定义生成图片文件名
  13. File myFile = new File(dirFile, fileName.toString()); // 创建图片文件
  14. imageSaver = new ImageSaver(imageReceiver.readNextImage(), myFile); // 创建一个读写线程任务用于保存图片
  15. eventHandler.postTask(imageSaver); // 执行读写线程任务生成图片
  16. }
  17. };
  18. // 保存图片, 图片数据读写,及图像生成见run方法
  19. class ImageSaver implements Runnable {
  20. private final Image myImage;
  21. private final File myFile;
  22. ImageSaver(Image image, File file) {
  23. myImage = image;
  24. myFile = file;
  25. }
  26. @Override
  27. public void run() {
  28. Image.Component component = myImage.getComponent(ImageFormat.ComponentType.JPEG);
  29. byte[] bytes = new byte[component.remaining()];
  30. component.read(bytes);
  31. FileOutputStream output = null;
  32. try {
  33. output = new FileOutputStream(myFile);
  34. output.write(bytes); // 写图像数据
  35. } catch (IOException e) {
  36. HiLog.error(LABEL, "save picture occur exception!");
  37. } finally {
  38. if (output != null) {
  39. try {
  40. output.close(); // 关闭流
  41. } catch (IOException e) {
  42. HiLog.error(LABEL, "image release occur exception!");
  43. }
  44. }
  45. myImage.release();
  46. }
  47. }
  48. }
  49. private void takePictureInit() {
  50. List<Size> pictureSizes = cameraAbility.getSupportedSizes(ImageFormat.JPEG); // 获取拍照支持分辨率列表
  51. pictureSize = getPictureSize(pictureSizes) // 根据拍照要求选择合适的分辨率
  52. imageReceiver = ImageReceiver.create(Math.max(pictureSize.width, pictureSize.height),
  53. Math.min(pictureSize.width, pictureSize.height), ImageFormat.JPEG, 5); // 创建ImageReceiver对象,注意create函数中宽度要大于高度;5为最大支持的图像数,请根据实际设置。
  54. imageReceiver.setImageArrivalListener(imageArrivalListener);
  55. }

复制

3. 通过triggerSingleCapture(FrameConfig)方法实现单帧捕获(如拍照)。

  1. private void capture() {
  2. // 获取拍照配置模板
  3. framePictureConfigBuilder = cameraDevice.getFrameConfigBuilder(FRAME_CONFIG_PICTURE);
  4. // 配置拍照Surface
  5. framePictureConfigBuilder.addSurface(imageReceiver.getRecevingSurface());
  6. // 配置拍照其他参数
  7. framePictureConfigBuilder.setImageRotation(90);
  8. try {
  9. // 启动单帧捕获(拍照)
  10. cameraDevice.triggerSingleCapture(framePictureConfigBuilder.build());
  11. } catch (IllegalArgumentException e) {
  12. HiLog.error(LABEL, "Argument Exception");
  13. } catch (IllegalStateException e) {
  14. HiLog.error(LABEL, "State Exception");
  15. }
  16. }

复制

为了捕获到质量更高和效果更好的图片,还可以在帧结果中实时监测自动对焦和自动曝光的状态,一般而言,在自动对焦完成,自动曝光收敛后的瞬间是发起单帧捕获的最佳时机。

实现连拍(多帧捕获)

连拍功能方便用户一次拍照获取多张照片,用于捕捉精彩瞬间。同普通拍照的实现流程一致,但连拍需要使用triggerMultiCapture(List frameConfigs)方法。

启动录像(循环帧捕获)

启动录像和启动预览类似,但需要另外配置录像Surface才能使用。

1. 录像前需要进行音视频模块的配置。

  1. private Source source; // 音视频源
  2. private AudioProperty.Builder audioPropertyBuilder; // 音频属性构造器
  3. private VideoProperty.Builder videoPropertyBuilder; // 视频属性构造器
  4. private StorageProperty.Builder storagePropertyBuilder; // 音视频存储属性构造器
  5. private Recorder mediaRecorder; // 录像操作对象
  6. private String recordName; // 音视频文件名
  7. private Size mRecordSize; // 录像分辨率
  8. private void initMediaRecorder() {
  9. videoPropertyBuilder.setRecorderBitRate(10000000); // 设置录制比特率
  10. int rotation = DisplayManager.getInstance().getDefaultDisplay(this).get().getRotation();
  11. videoPropertyBuilder.setRecorderDegrees(getOrientation(rotation)); // 设置录像方向
  12. videoPropertyBuilder.setRecorderFps(30); // 设置录制采样率
  13. videoPropertyBuilder.setRecorderHeight(Math.min(recordSize.height, recordSize.width)); // 设置录像支持的分辨率,需保证width > height
  14. videoPropertyBuilder.setRecorderWidth(Math.max(recordSize.height, recordSize.width));
  15. videoPropertyBuilder.setRecorderVideoEncoder(Recorder.VideoEncoder.H264); // 设置视频编码方式
  16. videoPropertyBuilder.setRecorderRate(30); // 设置录制帧率
  17. source.setRecorderAudioSource(Recorder.AudioSource.MIC); // 设置录制音频源
  18. source.setRecorderVideoSource(Recorder.VideoSource.SURFACE); // 设置视频窗口
  19. mediaRecorder.setSource(source); // 设置音视频源
  20. mediaRecorder.setOutputFormat(Recorder.OutputFormat.MPEG_4); // 设置音视频输出格式
  21. StringBuffer fileName = new StringBuffer("record_"); // 生成随机文件名
  22. fileName.append(UUID.randomUUID()).append(".mp4");
  23. recordName = fileName.toString();
  24. File file = new File(dirFile, recordName); // 创建录像文件对象
  25. storagePropertyBuilder.setRecorderFile(file); // 设置存储音视频文件名
  26. mediaRecorder.setStorageProperty(storagePropertyBuilder.build());
  27. audioPropertyBuilder.setRecorderAudioEncoder(Recorder.AudioEncoder.AAC); // 设置音频编码格式
  28. mediaRecorder.setAudioProperty(audioPropertyBuilder.build()); // 设置音频属性
  29. mediaRecorder.setVideoProperty(videoPropertyBuilder.build()); // 设置视频属性
  30. mediaRecorder.prepare(); // 准备录制
  31. HiLog.info(LABEL, "initMediaRecorder end");
  32. }

复制

2. 配置录像帧,启动录像

  1. private final class CameraStateCallbackImpl extends CameraStateCallback {
  2. @Override
  3. public void onConfigured(Camera camera) {
  4. // 获取录像配置模板
  5. frameConfigBuilder = camera.getFrameConfigBuilder(FRAME_CONFIG_RECORD);
  6. // 配置预览Surface
  7. frameConfigBuilder.addSurface(previewSurface);
  8. // 配置录像的Surface
  9. mRecorderSurface = mediaRecorder.getVideoSurface();
  10. frameConfigBuilder.addSurface(mRecorderSurface);
  11. previewFrameConfig = frameConfigBuilder.build();
  12. try {
  13. // 启动循环帧捕获
  14. int triggerId = camera.triggerLoopingCapture(previewFrameConfig);
  15. } catch (IllegalArgumentException e) {
  16. HiLog.error(LABEL, "Argument Exception");
  17. } catch (IllegalStateException e) {
  18. HiLog.error(LABEL, "State Exception");
  19. }
  20. }
  21. }

复制

相机设备释放

使用完相机后,必须通过release()来关闭相机和释放资源,否则可能导致其他相机应用无法启动。一旦相机被释放,它所提供的操作就不能再被调用,否则会导致不可预期的结果,或是会引发状态异常。

相机设备释放的示例代码如下:

  1. private void releaseCamera() {
  2. if (camera != null) {
  3. // 关闭相机和释放资源
  4. camera.release();
  5. camera = null;
  6. }
  7. // 拍照配置模板置空
  8. framePictureConfigBuilder = null;
  9. // 预览配置模板置空
  10. previewFrameConfig = null;
  11. }

最后,为了能让大家更好的去学习提升鸿蒙 (Harmony OS) 开发技术,小编连夜整理了一份30个G纯血版学习资料(含视频、电子书、学习文档等)以及一份在Github上持续爆火霸榜的《纯血版华为鸿蒙 (Harmony OS)开发手册》(共计890页),希望对大家有所帮助。

纯血版鸿蒙 HarmonyOS 4.0 视频学习资料

 需要以上视频学习资料小伙伴

请点击→纯血版全套鸿蒙HarmonyOS学习资料


《纯血版华为鸿蒙 (Harmony OS)开发手册》

这份手册涵盖了当前鸿蒙 (Harmony OS) 开发技术必掌握的核心知识点

纯血版鸿蒙 (Harmony OS)开发手册部分精彩内容

HarmonyOS 概念:

  • 系统定义
  • 技术架构
  • 技术特性
  • 系统安全

如何快速入门?

  • 基本概念
  • 构建第一个ArkTS应用
  • 构建第一个JS应用
  • ……


开发基础知识: 

  • 应用基础知识
  • 配置文件
  • 应用数据管理
  • 应用安全管理
  • 应用隐私保护
  • 三方应用调用管控机制
  • 资源分类与访问
  • 学习ArkTS语言
  • ……

基于ArkTS 开发:

  • Ability开发
  • UI开发
  • 公共事件与通知
  • 窗口管理
  • 媒体
  • 安全
  • 网络与链接
  • 电话服务
  • 数据管理
  • 后台任务(Background Task)管理
  • 设备管理
  • 设备使用信息统计
  • DFX
  • 国际化开发
  • 折叠屏系列
  • .……

获取以上文中提到的这份纯血版鸿蒙 (Harmony OS) 开发资料的小伙伴 

请点击→纯血版全套鸿蒙HarmonyOS学习资料


?写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing?,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新VIP学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料

注:本文转载自blog.csdn.net的蜀道山QAQ的文章"https://blog.csdn.net/shudaoshanQAQ/article/details/135723024"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top