HarmonyOS鸿蒙Next中相机API拍照问题

发布于 1周前 作者 yuanlaile 来自 鸿蒙OS

HarmonyOS鸿蒙Next中相机API拍照问题 相机api预览有Yuv数据,但是拍照时返回的数据只有压缩后的jpeg,我没法拦截获取其原始yuv数据,这样我无法将相机返回的图片加载成纹理,在opengl渲染

3 回复

可以参考一下以下Demo

可以参考一下以下Demo

import { camera } from '@kit.CameraKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { image } from '@kit.ImageKit';
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { abilityAccessCtrl, PermissionRequestResult, Permissions } from '@kit.AbilityKit';
import { promptAction, router } from '@kit.ArkUI';
import { fileIo } from '@kit.CoreFileKit';

const TAG = '[CameraDemo]';

struct CameraDemo {
  context: Context = getContext(this) as Context;
  @State pixelMap: image.PixelMap | undefined = undefined;
  @State finalPixelMap: image.PixelMap | undefined = undefined;
  @State buffer: ArrayBuffer | undefined = undefined;
  @State surfaceId: string = '';
  @State hasPicture: boolean = false;
  @State fileNames: string[] = [];
  @State imageSize: image.Size = { width: 1920, height: 1080 };
  @State saveButtonOptions: SaveButtonOptions = {
    icon: SaveIconStyle.FULL_FILLED,
    text: SaveDescription.SAVE_IMAGE,
    buttonType: ButtonType.Capsule
  }
  private mXComponentController: XComponentController = new XComponentController;
  private cameraManager: camera.CameraManager | undefined = undefined;
  private cameraSession: camera.PhotoSession | undefined = undefined;
  private photoOutput: camera.PhotoOutput | undefined = undefined;
  private cameraInput: camera.CameraInput | undefined = undefined;
  private previewOutput: camera.PreviewOutput | undefined = undefined;
  private imageReceiver: image.ImageReceiver | undefined = undefined;

aboutToAppear(): void {
  let permissions: Array<Permissions> = [
    'ohos.permission.CAMERA',
    'ohos.permission.WRITE_MEDIA',
    'ohos.permission.READ_MEDIA',
    'ohos.permission.MEDIA_LOCATION',
  ];
  let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
  atManager.requestPermissionsFromUser(this.context, permissions).then((data: PermissionRequestResult) => {
    let grantStatus: Array<number> = data.authResults;
    let length: number = grantStatus.length;
    for (let i = 0; i < length; i++) {
      if (grantStatus[i] != 0) {
        return;
      }
    }
    console.info(`${TAG} Success to request permissions from user. authResults is ${grantStatus}.`);
  }).catch((err: BusinessError) => {
    console.error(`${TAG} Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`);
  })
}

createCameraManager() {
  let cameraManager: camera.CameraManager = camera.getCameraManager(this.context);
  if (!cameraManager) {
    console.error('CameraDemo camera.getCameraManager error');
    return;
  }
  this.cameraManager = cameraManager
  this.cameraManager.on('cameraStatus', (err: BusinessError, cameraStatusInfo: camera.CameraStatusInfo) => {
    console.info(`CameraDemo camera: ${cameraStatusInfo.camera.cameraId}, status: ${cameraStatusInfo.status}`);
  });
}

build() {
  Column() {
    Column({ space: 20 }) {
      if (this.hasPicture) {
        Image(this.finalPixelMap)
          .objectFit(ImageFit.Fill)
          .width('100%')
          .height(300)
        SaveButton(this.saveButtonOptions)
          .onClick(async (event, result: SaveButtonOnClickResult) => {
            if (result == SaveButtonOnClickResult.SUCCESS) {
              if (this.finalPixelMap) {
                try {
                  let phAccessHelper: photoAccessHelper.PhotoAccessHelper = photoAccessHelper.getPhotoAccessHelper(this.context);
                  let options: photoAccessHelper.CreateOptions = {
                    title: Date.now().toString()
                  };
                  let photoUri: string = await phAccessHelper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'png', options);
                  console.info('CameraDemo createAsset successfully, photoUri: ' + photoUri);
                  let file: fileIo.File = fileIo.openSync(photoUri, fileIo.OpenMode.WRITE_ONLY);
                  fileIo.writeSync(file.fd, this.buffer);
                  fileIo.closeSync(file);
                  promptAction.showToast({message:`保存成功`})
                } catch (error) {
                  let err = error as BusinessError;
                  console.error(`CameraDemo savePicture error: ${JSON.stringify(err)}`);
                  promptAction.showToast({ message:`保存失败` })
                }
              }
            } else {
              console.error('CameraDemo SaveButtonOnClickResult createAsset failed.');
              promptAction.showToast({ message:`保存失败` })
            }
            setTimeout(() => {
              this.hasPicture = false;
              this.finalPixelMap = undefined;
            }, 1000)
          })
      } else {
        XComponent({
          id: '',
          type: 'surface',
          libraryname: '',
          controller: this.mXComponentController
        })
          .onLoad(() => {
            this.mXComponentController.setXComponentSurfaceSize({ surfaceWidth: 1920, surfaceHeight: 1080 });
            this.surfaceId = this.mXComponentController.getXComponentSurfaceId();
            setTimeout(async () => {
              await this.prepareCamera();
            }, 500);
          })
          .width('100%')
          .height(600)
        Button('拍照')
          .width(200)
          .height(30)
          .onClick(async () => {
            let photoCaptureSetting: camera.PhotoCaptureSetting = {
              quality: camera.QualityLevel.QUALITY_LEVEL_HIGH, // 设置图片质量高
              rotation: camera.ImageRotation.ROTATION_0 // 设置图片旋转角度0
            }
            await this.photoOutput?.capture(photoCaptureSetting).catch((error: BusinessError) => {
              console.error(`CameraDemo Failed to capture the photo ${error.message}`); //不符合条件则进入
            })
            this.hasPicture = true;
          })
      }
    }
    .width('100%')
    .height('100%')
    .padding(15)
    .borderRadius(8)
  }
  .width('100%')
  .height('100%')
  .backgroundColor('#FFFFFF')
}

async prepareCamera() {
  this.createCameraManager();
  if (!this.cameraManager) {
    console.error('CameraDemo cameraManager is undefined.')
    return;
  }
  let cameraDevices: Array<camera.CameraDevice> = [];
  try {
    cameraDevices = this.cameraManager.getSupportedCameras();
  } catch (error) {
    let err = error as BusinessError;
    console.error(`CameraDemo The getSupportedCameras call failed. error: ${JSON.stringify(err)}`)
  }
  cameraDevices.forEach((cameraDevice: camera.CameraDevice) => {
    console.info(`CameraDemo cameraId: ${cameraDevice.cameraId}, cameraPosition: ${cameraDevice.cameraPosition.toString()}, cameraType: ${cameraDevice.cameraType.toString()}, connectionType: ${cameraDevice.connectionType.toString()}`)
  })
  try {
    this.cameraInput = this.cameraManager.createCameraInput(cameraDevices[0]);
  } catch (error) {
    let err = error as BusinessError;
    console.error(`CameraDemo createCaptureSession error. error: ${JSON.stringify(err)}`);
    return
  }
  this.cameraInput.on('error', cameraDevices[0], (error: BusinessError) => {
    console.error(`CameraDemo Camera input error: ${JSON.stringify(error)}`);
  });
  try {
    await this.cameraInput.open();
  } catch (error) {
    let err = error as BusinessError;
    console.error(`CameraDemo cameraInput open error. error: ${JSON.stringify(err)}`);
  }
  let cameraSceneModes: Array<camera.SceneMode> = [];
  try {
    cameraSceneModes = this.cameraManager.getSupportedSceneModes(cameraDevices[0]);
    cameraSceneModes.forEach((cameraSceneMode: camera.SceneMode) => {
      console.info(`CameraDemo cameraSceneMode: ${cameraSceneMode.toString()}`)
    })
  } catch (error) {
    let err = error as BusinessError;
    console.error(`CameraDemo The getSupportedSceneModes call failed. error: ${JSON.stringify(err)}`)
  }
  let cameraOutputCapability: camera.CameraOutputCapability = this.cameraManager.getSupportedOutputCapability(cameraDevices[0], camera.SceneMode.NORMAL_PHOTO)
  if (!cameraOutputCapability) {
    console.error('CameraDemo cameraManager.getSupportedOutputCapability error')
    return;
  }
  this.printCameraOutputCapability(cameraOutputCapability);
  let previewProfile = cameraOutputCapability.previewProfiles[0];
  cameraOutputCapability.previewProfiles.forEach(profile => {
    if (profile.size.width == this.imageSize.width && profile.size.height == this.imageSize.height) {
      previewProfile = profile;
      return;
    }
  })
  this.imageSize = previewProfile.size;
  try {
    this.previewOutput = this.cameraManager.createPreviewOutput(previewProfile, this.surfaceId);
  } catch (error) {
    let err = error as BusinessError;
    console.error(`CameraDemo createCaptureSession error. error: ${JSON.stringify(err)}`);
    return
  }
  this.previewOutput.on('error', (error: BusinessError) => {
    console.error(`CameraDemo previewOutput error: ${JSON.stringify(error)}`);
  });
  try {
    this.imageReceiver = image.createImageReceiver(this.imageSize, image.ImageFormat.JPEG, 8);
    this.onImageArrival(this.imageReceiver);
  } catch (error) {
    let err = error as BusinessError;
    console.error(`CameraDemo createImageReceiver error ${JSON.stringify(err)}`);
    return
  }
  try {
    let photoProfile = cameraOutputCapability.photoProfiles[0];
    cameraOutputCapability.photoProfiles.forEach(profile => {
      if (profile.size.width == this.imageSize.width && profile.size.height == this.imageSize.height) {
        photoProfile = profile;
        return;
      }
    })
    this.photoOutput = this.cameraManager.createPhotoOutput(photoProfile);
  } catch (error) {
    let err = error as BusinessError;
    console.error(`CameraDemo createPhotoOutput error ${JSON.stringify(err)}`);
  }
  if (this.photoOutput === undefined) {
    console.error('CameraDemo photoOutput is undefined.');
    return;
  }
  this.setPhotoOutputCb(this.photoOutput);
  try {
    this.cameraSession = this.cameraManager.createSession<camera.PhotoSession>(camera.SceneMode.NORMAL_PHOTO);
  } catch (error) {
    let err = error as BusinessError;
    console.error(`CameraDemo createCaptureSession error. error: ${JSON.stringify(err)}`);
    return
  }
  this.cameraSession.on('error', (error: BusinessError) => {
    console.error(`CameraDemo Capture session error: ${JSON.stringify(error)}`);
  });
  try {
    this.cameraSession.beginConfig()
  } catch (error) {
    let err = error as BusinessError;
    console.error(`CameraDemo beginConfig error. error: ${JSON.stringify(err)}`);
  }
  try {
    this.cameraSession.addInput(this.cameraInput)
  } catch (error) {
    let err = error as BusinessError;
    console.error(`CameraDemo addInput error. error: ${JSON.stringify(err)}`);
  }
  try {
    this.cameraSession.addOutput(this.previewOutput)
  } catch (error) {
    let err = error as BusinessError;
    console.error(`CameraDemo add previewOutput error. error: ${JSON.stringify(err)}`);
  }
  try {
    this.cameraSession.addOutput(this.photoOutput);
  } catch (error) {
    let err = error as BusinessError;
    console.error(`CameraDemo add photoOutput error. error: ${JSON.stringify(err)}`);
  }
  try {
    await this.cameraSession.commitConfig();
  } catch (error) {
    let err = error as BusinessError;
    console.error(`CameraDemo captureSession commitConfig error: ${JSON.stringify(err)}`);
  }
  try {
    await this.cameraSession.start();
  } catch (error) {
    let err = error as BusinessError;
    console.error(`CameraDemo captureSession start error: ${JSON.stringify(err)}`);
  }
  this.configuringSession(this.cameraSession)
}

更多关于HarmonyOS鸿蒙Next中相机API拍照问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,相机API的拍照功能主要通过CameraKit实现。开发者可以使用CameraKit来配置相机参数、捕获图像和处理图像数据。具体步骤如下:

  1. 初始化CameraKit:通过CameraKit.getInstance(context)获取CameraKit实例。
  2. 配置相机参数:使用CameraConfig.Builder设置分辨率、对焦模式、闪光灯等参数。
  3. 启动预览:调用startPreview(surface)开始在指定Surface上显示相机预览。
  4. 拍照:使用takePicture(callback)方法捕获图像,callback会返回图像数据。
  5. 处理图像数据:在callback中处理返回的图像数据,如保存或显示。

示例代码:

CameraKit cameraKit = CameraKit.getInstance(context);
CameraConfig config = new CameraConfig.Builder()
    .setPreviewSize(1280, 720)
    .setFocusMode(CameraConfig.FocusMode.AUTO)
    .build();
cameraKit.setConfig(config);
Surface surface = ...; // 获取Surface
cameraKit.startPreview(surface);
cameraKit.takePicture(new CameraKit.PictureCallback() {
    @Override
    public void onPictureTaken(byte[] data) {
        // 处理图像数据
    }
});

常见问题包括图像数据为空、预览不显示等,需检查相机权限、参数配置和回调处理。

在HarmonyOS鸿蒙Next中,使用相机API拍照时,首先确保已正确配置相机权限。通过CameraKit API初始化相机实例,设置预览画面,并调用capture方法进行拍照。拍照完成后,通过回调获取图像数据或保存至指定路径。注意处理相机生命周期,及时释放资源以避免内存泄漏。若遇问题,检查日志或使用调试工具定位错误。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!