首页 鸿蒙 正文
  • 本文约7225字,阅读需36分钟
  • 8
  • 0

鸿蒙相机流

import { camera, cameraPicker } from '@kit.CameraKit';
import { image } from '@kit.ImageKit';
import { JSON } from '@kit.ArkTS';
import Logger from '../../UtilClass/LoggerUtils';
import { BusinessError } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';

const TAG: string = 'CameraService';

/**
 * 相机服务
 * 
 *@author liu 2025/05/12
 */
class CameraService {
  private cameraManager: camera.CameraManager | undefined = undefined;
  private cameras: Array<camera.CameraDevice> | Array<camera.CameraDevice> = [];
  private cameraInput: camera.CameraInput | undefined = undefined;
  private previewOutput: camera.PreviewOutput | undefined = undefined;
  private session: camera.PhotoSession | camera.VideoSession | undefined = undefined;
  private curCameraDevice: camera.CameraDevice | undefined = undefined;
  private receiver: image.ImageReceiver | undefined = undefined;
  private width: number = 1920;
  private height: number = 1080;
  frameStartFlag: number = 0;
  private finalPixelMap: image.PixelMap | undefined = undefined;
  private imageSize: image.Size = { width: 1920, height: 1080 };

  /**
   * 初始化相机功能
   * @param cameraDeviceIndex - 相机设备索引
   * @returns 无返回值
   */
  async initCamera(cameraDeviceIndex: number, xComponentSurfaceId: string): Promise<void> {
    Logger.debug(TAG, `initCamera cameraDeviceIndex: ${cameraDeviceIndex}`);
    try {
      await this.releaseCamera();
      // 获取相机管理器实例
      this.cameraManager = this.getCameraManagerFn();
      if (this.cameraManager === undefined) {
        Logger.error(TAG, 'cameraManager is undefined');
        return;
      }
      this.cameras = this.getSupportedCamerasFn(this.cameraManager);
      this.curCameraDevice = this.cameras[cameraDeviceIndex];
      if (this.curCameraDevice === undefined) {
        Logger.error(TAG, 'Failed to create the camera input.');
        return;
      }
      // 创建cameraInput输出对象
      this.cameraInput = this.createCameraInputFn(this.cameraManager, this.curCameraDevice);
      if (this.cameraInput === undefined) {
        Logger.error(TAG, 'Failed to create the camera input.');
        return;
      }
      // 打开相机
      let isOpenSuccess = await this.cameraInputOpenFn(this.cameraInput);
      if (!isOpenSuccess) {
        Logger.error(TAG, 'Failed to open the camera.');
        return;
      }
      // 选择具有不同的stride和width
      let previewProfile: camera.Profile = {
        format: camera.CameraFormat.CAMERA_FORMAT_YUV_420_SP,
        size: {
          width: this.width,
          height: this.height
        }
      };
      let size: image.Size = {
        width: this.width,
        height: this.height
      }
      this.receiver = image.createImageReceiver(size, image.ImageFormat.JPEG, 8);
      this.previewOutput = this.createPreviewOutputFn(this.cameraManager, previewProfile, xComponentSurfaceId);
      // 会话流
      await this.sessionFlowFn(this.cameraManager, this.cameraInput, this.previewOutput);
    } catch (error) {
      Logger.error(TAG, `initCamera fail: ${JSON.stringify(error)}`);
    }
  }

  setPhotoOutputCb(photoOutput: camera.PhotoOutput) {
    //设置回调之后,调用photoOutput的capture方法,就会将拍照的buffer回传到回调中
    photoOutput.on('photoAvailable', (errCode: BusinessError, photo: camera.Photo): void => {
      console.info(`CameraDemo getPhoto start. err: ${JSON.stringify(errCode)}`);
      if (errCode || photo === undefined || photo.main === undefined) {
        console.error('CameraDemo getPhoto failed');
        return;
      }
      let imageObj = photo.main;
      imageObj.getComponent(image.ComponentType.JPEG,
        async (errCode: BusinessError, component: image.Component): Promise<void> => {
          console.info('CameraDemo getComponent start');
          if (errCode || component === undefined) {
            console.error('CameraDemo getComponent failed');
            return;
          }
          let imageBuffer: ArrayBuffer;
          if (component.byteBuffer) {
            imageBuffer = component.byteBuffer;
            let sourceOptions: image.SourceOptions = {
              sourceDensity: 0,
              sourcePixelFormat: image.PixelMapFormat.RGBA_8888,
              sourceSize: this.imageSize
            }
            let imageSource: image.ImageSource = image.createImageSource(imageBuffer, sourceOptions);
            let opts: image.InitializationOptions = {
              editable: false,
              pixelFormat: image.PixelMapFormat.RGBA_8888,
              size: this.imageSize
            }
            let pixelMap = await imageSource.createPixelMap(opts);
            this.finalPixelMap = pixelMap;
          } else {
            return;
          }
        });
    });
  }

  /**
   * 释放会话和相关参数
   */
  async releaseCamera(): Promise<void> {
    Logger.info(TAG, 'releaseCamera is called');
    try {
      await this.receiver?.release();
    } catch (err) {
      Logger.error(TAG, `imageReceiver release fail: error: ${JSON.stringify(err)}`);
    }
    try {
      await this.previewOutput?.release();
    } catch (err) {
      Logger.error(TAG, `previewOutput release fail: error: ${JSON.stringify(err)}`);
    } finally {
      this.previewOutput = undefined;
    }
    try {
      await this.session?.release();
    } catch (err) {
      Logger.error(TAG, `captureSession release fail: error: ${JSON.stringify(err)}`);
    } finally {
      this.session = undefined;
    }
    try {
      await this.cameraInput?.close();
    } catch (err) {
      Logger.error(TAG, `cameraInput close fail: error: ${JSON.stringify(err)}`);
    } finally {
      this.cameraInput = undefined;
    }
    Logger.info(TAG, 'releaseCamera success');
  }

  /**
   * 获取相机管理器实例
   */
  getCameraManagerFn(): camera.CameraManager | undefined {
    if (this.cameraManager) {
      return this.cameraManager;
    }
    let cameraManager: camera.CameraManager | undefined = undefined;
    try {
      cameraManager = camera.getCameraManager(getContext(this));
      Logger.info(TAG, `getCameraManager success: ${cameraManager}`);
    } catch (error) {
      Logger.error(TAG, `getCameraManager failed: ${JSON.stringify(error)}`);
    }
    return cameraManager;
  }

  /**
   * 获取支持指定的摄像机设备对象
   */
  getSupportedCamerasFn(cameraManager: camera.CameraManager): Array<camera.CameraDevice> {
    let supportedCameras: Array<camera.CameraDevice> = [];
    try {
      supportedCameras = cameraManager.getSupportedCameras();
      Logger.info(TAG, `getSupportedCameras success: ${this.cameras}, length: ${this.cameras?.length}`);
    } catch (error) {
      Logger.error(TAG, `getSupportedCameras failed: ${JSON.stringify(error)}`);
    }
    return supportedCameras;
  }

  /**
   * 创建cameraInput输出对象
   */
  createCameraInputFn(cameraManager: camera.CameraManager,
    cameraDevice: camera.CameraDevice): camera.CameraInput | undefined {
    Logger.info(TAG, 'createCameraInputFn is called.');
    let cameraInput: camera.CameraInput | undefined = undefined;
    try {
      cameraInput = cameraManager.createCameraInput(cameraDevice);
      Logger.info(TAG, 'createCameraInputFn success');
    } catch (error) {
      Logger.error(TAG, `createCameraInputFn failed: ${JSON.stringify(error)}`);
    }
    return cameraInput;
  }

  /**
   * 创建previewOutput输出对象
   */
  createPreviewOutputFn(cameraManager: camera.CameraManager, previewProfileObj: camera.Profile,
    surfaceId: string): camera.PreviewOutput | undefined {
    let previewOutput: camera.PreviewOutput | undefined = undefined;
    try {
      previewOutput = cameraManager.createPreviewOutput(previewProfileObj, surfaceId);
      Logger.info(TAG, `createPreviewOutput success: ${previewOutput}`);
    } catch (error) {
      Logger.error(TAG, `createPreviewOutput failed: ${JSON.stringify(error)}`);
    }
    return previewOutput;
  }

  /**
   * 打开相机
   */
  async cameraInputOpenFn(cameraInput: camera.CameraInput): Promise<boolean> {
    let isOpenSuccess = false;
    try {
      await cameraInput.open();
      isOpenSuccess = true;
      Logger.info(TAG, 'cameraInput open success');
    } catch (error) {
      Logger.error(TAG, `createCameraInput failed : ${JSON.stringify(error)}`);
    }
    return isOpenSuccess;
  }

  /**
   * 会话流
   */
  async sessionFlowFn(cameraManager: camera.CameraManager, cameraInput: camera.CameraInput,
    previewOutput: camera.PreviewOutput | undefined): Promise<void> {
    try {
      // 创建CaptureSession实例
      this.session = cameraManager.createSession(camera.SceneMode.NORMAL_PHOTO) as camera.PhotoSession;
      this.session.beginConfig();
      this.session.addInput(cameraInput);
      this.session.addOutput(previewOutput);
      await this.session.commitConfig();
      await this.session.start();
      Logger.info(TAG, 'sessionFlowFn success');
    } catch (error) {
      Logger.error(TAG, `sessionFlowFn fail : ${JSON.stringify(error)}`);
    }
  }

  async pickUpCamera(context:common.Context):Promise<string> {
    let pickRes: Promise<string> = new Promise((resolve, reject) => {
      let pickerProfile: cameraPicker.PickerProfile = {
        cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK
      };
      cameraPicker.pick(context, [cameraPicker.PickerMediaType.PHOTO], pickerProfile).then((res) => {
        if(res.resultCode === 0) {
          resolve(res.resultUri);
        }else {
          reject(res.resultCode);
        }
      }).catch((err: BusinessError) => {
        reject(err);
      })
    })

    return pickRes;
  }
}

export default new CameraService();
评论