HarmonyOS 双路预览流获取的数据,无法生成一个 pixelMap

1、从双路预览流获取数据,并拷贝生成一个 ArrayBuffer

2、根据这个 ArrayBuffer 生成一个 pixelMap,但是报错

HarmonyOS
2天前
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
Excelsior_abit

参考demo:

import camera from '@ohos.multimedia.camera';
import image from '@ohos.multimedia.image';
import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
import common from '@ohos.app.ability.common';
import fs from '@ohos.file.fs';

import {BusinessError} from '@ohos.base';
@Entry
@Component
struct Index {
  @State message: string = 'Hello World'
  private mXComponentController: XComponentController = new XComponentController;
  private surfaceId: string = '-1';
  @State imgUrl: PixelMap | undefined = undefined;
  private context: ESObject = undefined
  private previewProfilesObj2: camera.Profile | undefined = undefined;
  private receiver: image.ImageReceiver | undefined = undefined;
  private receiver1: image.ImageReceiver | undefined = undefined;




  aboutToAppear() {
    //申请权限
    let context = getContext() as common.UIAbilityContext;
    abilityAccessCtrl.createAtManager().requestPermissionsFromUser(context, ['ohos.permission.CAMERA']).then(() => {
      this.mXComponentController.setXComponentSurfaceSize({ surfaceWidth: 1920, surfaceHeight: 1080 });
      // 获取Surface ID
      this.surfaceId = this.mXComponentController.getXComponentSurfaceId();
      this.createDualChannelPreview(this.surfaceId);
    });
    console.info(`surfaceId=${this.surfaceId}`);
  }

  async createDualChannelPreview(XComponentSurfaceId: string): Promise<void> {
    let cameraManager = await camera.getCameraManager(getContext() as ESObject);
    let camerasDevices: Array<camera.CameraDevice> = cameraManager.getSupportedCameras(); // 获取支持的相机设备对象

    // 获取支持的模式类型
    let sceneModes: Array<camera.SceneMode> = cameraManager.getSupportedSceneModes(camerasDevices[0]);
    let isSupportPhotoMode: boolean = sceneModes.indexOf(camera.SceneMode.NORMAL_PHOTO) >= 0;
    if (!isSupportPhotoMode) {
      console.error('photo mode not support');
      return;
    }
    // 获取profile对象
    let profiles: camera.CameraOutputCapability = cameraManager.getSupportedOutputCapability(camerasDevices[0]); // 获取对应相机设备profiles
    let previewProfiles: Array<camera.Profile> = profiles.previewProfiles;

    // 预览流1
    let previewProfilesObj: camera.Profile = previewProfiles[0];

    // 预览流2
    this.previewProfilesObj2 = previewProfiles[0];

    let size:image.Size = {
      height: this.previewProfilesObj2.size.height,
      width: this.previewProfilesObj2.size.width
    }
    this.receiver= image.createImageReceiver(size, image.ImageFormat.JPEG, 8)
    this.receiver1= image.createImageReceiver(size, image.ImageFormat.JPEG, 8)
    // 创建 预览流1 输出对象
    let previewOutput: camera.PreviewOutput = cameraManager.createPreviewOutput(previewProfilesObj, XComponentSurfaceId);
    // 创建 预览流2 输出对象
    let imageReceiverSurfaceId: string = await this.receiver.getReceivingSurfaceId();
    console.log("imageReceiverSurfaceId-------------"+imageReceiverSurfaceId)

    let previewOutput2: camera.PreviewOutput = cameraManager.createPreviewOutput(this.previewProfilesObj2, imageReceiverSurfaceId);
    // 创建cameraInput对象
    let cameraInput: camera.CameraInput = cameraManager.createCameraInput(camerasDevices[0]);
    // 打开相机
    await cameraInput.open();
    // 会话流程
    let captureSession: camera.CaptureSession = cameraManager.createCaptureSession();
    // 开始配置会话
    captureSession.beginConfig();
    // 把CameraInput加入到会话
    captureSession.addInput(cameraInput);
    // 把 预览流1 加入到会话
    captureSession.addOutput(previewOutput);
    // 把 预览流2 加入到会话
    captureSession.addOutput(previewOutput2);
    // 提交配置信息
    await captureSession.commitConfig();
    // 会话开始
    await captureSession.start();
    this.onImageArrival(this.receiver);
  }
  a(){

  }
  async onImageArrival(receiver: image.ImageReceiver): Promise<void> {
    receiver.on('imageArrival', () => {
      console.error("imageArrival callback");
      receiver.readNextImage((err, nextImage: image.Image) => {
        let a = nextImage.format
        nextImage.getComponent(image.ComponentType.JPEG, async (err, imgComponent: image.Component) => {
          if (err || imgComponent === undefined) {
            return;
          }
          this.saveImageToFile(imgComponent.byteBuffer);
          if (imgComponent.byteBuffer as ArrayBuffer) {
            let sourceOptions: image.SourceOptions = {
              sourceDensity: 120,
              sourcePixelFormat: 8, // NV21
              sourceSize: {
                height: this.previewProfilesObj2!.size.height,
                width: this.previewProfilesObj2!.size.width
              },
            }
            let imageResource = image.createImageSource(imgComponent.byteBuffer, sourceOptions);
            let imagePackerApi = image.createImagePacker();
            let packOpts: image.PackingOption = { format: "image/jpeg", quality: 98 };
            const filePath: string = getContext().cacheDir + "/image.jpg";
            let file = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
            imagePackerApi.packToFile(imageResource, file.fd, packOpts).then(() => {
              console.error('pack success: ' + filePath);
            }).catch((error: BusinessError) => {
              console.error('Failed to pack the image. And the error is: ' + error);
            })
            imageResource.createPixelMap({editable:true,desiredPixelFormat:image.PixelMapFormat.NV21}).then((res)=>{
              this.imgUrl = res;
            });
          } else {
            return;
          }
          nextImage.release();
        })
      })
    })
  }
  saveImageToFile(data: ArrayBuffer) {
    const context = getContext(this);
    let filePath = context.tempDir + "/test.jpg";
    console.info("path is " + filePath);
    let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
    fs.write(file.fd, data, (err, writeLen) => {
      if (err) {
        console.info("write failed with error message: " + err.message + ", error code: " + err.code);
      } else {
        console.info("write data to file succeed and size is:" + writeLen);
        fs.closeSync(file);
      }
    });
    // context.tempDir + "/test.jpg" 对应绝对路径 /data/app/el2/100/base/com.example.image_example/haps/Packer/temp/test.jpg (也可通过hdc shell 查询对应目录)
    // hdc file recv /data/app/el2/100/base/com.example.image_example/haps/Packer/temp/test.jpg D:\ (获取文件到本地,查看保存结果)
  }
  build() {
    Column() {

      // 创建XComponent
      XComponent({
        id: '',
        type: 'surface',
        libraryname: '',
        controller: this.mXComponentController
      })
        .onLoad(() => {
          // 设置Surface宽高(1920*1080),预览尺寸设置参考前面 previewProfilesArray 获取的当前设备所支持的预览分辨率大小去设置
          // this.mXComponentController.setXComponentSurfaceSize({ surfaceWidth: 1920, surfaceHeight: 1080 });
          // 获取Surface ID
          this.surfaceId = this.mXComponentController.getXComponentSurfaceId();
          this.createDualChannelPreview(this.surfaceId);
        })
        .width('800px')
        .height('1280px')

      Row() {
        // 将编辑好的pixelMap传递给状态变量imagePixelMap后,通过Image组件进行渲染
        Image(this.imgUrl).objectFit(ImageFit.None)
      }.width('100%').height('50%').backgroundColor('#F0F0F0')
    }
  }
}
分享
微博
QQ
微信
回复
2天前
相关问题
如何实现预览+录制功能
1068浏览 • 1回复 待解决
如何连续获取相机预览数据
702浏览 • 1回复 待解决
如何随机生成一个汉字?
361浏览 • 1回复 待解决
HarmonyOS 需要一个图片预览组件
297浏览 • 1回复 待解决
如何生成一个32位UUID
476浏览 • 1回复 待解决
如何生成一个36位UUID?
407浏览 • 1回复 待解决
如果写一个多级获取数据问题?
3404浏览 • 1回复 待解决
如何把一个Component画到Pixelmap
1895浏览 • 1回复 待解决
如何生成一个可以交互移动子窗口
932浏览 • 1回复 待解决