基于CameraKit对相机进行操作

用户在进行拍照、录像等操作时需要通过相机获取捕获图像的能力,开发者可以通过CameraKit相关相机接口对相机进行操作。拍照是相机的最重要功能之一,拍照模块基于相机复杂的逻辑,为了保证用户拍出的照片质量,在中间步骤可以设置分辨率、闪光灯、焦距、照片质量及旋转角度等信息。

HarmonyOS
2024-06-13 00:18:05
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
e_lion

场景一:拍照并返回图片场景二:切换摄像头场景三:打开关闭闪光灯

方案描述

场景一:开发相机功能进行拍照并返回图片

效果图

自定义相机创建一路预览和一路拍照,同时进行实时画面的预览和拍照并返回图像

方案一通过camerakit自定义相机拍照

"requestPermissions": [ 
{ 
  "name": 
  "ohos.permission.CAMERA", 
  "reason": 
  "$string:EntryAbility_desc", 
  "usedScene": 
  { 
    "abilities": [ 
    "EntryAbility" 
    ] 
  } 
} 
, 
{ 
  "name": 
  "ohos.permission.MICROPHONE", 
  "reason": 
  "$string:EntryAbility_desc", 
  "usedScene": 
  { 
    "abilities": [ 
    "EntryAbility" 
    ] 
  } 
} 
, 
{ 
  "name": 
  "ohos.permission.MEDIA_LOCATION", 
  "reason": 
  "$string:EntryAbility_desc", 
  "usedScene": 
  { 
    "abilities": [ 
    "EntryAbility" 
    ] 
  } 
} 
, 
{ 
  "name": 
  "ohos.permission.WRITE_MEDIA", 
  "reason": 
  "$string:EntryAbility_desc", 
  "usedScene": 
  { 
    "abilities": [ 
    "EntryAbility" 
    ] 
  } 
} 
, 
{ 
  "name": 
  "ohos.permission.READ_MEDIA", 
  "reason": 
  "$string:EntryAbility_desc", 
  "usedScene": 
  { 
    "abilities": [ 
    "EntryAbility" 
    ] 
  } 
  , 
} 
]

校验是否申请授权:

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; 
  } 
}

2.创建一个相机设备

2.1 通过getCameraManage方法,获取cameraManager对象,用来管理相机的状态能力。

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

通过cameraManager类中的getSupportedCameras方法,获取当前设备支持的相机列表,列表中存储了设备支持的所有相机ID。若列表不为空,则说明列表中的每个ID都支持独立创建相机对象;否则,说明当前设备无可用相机,不可继续后续操作。

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; 
}

2.2 通过上一步返回的CameraDevice,使用createCameraInput创建一个相机输入流 。通过getSupportedOutputCapability方法,获取当前设备支持的所有输出流,如预览流、拍照流等.

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; 
}

3.创建相机会话相机使用预览、拍照、录像、元数据功能前,均需要创建相机会话。在会话中,可以完成以下功能:

  • 配置相机的输入流和输出流。相机在拍摄前,必须完成输入输出流的配置。配置输入流即添加设备输入,对用户而言,相当于选择设备的某一摄像头拍摄;配置输出流,即选择数据将以什么形式输出。当应用需要实现拍照时,输出流应配置为预览流和拍照流,预览流的数据将显示在XComponent组件上,拍照流的数据将通过ImageReceiver接口的能力保存下来。
  • 添加闪光灯、调整焦距等配置。
  • 会话切换控制。应用可以通过移除和添加输出流的方式,切换相机模式。如当前会话的输出流为拍照流,应用可以将拍照流移除,然后添加视频流作为输出流,即完成了拍照到录像的切换。

需要先通过createCaptureSession方法创建一个会话;然后调用Session类中的beginConfig方法配置会话;之后对会话进行使能,即向会话中添加相机的输入流和输出流。这里实现相机拍照功能,所以需要添加预览流previewOutput和拍照流photoOutput,预览流和拍照流创建方案见下一步;最后调用Session类中的commitConfigstart方法提交相关配置,并启动会话。

// 会话流程 
cameraSession = cameraManager.createCaptureSession(); 
// 开始配置会话 
cameraSession.beginConfig(); 
// 把CameraInput加入到会话 
cameraSession.addInput(cameraInput); 
// 把 预览流 加入到会话 
cameraSession.addOutput(previewOutput) 
// 把 拍照流 加入到会话 
cameraSession.addOutput(photoOutPut); 
// 提交配置信息 
await cameraSession.commitConfig(); 
// 会话开始 
await cameraSession.start();

实现拍照功能。通过PhotoOutput.capture来触发一次拍照

Button() { 
  Text("拍照") 
    .fontColor(Color.Black) 
    .alignSelf(ItemAlign.Center) 
    .onClick(() => { 
      // this.capture(this.photoOutPut, null) 
      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)

方案二:通过cammerapicker完成拍照

使用 cameraPicker 拉起系统相机pickpicker.pick 表示拉起相机选择器,根据媒体类型进入相应的模式。

try { 
  let pickerProfile = new CameraPosition(camera.CameraPosition.CAMERA_POSITION_BACK,uri) 
  //前置摄像机传CAMERA_POSITION_FRONT,后置摄像机传CAMERA_POSITION_BACK,saveuri传想存到对应沙箱的uri 
  let pickerResult: picker.PickerResult = await picker.pick(mContext, 
    [picker.PickerMediaType.VIDEO, picker.PickerMediaType.VIDEO], pickerProfile); 
  console.log("the pick pickerResult is:" + JSON.stringify(pickerResult)); 
} catch (error) { 
  let err = error as BusinessError; 
  console.error(`the pick call failed. error code: ${err.code}`); 
}

场景二:切换摄像头

效果图

方案

在通过getSupportedCameras获取相机设备对象后返回的相机设备列表CameraDevice[]中可以获取相机位置信息,然后可以通过设置0(后置)或者1(前置)来达到切换前后摄像头的效果。

核心代码

场景三:打开关闭闪光灯

方案

通过Flash类中的setFlashMode来设置闪光灯模式进行设置之前,需要先检查:

1. 设备是否支持闪光灯,可使用方法hasFlash

2. 设备是否支持指定的闪光灯模式,可使用方法isFlashModeSupported

核心代码

// 判断设备是否支持闪光灯 
let flashStatus: boolean = false; 
try { 
  flashStatus = camerasession.hasFlash();//返回true表示设备支持闪光灯,false表示不支持。接口调用失败会返回相应错误码 
} 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); 
    } 
  } 
}
分享
微博
QQ
微信
回复
2024-06-13 20:30:33
相关问题
基于PhotoViewPicker图片进行操作
708浏览 • 1回复 待解决
基于ImageKit图片进行处理
545浏览 • 1回复 待解决
如何一个文件进行读写操作
363浏览 • 1回复 待解决
harmonyOS基于api9如何调用相机拍照?
3717浏览 • 1回复 待解决
如何Serviceabbility进行调试?
2911浏览 • 1回复 待解决
基于libuv异步库进行线程通信
1783浏览 • 0回复 待解决
如何网页进行预加载?
441浏览 • 1回复 待解决
打包怎么代码进行混淆?
6448浏览 • 1回复 待解决
如何网页进行预连接?
334浏览 • 1回复 待解决
如何JSON数据进行解析优化
672浏览 • 1回复 待解决
如何常见密钥进行格式转换
653浏览 • 1回复 待解决
如何图片进行高斯模糊处理
2056浏览 • 1回复 待解决
如何鸿蒙设备进行ui测试?
3122浏览 • 1回复 待解决
如何相册图片进行编辑裁剪
1696浏览 • 1回复 待解决
如何编译产物进行反编译
488浏览 • 1回复 待解决
如何UI描述进行单元测试?
489浏览 • 1回复 待解决