目录

Photo Capture (ArkTS)

Overview

Photo capture is an important function of the camera. Based on the complex logic of the camera device, the photo capture module allows you to set information such as resolution, flash, focal length, photo quality, and rotation angle in intermediate steps to ensure the quality of captured photos.

Currently, two photo capture solutions are available: deferred capture and single-shot capture. This document uses single-shot capture as the basis for description.

How to Develop

For detailed API descriptions, see @ohos.multimedia.camera (Camera Management).

  1. Import the Image interface. To access the data output by the camera, you must use the image interface capabilities provided by the system. Here is how to import the Image interface.

    import { image } from '@kit.ImageKit';
    import { camera } from '@kit.CameraKit';
    import { fileIo } from '@kit.CoreFileKit';
    import { BusinessError } from '@kit.BasicServicesKit';
  2. Create a photo output stream.

    Obtain the photo output streams supported by the current device from photoProfiles in CameraOutputCapability. Call createPhotoOutput, passing in a supported output stream profile, to create a photo output stream.

    getPhotoOutput(cameraManager: camera.CameraManager,
      cameraOutputCapability: camera.CameraOutputCapability): camera.PhotoOutput | undefined {
      let photoProfilesArray: camera.Profile[] = cameraOutputCapability.photoProfiles;
      if (!photoProfilesArray || photoProfilesArray.length === 0) {
        console.error('photoProfilesArray is null or []');
      }
      let photoOutput: camera.PhotoOutput | undefined = undefined;
      try {
        this.photoProfileObj = photoProfilesArray[0]
        photoOutput = cameraManager.createPhotoOutput(photoProfilesArray[0]);
      } catch (error) {
        let err = error as BusinessError;
        console.error(`Failed to createPhotoOutput. error: ${err}`);
      }
      return photoOutput;
    }
  3. Set the callback for the on('photoAvailable') event and save the photo buffer as an image.

    For details about how to obtain the context, see Obtaining the Context of UIAbility.

    To view the saved photos and videos in Gallery, you need to save them to the media library. For details, see Saving Media Assets.

    When the buffer is obtained through the photoOutput.on('photoAvailable') API, save the buffer to the media library in a security component.

    setPhotoOutputCb(photoOutput: camera.PhotoOutput, context: Context) {
      // After the callback is set, calling the capture method of photoOutput returns the photo buffer to the callback.
      photoOutput.on('photoAvailable', (errCode: BusinessError, photo: camera.Photo): void => {
        console.info('getPhoto start');
        if (errCode || photo === undefined) {
          console.error(`getPhoto failed, err: ${errCode}`);
          return;
        }
          // To view saved images and videos in Gallery, use a security component to create media assets.
          this.mediaLibSavePhotoSingle(context, photo.main)
      });
    }
    
    mediaLibSavePhotoSingle(context: Context, imageObj: image.Image) {
      imageObj.getComponent(image.ComponentType.JPEG, async (errCode: BusinessError, component: image.Component) => {
        if (errCode || component === undefined) {
          Logger.error('getComponent failed');
          return;
        }
        const buffer: ArrayBuffer = component.byteBuffer;
        if (!buffer) {
          Logger.error('byteBuffer is null');
          return;
        }
        let photoType: photoAccessHelper.PhotoType = photoAccessHelper.PhotoType.IMAGE;
        let extension: string = 'jpg';
        let options: photoAccessHelper.CreateOptions = {
          title: 'testPhoto'
        }
        let assetChangeRequest: photoAccessHelper.MediaAssetChangeRequest =
          photoAccessHelper.MediaAssetChangeRequest.createAssetRequest(context, photoType, extension, options);
        assetChangeRequest.addResource(photoAccessHelper.ResourceType.IMAGE_RESOURCE, buffer)
        assetChangeRequest.saveCameraPhoto();
        let accessHelper: photoAccessHelper.PhotoAccessHelper =
          photoAccessHelper.getPhotoAccessHelper(context);
        await accessHelper.applyChanges(assetChangeRequest);
        let imageSource = image.createImageSource(buffer);
        let pixelmap = imageSource.createPixelMapSync();
        this.callback(pixelmap, assetChangeRequest.getAsset().uri);
        accessHelper.release();
        // Release the buffer after processing; failure to release it properly will prevent subsequent photo capture from obtaining the buffer.
        imageObj.release();
      });
    }
  4. Set camera parameters.

    You can set camera parameters to adjust photo capture functions, including the flash, zoom ratio, and focal length.

    configuringSession(photoSession: camera.PhotoSession | camera.VideoSession): void {
      // Check whether the camera has flash.
      let flashStatus: boolean = false;
      try {
        flashStatus = photoSession.hasFlash();
      } catch (error) {
        let err = error as BusinessError;
        console.error(`Failed to hasFlash. error: ${err}`);
      }
      console.info(`Returned with the flash light support status: ${flashStatus}`);
      if (flashStatus) {
        // Check whether turning off the flash mode is supported.
        let flashModeStatus: boolean = false;
        try {
          flashModeStatus = photoSession?.isFlashModeSupported(camera.FlashMode.FLASH_MODE_CLOSE);
        } catch (error) {
          let err = error as BusinessError;
          console.error(`Failed to check whether the flash mode is supported. error: ${err}`);
        }
        if (flashModeStatus) {
          // Set the flash mode to off.
          try {
            photoSession?.setFlashMode(camera.FlashMode.FLASH_MODE_CLOSE);
          } catch (error) {
            let err = error as BusinessError;
            console.error(`Failed to set the flash mode. error: ${err}`);
          }
        }
      }
      // Check whether the continuous auto focus is supported.
      let focusModeStatus: boolean = false;
      try {
        focusModeStatus = photoSession?.isFocusModeSupported(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO);
      } catch (error) {
        let err = error as BusinessError;
        console.error(`Failed to check whether the focus mode is supported. error: ${err}`);
      }
      if (focusModeStatus) {
        // Set the focus mode to continuous auto focus.
        try {
          photoSession?.setFocusMode(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO);
        } catch (error) {
          let err = error as BusinessError;
          console.error(`Failed to set the focus mode. error: ${err}`);
        }
      }
      // Obtain the zoom ratio range supported by the camera.
      let zoomRatioRange: number[] = [];
      try {
        zoomRatioRange = photoSession?.getZoomRatioRange();
      } catch (error) {
        let err = error as BusinessError;
        console.error(`Failed to get the zoom ratio range. error: ${err}`);
      }
      if (zoomRatioRange.length <= 0 ) {
        return;
      }
      // Set a zoom ratio.
      try {
        photoSession?.setZoomRatio(zoomRatioRange[0]);
      } catch (error) {
        let err = error as BusinessError;
        console.error(`Failed to set the zoom ratio value. error: ${err}`);
      }
    }
  5. Trigger photo capture.

    Call capture in PhotoOutput to capture a photo. In this API, the first parameter specifies the settings (for example, photo quality and rotation angle) for photo capture, and the second parameter is a callback function.

    To obtain the photo rotation angle (specified by rotation), call getPhotoRotation in PhotoOutput.

    For details about the photo's geographical location information (specified by Location), you can refer to the implementation in the capture example.

    capture(captureLocation?: camera.Location): void {
      let captureLocationDefault: camera.Location = {
        latitude: 0,
        longitude: 0,
        altitude: 0
      };
      if (captureLocation != undefined) {
        captureLocationDefault = captureLocation;
      }
      let settings: camera.PhotoCaptureSetting = {
        quality: camera.QualityLevel.QUALITY_LEVEL_HIGH,  // Set the image quality to high.
        // Set the image rotation angle. The value of camera.ImageRotation.ROTATION_0 is obtained from the getPhotoRotation method described in the instructions.
        rotation: camera.ImageRotation.ROTATION_0,
        location: captureLocation,  // Set the image location.
        mirror: false  // Set the mirror switch (disabled by default).
      };
      try {
        if (this.photoOutput == undefined) {
          console.info(`photoOutput is undefined.`);
          return;
        }
        this.photoOutput.capture(settings, (err: BusinessError) => {
          if (err) {
            console.error(`Failed to capture the photo. error: ${err}`);
            return;
          }
          console.info('Callback invoked to indicate the photo capture request success.');
        });
      } catch (error) {
        console.error(`capture call failed. error: ${error}`);
      }
    }

High-Performance Capture

Starting from API version 21, the high-performance capture feature is supported, which allows you to set an explicit quality prioritization strategy during single-shot capture.

The experience of single-shot capture is primarily measured by image output speed and final image quality. Therefore, to meet the differentiated requirements of developers in different scenarios, the emphasis on these two metrics varies. For example, street snapshots require quickly capturing the moment, while landscape or portrait photography pursues ultimate image quality.

Only single-shot capture supports setting the quality prioritization strategy. If the quality prioritization strategy is set in deferred capture, the setting will not take effect.

[h2]Quality Prioritization Strategy

When using single-shot capture, two quality prioritization strategy types are supported: speed priority and quality priority, which correspond to different PhotoQualityPrioritization enumeration values.

[h2]How to Correctly Set the Quality Prioritization Strategy

To correctly set the quality prioritization strategy in single-shot capture, the high-performance capture feature provides the following two APIs:

[h2]How to Develop

The high-performance capture APIs need to be called during the enabling step of the Camera Session Management (ArkTS) process.

The specific calling timing is as follows:

Status Listening

During camera application development, you can listen for the status of the photo output stream, including the start of the photo stream, the start and end of the photo frame, and the errors of the photo output stream.