#HarmonyOS NEXT 体验官#使用相机服务开发相机应用 原创

不爱吃糖的程序媛
发布于 2024-7-30 11:05
浏览
0收藏

使用相机服务开发相机应用

今天我们通过调用Camera Kit(相机服务)提供的接口来开发相机应用,通过访问和操作相机硬件,实现基础操作,如预览、拍照和录像;还可以通过接口组合完成更多操作,如控制闪光灯和曝光时间、对焦或调焦等。

接下来我们看一下如何实现。

相机应用开发的主要流程包含开发准备、设备输入、会话管理、预览、拍照和录像等。

在开发相机应用时,需要先申请相机相关权限,确保应用拥有访问相机硬件及其他功能的权限,需要的权限如下表。

权限名 说明 授权方式
ohos.permission.CAMERA 允许应用使用相机拍摄照片和录制视频。 user_grant
ohos.permission.MICROPHONE 允许应用使用麦克风(可选)。 如需同时录制音频,需要申请该权限。 user_grant
ohos.permission.WRITE_MEDIA 允许应用读写用户外部存储中的媒体文件信息(可选)。 user_grant
ohos.permission.READ_MEDIA 允许应用读取用户外部存储中的媒体文件信息(可选)。 user_grant
ohos.permission.MEDIA_LOCATION 允许应用访问用户媒体文件中的地理位置信息(可选)。 user_grant

这个时候如果开发者仅是需要拉起系统相机拍摄一张照片、录制一段视频,可直接使用CameraPicker,无需申请相机权限,直接拉起系统相机完成拍摄。

import { cameraPicker as picker } from '@kit.CameraKit';
import { camera } from '@kit.CameraKit';
import { common } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
let mContext = getContext(this) as common.Context;

async function demo() {
  try {
    let pickerProfile: picker.PickerProfile = {
      cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK
    };
    let pickerResult: picker.PickerResult = await picker.pick(mContext,
      [picker.PickerMediaType.PHOTO, picker.PickerMediaType.VIDEO], pickerProfile);
    console.log("the pick pickerResult is:" + JSON.stringify(pickerResult));
  } catch (error) {
    let err = error as BusinessError;
    console.error(`the pick call failed. error code: ${err.code}`);
  }
}

效果

#HarmonyOS NEXT 体验官#使用相机服务开发相机应用-鸿蒙开发者社区

接下来看一下上面的权限是如何申明的

 {
        "name": "ohos.permission.CAMERA",
        "reason": "$string:EntryAbility_desc",
        "usedScene": {
          "abilities": [
            "FormAbility"
          ],
          "when": "always"
        }
      }

手动申请权限

let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
let context: Context = getContext(this) as common.UIAbilityContext;
atManager.requestPermissionsFromUser(context, ['ohos.permission.CAMERA'],
  (err: BusinessError, data: PermissionRequestResult) => {
    if (err) {
      console.error(`requestPermissionsFromUser fail, err->${JSON.stringify(err)}`);
    } else {
      console.info('data:' + JSON.stringify(data));
      console.info('data permissions:' + data.permissions);
      console.info('data authResults:' + data.authResults);
      console.info('data dialogShownResults:' + data.dialogShownResults);
    }
  });

最后看一下上面的开发模型。

开发模型

相机调用摄像头采集、加工图像视频数据,精确控制对应的硬件,灵活输出图像、视频内容,满足多镜头硬件适配(如广角、长焦、TOF)、多业务场景适配(如不同分辨率、不同格式、不同效果)的要求。

相机的工作流程如图所示,可概括为相机输入设备管理、会话管理和相机输出管理三部分。

  • 相机设备调用摄像头采集数据,作为相机输入流。
  • 会话管理可配置输入流,即选择哪些镜头进行拍摄。另外还可以配置闪光灯、曝光时间、对焦和调焦等参数,实现不同效果的拍摄,从而适配不同的业务场景。应用可以通过切换会话满足不同场景的拍摄需求。
  • 配置相机的输出流,即将内容以预览流、拍照流或视频流输出。

图1 相机工作流程 #HarmonyOS NEXT 体验官#使用相机服务开发相机应用-鸿蒙开发者社区

了解相机工作流程后,就可以更好地开发相机应用啦。

图2 相机开发模型 #HarmonyOS NEXT 体验官#使用相机服务开发相机应用-鸿蒙开发者社区

相机应用通过控制相机,实现图像显示(预览)、照片保存(拍照)、视频录制(录像)等基础操作。在实现基本操作过程中,相机服务会控制相机设备采集和输出数据,采集的图像数据在相机底层的设备硬件接口(HDI,Hardware Device Interfaces),直接通过BufferQueue传递到具体的功能模块进行处理。BufferQueue在应用开发中无需关注,用于将底层处理的数据及时送到上层进行图像显示。

以视频录制为例进行说明,相机应用在录制视频过程中,媒体录制服务先创建一个视频Surface用于传递数据,并提供给相机服务,相机服务可控制相机设备采集视频数据,生成视频流。采集的数据通过底层相机HDI处理后,通过Surface将视频流传递给媒体录制服务,媒体录制服务对视频数据进行处理后,保存为视频文件,完成视频录制。

完整源码

import { abilityAccessCtrl, Context, PermissionRequestResult, common } from '@kit.AbilityKit';

import { cameraPicker as picker } from '@kit.CameraKit';
import { camera } from '@kit.CameraKit';
import { BusinessError } from '@kit.BasicServicesKit';

let mContext = getContext(this) as common.Context;

async function pickerPhoto() {
  try {
    let pickerProfile: picker.PickerProfile = {
      cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK
    };
    let pickerResult: picker.PickerResult = await picker.pick(mContext,
      [picker.PickerMediaType.PHOTO, picker.PickerMediaType.VIDEO], pickerProfile);
    console.log("the pick pickerResult is:" + JSON.stringify(pickerResult));
  } catch (error) {
    let err = error as BusinessError;
    console.error(`the pick call failed. error code: ${err.code}`);
  }
}

@Entry
@Component
struct CameraPage {
  @State message: string = 'Hello World';

  aboutToAppear(): void {

    let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
    let context: Context = getContext(this) as common.UIAbilityContext;
    atManager.requestPermissionsFromUser(context, ['ohos.permission.CAMERA'],
      (err: BusinessError, data: PermissionRequestResult) => {
        if (err) {
          console.error(`requestPermissionsFromUser fail, err->${JSON.stringify(err)}`);
        } else {
          console.info('data:' + JSON.stringify(data));
          console.info('data permissions:' + data.permissions);
          console.info('data authResults:' + data.authResults);
          console.info('data dialogShownResults:' + data.dialogShownResults);
        }
      });
  }

  build() {
    Column() {

      Button("选择相册").onClick((event: ClickEvent) => {
        pickerPhoto()

      })

    }
    .height('100%')
    .width('100%')
  }
}

所以你学会了吗?

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2024-8-2 09:39:55修改
2
收藏
回复
举报
回复
    相关推荐