HarmonyOS鸿蒙Next中Camera Kit:使用相机服务预览时,前置摄像头清晰,后置模糊如何解决

HarmonyOS鸿蒙Next中Camera Kit:使用相机服务预览时,前置摄像头清晰,后置模糊如何解决 使用相机服务预览时,前置摄像头清晰,后置模糊如何解决

3 回复

楼主你好,可以尝试如下代码

import camera from '@ohos.multimedia.camera';
import { BusinessError } from '@ohos.base';
import image from '@ohos.multimedia.image';
import abilityAccessCtrl, { PermissionRequestResult, Permissions } from '@ohos.abilityAccessCtrl';
import bundleManager from '@ohos.bundle.bundleManager';
import { GlobalContext } from '../utils/GlobalContext';
import Logger from '../utils/Logger';
import common from '@ohos.app.ability.common';

let context = getContext() as common.UIAbilityContext;

let TAG: string = "Index";
let camerasession: camera.CaptureSession
let cameraInput: camera.CameraInput
let photoOutPut: camera.PhotoOutput
let previewOutput: camera.PreviewOutput;
let previewOutput2: camera.PreviewOutput;
let captureSession: camera.CaptureSession;
let cameraWidth = 1920;
let cameraHeight = 1080;

let mXComponentController: XComponentController = new XComponentController;
let surfaceId: string = '';
let pixma: PixelMap | undefined = undefined
let ca: Number = 0
private receiver: image.ImageReceiver = this.createImageReceiver();

await grantPermission().then(res => {
  console.info(TAG, `权限申请成功 ${JSON.stringify(res)}`);
  if (res) {
    //预览和拍照
    createPhotoAndPreview(surfaceId, receiver, ca);
  }
})

@Component
@Entry
struct XComponentPage {
  build() {
    Column() {
      XComponent({
        id: '',
        type: 'surface',
        libraryname: '',
        controller: this.mXComponentController
      })
        .onLoad(async () => {
          // 设置Surface宽高(1920*1080),预览尺寸设置参考前面 previewProfilesArray 获取的当前设备所支持的预览分辨率大小去设置
          // 预览流与录像输出流的分辨率的宽高比要保持一致
          // this.mXComponentController.setXComponentSurfaceSize({ surfaceWidth: cameraWidth, surfaceHeight: cameraHeight });
          // 获取Surface ID
          this.surfaceId = this.mXComponentController.getXComponentSurfaceId();
        })
        .width('1080px')
        .height('1920px')
      Button() {
        Text("拍照")
          .fontColor(Color.Black)
          .alignSelf(ItemAlign.Center)
          .onClick(() => {
            let settings: camera.PhotoCaptureSetting = {
              quality: camera.QualityLevel.QUALITY_LEVEL_HIGH, // 设置图片质量高
              rotation: camera.ImageRotation.ROTATION_0, // 设置图片旋转角度0
              mirror: false // 设置镜像使能开关(默认关)
            };
            photoOutPut.capture(settings, (err: BusinessError) => {
              if (err) {
                console.error(`Failed to capture the photo. error: ${JSON.stringify(err)}`);
                return;
              }
              console.info('Callback invoked to indicate the photo capture request success.');
            });
          })
      }
      .width(100)
      .height(100)

      Button('摄像头_front')
        .size({ width: 150, height: 34 })
        .margin({ left: 10 })
        .onClick(() => {

          ca = 1
          removeSession(captureSession, cameraInput, previewOutput, photoOutPut)
          createPhotoAndPreview(surfaceId, receiver, ca)
          // this.cameraController.setDevicePosition(DevicePosition.front);
        })
      Button('摄像头_back')
        .size({ width: 150, height: 34 })
        .margin({ left: 10 })
        .onClick(() => {
          ca = 0
          removeSession(captureSession, cameraInput, previewOutput, photoOutPut)
          createPhotoAndPreview(surfaceId, receiver, ca)
          // this.cameraController.setDevicePosition(DevicePosition.back);
        })
    }
  }

  configuringSession(): void {
    // 判断设备是否支持闪光灯
    let flashStatus: boolean = false;
    try {
      flashStatus = camerasession.hasFlash();
    } catch (error) {
      let err = error as BusinessError;
      console.error('Failed to hasFlash. errorCode = ' + err.code);
    }
    console.info('Promise returned with the flash light support status:' + flashStatus);

    if (flashStatus) {
      // 判断是否支持自动闪光灯模式
      let flashModeStatus: boolean = false;
      try {
        let status: boolean = camerasession.isFlashModeSupported(camera.FlashMode.FLASH_MODE_AUTO);
        flashModeStatus = status;
      } catch (error) {
        let err = error as BusinessError;
        console.error('Failed to check whether the flash mode is supported. errorCode = ' + err.code);
      }
      if (flashModeStatus) {
        // 设置自动闪光灯模式
        try {
          camerasession.setFlashMode(camera.FlashMode.FLASH_MODE_AUTO);
        } catch (error) {
          let err = error as BusinessError;
          console.error('Failed to set the flash mode. errorCode = ' + err.code);
        }
      }
    }

    // 判断是否支持连续自动变焦模式
    let focusModeStatus: boolean = false;
    try {
      let status: boolean = camerasession.isFocusModeSupported(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO);
      focusModeStatus = status;
    } catch (error) {
      let err = error as BusinessError;
      console.error('Failed to check whether the focus mode is supported. errorCode = ' + err.code);
    }

    if (focusModeStatus) {
      // 设置连续自动变焦模式
      try {
        camerasession.setFocusMode(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO);
      } catch (error) {
        let err = error as BusinessError;
        console.error('Failed to set the focus mode. errorCode = ' + err.code);
      }
    }

    // 获取相机支持的可变焦距比范围
    let zoomRatioRange: Array<number> = [];
    try {
      zoomRatioRange = camerasession.getZoomRatioRange();
    } catch (error) {
      let err = error as BusinessError;
      console.error('Failed to get the zoom ratio range. errorCode = ' + err.code);
    }
    if (zoomRatioRange.length <= 0) {
      return;
    }
    // 设置可变焦距比
    try {
      camerasession.setZoomRatio(zoomRatioRange[0]);
    } catch (error) {
      let err = error as BusinessError;
      console.error('Failed to set the zoom ratio value. errorCode = ' + err.code);
    }

  }

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

  createImageReceiver(): image.ImageReceiver {
    let receiver: image.ImageReceiver = image.createImageReceiver(cameraWidth, cameraHeight, 4, 8);
    console.info('imageArrival11');
    receiver.on("imageArrival", async (e, data) => {
      console.info('imageArrival');
      let imageData = await receiver.readNextImage()
      let imgComponent = await imageData.getComponent(image.ComponentType.JPEG)
      image.createImageSource(imgComponent.byteBuffer)
        .createPixelMap().then((px) => {
        this.pixma = px
      })
    })
    return receiver;
  }

  capture(photoOutput: camera.PhotoOutput, captureLocation?: camera.Location,): void {
    let settings: camera.PhotoCaptureSetting = {
      quality: camera.QualityLevel.QUALITY_LEVEL_HIGH, // 设置图片质量高
      rotation: camera.ImageRotation.ROTATION_0, // 设置图片旋转角度0
      location: captureLocation, // 设置图片地理位置
      mirror: false // 设置镜像使能开关(默认关)
    };
    photoOutput.capture(settings, (err: BusinessError) => {
      if (err) {
        console.error(`Failed to capture the photo. error: ${JSON.stringify(err)}`);
        return;
      }
      console.info('Callback invoked to indicate the photo capture request success.');
    });
  }

  async getSupportedOutputCapability(cameraDevice: camera.CameraDevice,
    cameraManager: camera.CameraManager): Promise<camera.CameraOutputCapability | undefined> {
    // 创建相机输入流
    let cameraInput: camera.CameraInput | undefined = undefined;
    try {
      cameraInput = cameraManager.createCameraInput(cameraDevice);
    } catch (error) {
      let err = error as BusinessError;
      console.error('Failed to createCameraInput errorCode = ' + err.code);
    }
    if (cameraInput === undefined) {
      return undefined;
    }
    // 监听cameraInput错误信息
    cameraInput.on('error', cameraDevice, (error: BusinessError) => {
      console.info(`Camera input error code: ${error.code}`);
    });
    cameraInput = cameraInput
    // 打开相机
    await cameraInput.open();
    // 获取相机设备支持的输出流能力
    let cameraOutputCapability: camera.CameraOutputCapability =
      cameraManager.getSupportedOutputCapability(cameraDevice);
    if (!cameraOutputCapability) {
      console.error("cameraManager.getSupportedOutputCapability error");
      return undefined;
    }
    console.info("outputCapability: " + JSON.stringify(cameraOutputCapability));
    return cameraOutputCapability;
  }
}

async function grantPermission(): Promise<boolean> {
  const PERMISSIONS: Array<Permissions> = [
    'ohos.permission.CAMERA',
  ];
  try {
    // 获取应用程序的accessTokenID
    let bundleInfo: bundleManager.BundleInfo =
      await bundleManager.getBundleInfoForSelf(
        bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION
      );
    let appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo;
    let tokenId = appInfo.accessTokenId;

    let atManager = abilityAccessCtrl.createAtManager();
    let pems: Array<Permissions> = [];

    for (let i = 0; i < PERMISSIONS.length; i++) {
      let state = await atManager.checkAccessToken(tokenId, PERMISSIONS[i]);
      console.info(TAG, `grantPermission checkAccessToken ${PERMISSIONS[i]} + : ${JSON.stringify(state)}`);
      if (state !== abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
        pems.push(PERMISSIONS[i]);
      }
    }
    if (pems.length > 0) {
      console.info(TAG, 'grantPermission requestPermissionsFromUser :' + JSON.stringify(pems));
      let result = await atManager.requestPermissionsFromUser(GlobalContext.get().getCameraAbilityContext(), pems);

      let grantStatus: Array<number> = result.authResults;
      let length: number = grantStatus.length;
      for (let i = 0; i < length; i++) {
        // console.info(TAG, `grantPermission requestPermissionsFromUser ${result.permissions[i]} + : ${grantStatus[i]}`);

        if (grantStatus[i] === 0) {
          // 用户授权,可以继续访问目标操作
        } else {
          // 用户拒绝授权,提示用户必须授权才能访问当前页面的功能
          console.log(TAG + 'grantPermission fail ');
          return false;
        }
      }
    }
    // 授权成功
    console.info(TAG, 'grantPermission success ');
    return true;
  } catch (e) {
    console.info(TAG, 'grantPermission fail ');
    return false;
  }
}

//预览流和拍照流
async function createPhotoAndPreview(XComponentSurfaceId: string, receiver: image.ImageReceiver,
  ca: Number): Promise<void> {
  releaseCamera();
  let cameraManager = getCameraManager();
  let camerasDevices: Array<camera.CameraDevice> = getCameraDevices(cameraManager); // 获取支持的相机设备对象
  let profiles: camera.CameraOutputCapability
  if (ca == 0) {
    // 获取profile对象
    profiles = cameraManager.getSupportedOutputCapability(camerasDevices[0]); // 获取对应相机设备profiles
  } else {
    profiles = cameraManager.getSupportedOutputCapability(camerasDevices[1]); // 获取对应相机设备profiles
  }

  let previewProfiles: Array<camera.Profile> = profiles.previewProfiles
  Logger.debug("createDualChannelPreview-- previewProfiles:" + previewProfiles.length)
  // 预览流
  let index_1080_1920: number = 0
  previewProfiles.forEach((item, index) => {
    if (item.size.width == 1920 && item.size.height == 1080 && item.format == 1003) {
      index_1080_1920 = index;
      console.log('1111111111111111111:' + index_1080_1920)
    }
  })
  let previewProfilesObj: camera.Profile = previewProfiles[index_1080_1920];

  console.log('预览配置列表:' + JSON.stringify(previewProfiles))
  console.log('预览配置个数num=' + JSON.stringify(previewProfiles.length))

  // 拍照流
  let previewProfilesObj2: camera.Profile = profiles.photoProfiles[0];

  // 创建 预览流 输出对象
  previewOutput = cameraManager.createPreviewOutput(previewProfilesObj, XComponentSurfaceId);

  // 创建 拍照流 输出对象
  let imageReceiverSurfaceId: string = await receiver.getReceivingSurfaceId();
  photoOutPut = cameraManager.createPhotoOutput(previewProfilesObj2, imageReceiverSurfaceId);
  // 创建cameraInput对象
  if (ca == 0) {
    cameraInput = cameraManager.createCameraInput(camerasDevices[0]);
  } else {
    cameraInput = cameraManager.createCameraInput(camerasDevices[1]);
  }

  // 打开相机
  await cameraInput.open();
  // 会话流程
  captureSession = cameraManager.createCaptureSession();
  // 开始配置会话
  captureSession.beginConfig();
  // 把CameraInput加入到会话
  captureSession.addInput(cameraInput);
  // 把 预览流 加入到会话
  captureSession.addOutput(previewOutput)
  // 把 拍照流 加入到会话
  captureSession.addOutput(photoOutPut);
  // 提交配置信息
  await captureSession.commitConfig();
  // 会话开始
  await captureSession.start();
  // 判断设备是否支持闪光灯
  let flashStatus: boolean = false;
  try {
    flashStatus = camerasession.hasFlash();
  } catch (error) {
    let err = error as BusinessError;
    console.error('Failed to hasFlash. errorCode = ' + err.code);
  }
  console.info('Promise returned with the flash light support status:' + flashStatus);

  if (flashStatus) {
    // 判断是否支持自动闪光灯模式
    let flashModeStatus: boolean = false;
    try {
      let status: boolean = camerasession.isFlashModeSupported(camera.FlashMode.FLASH_MODE_AUTO);
      flashModeStatus = status;
    } catch (error) {
      let err = error as BusinessError;
      console.error('Failed to check whether the flash mode is supported. errorCode = ' + err.code);
    }
    if (flashModeStatus) {
      // 设置自动闪光灯模式
      try {
        camerasession.setFlashMode(camera.FlashMode.FLASH_MODE_AUTO);
      } catch (error) {
        let err = error as BusinessError;
        console.error('Failed to set the flash mode. errorCode = ' + err.code);
      }
    }
  }
}

async function releaseCamera() {
  if (cameraInput) {
    cameraInput.close()
  }
  if (previewOutput) {
    previewOutput.release()
  }
  if (previewOutput2) {
    previewOutput2.release()
  }
  if (captureSession) {
    captureSession.release()
  }
}

function onPreviewOutputFrameStart
(
  previewOutput:
    camera.PreviewOutput
):
  void {
  previewOutput.on('frameStart', () => {
    console.info('Preview frame started');
  });
}

function getCameraManager(): camera.CameraManager {
  // return camera.getCameraManager(GlobalContext.get().getCameraAbilityContext());
  return camera.getCameraManager(context);

}

function onPreviewOutputFrameEnd(previewOutput: camera.PreviewOutput): void {
  previewOutput.on('frameEnd', () => {
    console.info('Preview frame ended');
  });
}

function onPreviewOutputError(previewOutput: camera.PreviewOutput): void {
  previewOutput.on('error', (previewOutputError: BusinessError) => {
    console.info(`Preview output error code: ${previewOutputError.code}`);
  });
}

function onPhotoOutputEnd(photoOutput: camera.PhotoOutput) {
  photoOutput.on('captureEnd', (err, data) => {
    data.captureId
  })
}

function getCameraDevices(cameraManager: camera.CameraManager): Array<camera.CameraDevice> {
  let cameraArray: Array<camera.CameraDevice> = cameraManager.getSupportedCameras();

  if (cameraArray != undefined && cameraArray.length <= 0) {
    console.error("cameraManager.getSupportedCameras error");
    return [];
  }
  for (let index = 0; index < cameraArray.length; index++) {
    console.info('cameraId : ' + cameraArray[index].cameraId); // 获取相机ID
    console.info('cameraPosition : ' + cameraArray[index].cameraPosition); // 获取相机位置
    console.info('cameraType : ' + cameraArray[index].cameraType); // 获取相机类型
    console.info('connectionType : ' + cameraArray[index].connectionType); // 获取相机连接类型
  }
  return cameraArray;
}


function getCaptureSession(cameraManager: camera.CameraManager): camera.CaptureSession {
  let captureSession = cameraManager.createCaptureSession();
  return captureSession;
}

function beginConfig(captureSession: camera.CaptureSession): void {
  try {
    captureSession.beginConfig();
    console.log("======> success")
  } catch (error) {
    let err = error as BusinessError;
    console.error(`Failed to beginConfig. error: ${JSON.stringify(err)}`);
  }
}

async function startSession(captureSession: camera.CaptureSession, cameraInput: camera.CameraInput,
  previewOutput: camera.PreviewOutput,
  photoOutput: camera.PhotoOutput): Promise<void> {
  try {
    captureSession.addInput(cameraInput);
  } catch (error) {
    let err = error as BusinessError;
    console.error(`Failed to addInput. error: ${JSON.stringify(err)}`);
  }
  try {
    captureSession.addOutput(previewOutput);
  } catch (error) {
    let err = error as BusinessError;
    console.error(`Failed to add previewOutput. error: ${JSON.stringify(err)}`);
  }
  try {
    captureSession.addOutput(photoOutput);
  } catch (error) {
    let err = error as BusinessError;
    console.error(`Failed to add photoOutput. error: ${JSON.stringify(err)}`);
  }
  try {
    await captureSession.commitConfig();
  } catch (error) {
    let err = error as BusinessError;
    console.error(`Failed to commitConfig. error: ${JSON.stringify(err)}`);
  }

  try {
    await captureSession.start()
  } catch (error) {
    let err = error as BusinessError;
    console.error(`Failed to start. error: ${JSON.stringify(err)}`);
  }
}

async function removeSession(captureSession: camera.CaptureSession, cameraInput: camera.CameraInput,
  previewOutput: camera.PreviewOutput, photoOutput: camera.PhotoOutput) {
  captureSession.removeInput(cameraInput)
  captureSession.removeOutput(previewOutput)
  captureSession.removeOutput(photoOutput)
}

更多关于HarmonyOS鸿蒙Next中Camera Kit:使用相机服务预览时,前置摄像头清晰,后置模糊如何解决的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,使用Camera Kit进行相机服务预览时,如果前置摄像头清晰而后置摄像头模糊,可能的原因包括:

  1. 摄像头硬件问题:后置摄像头可能存在硬件故障或镜头脏污,影响成像质量。
  2. 软件配置问题:后置摄像头的参数配置可能不正确,如分辨率、对焦模式等未优化。
  3. 权限设置问题:应用可能未正确获取后置摄像头的权限,导致无法完全启用其功能。
  4. API调用问题:在使用Camera Kit的API时,可能未正确处理后置摄像头的初始化或配置。

解决步骤:

  1. 检查硬件:确保后置摄像头无物理损伤或脏污。
  2. 验证配置:检查Camera Kit中后置摄像头的配置参数,确保与设备规格匹配。
  3. 确认权限:确保应用已正确申请并获取了后置摄像头的使用权限。
  4. 调试API:审查Camera Kit的API调用,确保后置摄像头的初始化和配置正确无误。

通过上述步骤,可以定位并解决后置摄像头模糊的问题。

在HarmonyOS鸿蒙Next中使用Camera Kit进行预览时,如果前置摄像头清晰而后置摄像头模糊,可以按照以下步骤进行排查和解决:

  1. 检查镜头清洁:确保后置摄像头镜头没有污渍或遮挡。
  2. 对焦设置:确认后置摄像头的对焦模式是否正确,尝试使用自动对焦(AF)或手动对焦(MF)进行调整。
  3. 分辨率配置:检查后置摄像头的分辨率设置,确保其与前置摄像头一致或适当。
  4. 硬件问题:如果软件调整无效,可能是后置摄像头硬件故障,建议联系售后检测。

通过以上步骤,通常可以解决后置摄像头模糊的问题。

回到顶部