目录

How do I read the preview image of the camera?

Solution

1. Import the image module.

Create a surface for the dual-channel preview stream. In addition to the surface of an XComponent object, the surface ID generated by an ImageReceiver object is needed. This is achieved by calling the APIs provided by the image module.

import { image } from '@kit.ImageKit';

2. Create a surface of the ImageReceiver object.

async function getImageReceiverSurfaceId(): Promise<string | undefined> {
  let receiver: image.ImageReceiver = image.createImageReceiver({ width: 640,height: 480 },4,8);
  console.info('before ImageReceiver check');
  let ImageReceiverSurfaceId: string | undefined = undefined;
  if (receiver !== undefined) {
    console.info('ImageReceiver is ok');
    let ImageReceiverSurfaceId: string = await receiver.getReceivingSurfaceId();
    console.info(`ImageReceived id: ${ImageReceiverSurfaceId}`);
  } else {
    console.error('ImageReceiver is not ok');
  }
  return ImageReceiverSurfaceId;
}

3. Create a surface of an XComponent object.

For details, see the camera preview guide.

//xxx.ets
// Create an XComponentController object.
@Entry
@Component
struct XComponentPage {
  // Create an XComponentController object.
  mXComponentController: XComponentController = new XComponentController;

  build() {
    Flex() {
      // Create XComponent
      XComponent({
        id: '',
        type: 'surface',
        libraryname: '',
        controller: this.mXComponentController
      })
        .onLoad(() => {
          // Set the width and height of the Surface (1920 * 1080), and set the preview size based on the preview resolution size supported
          // by the current device obtained from previewProfilesArray earlier
          this.mXComponentController.setXComponentSurfaceRect({surfaceWidth:1920,surfaceHeight:1080});
          // Get Surface ID
          let surfaceId: string = this.mXComponentController.getXComponentSurfaceId();
        })
        .width('1920px')
        .height('1080px')
    }
  }
}

4. Implement dual-channel preview.

Call createPreviewOutput to transfer the two surface IDs generated in steps 2 and 3 to the camera service to create two preview streams. Develop other processes based on the normal preview process.

import { camera } from '@kit.CameraKit';
import { image } from '@kit.ImageKit';

async function createDualChannelPreview(cameraManager: camera.CameraManager, XComponentSurfaceId: string, receiver: image.ImageReceiver): Promise<void> {
  let camerasDevices: Array<camera.CameraDevice> = cameraManager.getSupportedCameras(); // Obtain the supported camera devices.

  // Get profile object
  let profiles: camera.CameraOutputCapability = cameraManager.getSupportedOutputCapability(camerasDevices[0], camera.SceneMode.NORMAL_PHOTO); // Obtain the profiles of the camera.
  let previewProfiles: Array<camera.Profile> = profiles.previewProfiles;

  // Preview Stream 1
  let previewProfilesObj: camera.Profile = previewProfiles[0];

  // Preview Stream 2
  let previewProfilesObj2: camera.Profile = previewProfiles[0];

  // Create preview stream 1 output object
  let previewOutput: camera.PreviewOutput = cameraManager.createPreviewOutput(previewProfilesObj, XComponentSurfaceId);

  // Create preview stream 2 output object
  let imageReceiverSurfaceId: string = await receiver.getReceivingSurfaceId();
  let previewOutput2: camera.PreviewOutput = cameraManager.createPreviewOutput(previewProfilesObj2, imageReceiverSurfaceId);

  // Create cameraInput object
  let cameraInput: camera.CameraInput = cameraManager.createCameraInput(camerasDevices[0]);

  // Turn on the camera
  await cameraInput.open();

  // session flow
  let captureSession = cameraManager.createSession(camera.SceneMode.NORMAL_PHOTO);

  // Start configuring session
  captureSession.beginConfig();

  // Add CameraInput to the conversation
  captureSession.addInput(cameraInput);

  // Add preview stream 1 to the session
  captureSession.addOutput(previewOutput);

  // Add preview stream 2 to the session
  captureSession.addOutput(previewOutput2);

  // Submit configuration information
  await captureSession.commitConfig();

  // session start
  await captureSession.start();
}

5. Obtain preview images in real time through the ImageReceiver object.

Use the imageArrival event of the ImageReceiver object to listen for and obtain image data returned by the bottom layer. For details, see the Image API reference.

import { BusinessError } from '@kit.BasicServicesKit';
import image from '@ohos.multimedia.image';

function onImageArrival(receiver: image.ImageReceiver): void {
  receiver.on('imageArrival', () => {
    receiver.readNextImage((err: BusinessError, nextImage: image.Image) => {
      if (err || nextImage === undefined) {
        return;
      }
      // The current ImageReceiver does not support obtaining YUV data. You can use the JPEG data channel to receive YUV data, but using this method carries risks
      nextImage.getComponent(image.ComponentType.JPEG, (err: BusinessError, imgComponent: image.Component) => {
        if (err || imgComponent === undefined) {
          return;
        }
        if (imgComponent.byteBuffer as ArrayBuffer) {
          // Handle according to business demands
        } else {
          return;
        }
      })
    })
  })
}

Reference

Dual-Channel Preview (ArkTS)

@ohos.multimedia.image (Image Processing)