OpenHarmony Camera开发指导(五):相机预览功能(ArkTS)

预览是在相机启动后实时显示场景画面,通常在拍照和录像前执行。

开发步骤

创建预览Surface

如果想在屏幕上显示预览画面,一般由XComponent组件为预览流提供Surface(通过XComponent的getXcomponentSurfaceId方法获取surfaceid),而XComponent的能力由UI提供,相关介绍可参考XComponent组件

typescript 复制代码
// xxx.ets
// 创建XComponentController 
@Component
struct XComponentPage {
  // 创建XComponentController
  mXComponentController: XComponentController = new XComponentController;
  surfaceId: string = '';

  build() {
    Flex() {
      // 创建XComponent
      XComponent({
        id: '',
        type: 'surface',
        libraryname: '',
        controller: this.mXComponentController
      })
        .onLoad(() => {
          // 设置Surface宽高(以1920*1080为例)
          this.mXComponentController.setXComponentSurfaceSize({surfaceWidth:1920,surfaceHeight:1080});
          // 获取Surface id
          this.surfaceId = this.mXComponentController.getXComponentSurfaceId();
        })
        .width('1920px')
        .height('1080px')
    }
  }
}

创建预览输出流

通过getSupportedOutputCapability方法获取到的CameraOutputCapability类中的previewProfiles属性表示当前设备支持的预览配置信息集合,设备能够支持多种不同的预览能力。通过createPreviewOutput方法创建预览输出流,其中,createPreviewOutput方法中的两个参数分别是previewProfilesArray数组中的某一项和上一步获取的surfaceId。

typescript 复制代码
import { camera } from '@kit.CameraKit';
import { BusinessError } from '@kit.BasicServicesKit';

function getPreviewOutput(cameraManager: camera.CameraManager, cameraOutputCapability: camera.CameraOutputCapability, surfaceId: string): camera.PreviewOutput | undefined {
  let previewProfilesArray: Array<camera.Profile> = cameraOutputCapability.previewProfiles;
  let previewOutput: camera.PreviewOutput | undefined = undefined;
  try {
    // 可根据用户需求选择不同的previewProfile
    previewOutput = cameraManager.createPreviewOutput(previewProfilesArray[0], surfaceId);
  } catch (error) {
    let err = error as BusinessError;
    console.error("Failed to create the PreviewOutput instance. error code: " + err.code);
  }
  return previewOutput;
}

启动预览

通过Session.start方法开始输出预览流。

typescript 复制代码
async function startPreviewOutput(cameraManager: camera.CameraManager, previewOutput: camera.PreviewOutput): Promise<void> {
  let cameraArray: Array<camera.CameraDevice> = [];
  cameraArray = cameraManager.getSupportedCameras();
  if (cameraArray.length == 0) {
    console.error('no camera.');
    return;
  }
  // 获取支持的模式类型。
  let sceneModes: Array<camera.SceneMode> = cameraManager.getSupportedSceneModes(cameraArray[0]);
  let isSupportPhotoMode: boolean = sceneModes.indexOf(camera.SceneMode.NORMAL_PHOTO) >= 0;
  if (!isSupportPhotoMode) {
    console.error('photo mode not support');
    return;
  }
  let cameraInput: camera.CameraInput | undefined = undefined;
  cameraInput = cameraManager.createCameraInput(cameraArray[0]);
  if (cameraInput === undefined) {
    console.error('cameraInput is undefined');
    return;
  }
  // 打开相机。
  await cameraInput.open();
  let session: camera.PhotoSession = cameraManager.createSession(camera.SceneMode.NORMAL_PHOTO) as camera.PhotoSession;
  session.beginConfig();
  session.addInput(cameraInput);
  session.addOutput(previewOutput);
  await session.commitConfig();
  await session.start();
}

注:4.0版本需通过调用PreviewOutput.start方法开始输出预览流,从4.1版本开始废弃该方法,改用session.start启动会话同时输出预览流。

停止预览

通过Session.stop方法停止输出预览流。4.0版本需通过调用PreviewOutput.stop方法停止输出预览流,从4.1版本开始废弃该方法,改用session.stop停止会话同时停止输出预览流。

typescript 复制代码
function stopCaptureSession(session: camera.Session): void {
  session.stop((err: BusinessError) => {
    if (err) {
      console.error(`Failed to stop the session, error code: ${err.code}.`);
      return;
    }
    console.info('Callback invoked to indicate the session stop success.');
  });

状态监听

在相机应用开发过程中,可以随时监听预览输出流的状态,包括预览流启动、预览流结束、预览流输出错误信息。

通过注册"frameStart"回调函数获取监听预览启动结果,previewOutput创建成功时即可监听,底层第一次开始曝光时触发该事件并返回,有该事件返回结果则认为预览流已启动。

typescript 复制代码
function callback(err: BusinessError): void {
  if (err !== undefined && err.code !== 0) {
    console.error(`Callback Error, errorCode: ${err.code}`);
    return;
  }
  console.info('Preview frame started');
}

function registerPreviewOutputFrameStart(previewOutput: camera.PreviewOutput): void {
  previewOutput.on('frameStart', callback);
}

通过注册的"frameEnd"回调函数获取监听预览结束结果,previewOutput创建成功时即可监听,预览完全结束最后一帧时触发该事件并返回,有该事件返回结果则认为预览流已结束。

typescript 复制代码
function callback(err: BusinessError): void {
  if (err !== undefined && err.code !== 0) {
    console.error(`Callback Error, errorCode: ${err.code}`);
    return;
  }
  console.info('Preview frame ended');
}

function registerPreviewOutputFrameEnd(previewOutput: camera.PreviewOutput): void {
  previewOutput.on('frameEnd', callback);
}

通过注册"error"回调函数获取监听预览输出的错误事件。

typescript 复制代码
function onPreviewOutputError(previewOutput: camera.PreviewOutput): void {
  previewOutput.on('error', (previewOutputError: BusinessError) => {
    console.error(`Preview output error code: ${previewOutputError.code}`);
  });
}

预览流配置信息

支持查询预览流支持的帧率范围、预览旋转角度等信息;支持配置预览流帧率范围、预览旋转角度等。

typescript 复制代码
function setFrameRateRange(previewOutput: camera.PreviewOutput): void {
  let supportedFrameRatesArray: Array<camera.FrameRateRange> = previewOutput.getSupportedFrameRates();
  previewOutput.setFrameRate(supportedFrameRatesArray[0].min, supportedFrameRatesArray[0].max);
  let activeFrameRate: camera.FrameRateRange = previewOutput.getActiveFrameRate();
}

function setPreviewRotation(previewOutput: camera.PreviewOutput, previewRotation : camera.ImageRotation, isDisplayLocked: boolean): void {
    previewOutput.setPreviewRotation(previewRotation, isDisplayLocked);
}

API参考

createPreviewOutput

typescript 复制代码
createPreviewOutput(profile: Profile, surfaceId: string): PreviewOutput

创建预览输出对象,同步返回结果。

typescript 复制代码
createPreviewOutput(surfaceId: string): PreviewOutput

创建无配置信息的预览输出对象,同步返回结果。该接口需配合Session.preconfig方法一起使用。

PreviewOutput

预览输出类。继承CameraOutput。

typescript 复制代码
on(type: 'frameStart', callback: AsyncCallback<void>): void
off(type: 'frameStart', callback?: AsyncCallback<void>): void
on(type: 'frameEnd', callback: AsyncCallback<void>): void
off('frameEnd')
on('error')
off(type: 'error', callback?: ErrorCallback): void

// 查询支持的帧率范围
getSupportedFrameRates(): Array<FrameRateRange>

// 设置预览流帧率范围,设置的范围必须在支持的帧率范围内。 进行设置前,可通过getSupportedFrameRates查询支持的帧率范围
setFrameRate(minFps: number, maxFps: number): void

// 获取已设置的帧率范围,使用setFrameRate对预览流设置过帧率后可查询。
getActiveFrameRate(): FrameRateRange

// 获取当前生效的配置信息
getActiveProfile(): Profile

// 获取预览旋转角度
getPreviewRotation(displayRotation: number): ImageRotation

// 设置预览旋转角度
setPreviewRotation(previewRotation: ImageRotation, isDisplayLocked?: boolean): void
相关推荐
梁下轻语的秋缘3 小时前
HarmonyOs学习 环境配置后 实验1:创建项目Hello World
学习·华为·harmonyos
Hello_MyDream3 小时前
鸿蒙语言基础
华为·harmonyos
杯莫停丶3 小时前
对象池模式在uniapp鸿蒙APP中的深度应用
uni-app·harmonyos·鸿蒙
simple_lau5 小时前
浅谈鸿蒙多线程
harmonyos·arkts·arkui
simple_lau5 小时前
鸿蒙开发如何与穿戴设备通讯
harmonyos·arkts·arkui
冯志浩5 小时前
HarmonyOS - 组件外部输入状态管理装饰器:Param
harmonyos·掘金·金石计划
RedHood6 小时前
鸿蒙投屏实现
electron·harmonyos
鸿蒙布道师17 小时前
鸿蒙NEXT开发键盘工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
杯莫停丶20 小时前
基于uniapp的鸿蒙APP大数据量性能优化
性能优化·uni-app·harmonyos·鸿蒙