如何读取相机的预览图
==========

开发步骤：

1.  导入image接口。
    
    创建双路预览流的SurfaceId时，除了XComponent组件的SurfaceId，还需要使用ImageReceiver组件创建的SurfaceId。使用image模块提供的接口完成此操作。
    
    import { image } from '@kit.ImageKit';
    
2.  创建ImageReceiver组件Surface。
    
    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.  创建XComponent组件Surface。
    
    参考相机预览指导文档。
    
    _//xxx.ets_
    _// 创建XComponentController_
    @Entry
    @Component
    struct XComponentPage {
     _ // 创建XComponentController_
      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.  实现双路预览。
    
    通过 \`createPreviewOutput\` 方法将步骤2和步骤3生成的两路 \`SurfaceId\` 传递到相机服务，创建两路预览流。其余流程按照正常预览流程开发。
    
    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(); _// 获取支持的相机设备对象_
    
     _ // Get profile object_
      let profiles: camera.CameraOutputCapability = cameraManager.getSupportedOutputCapability(camerasDevices\[0\], camera.SceneMode.NORMAL\_PHOTO); _// 获取对应相机设备profiles_
      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.  通过ImageReceiver实时获取预览图像。
    
    通过ImageReceiver组件的imageArrival事件监听获取底层返回的图像数据。有关详细的API说明，请参考Image API。
    
    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;
            }
          })
        })
      })
    }
    

#### 参考链接

[双路预览(ArkTS)](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/camera-dual-channel-preview)

[@ohos.multimedia.image (图片处理)](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-image)