1# 拍照(ArkTS) 2 3拍照是相机的最重要功能之一,拍照模块基于相机复杂的逻辑,为了保证用户拍出的照片质量,在中间步骤可以设置分辨率、闪光灯、焦距、照片质量及旋转角度等信息。 4 5## 开发步骤 6 7详细的API说明请参考[Camera API参考](../../reference/apis-camera-kit/js-apis-camera.md)。 8 91. 导入image接口。创建拍照输出流的SurfaceId以及拍照输出的数据,都需要用到系统提供的image接口能力,导入image接口的方法如下。 10 11 ```ts 12 import { image } from '@kit.ImageKit'; 13 import { camera } from '@kit.CameraKit'; 14 import { fileIo as fs } from '@kit.CoreFileKit'; 15 import { photoAccessHelper } from '@kit.MediaLibraryKit'; 16 import { BusinessError } from '@kit.BasicServicesKit'; 17 ``` 18 192. 创建拍照输出流。 20 21 通过[CameraOutputCapability](../../reference/apis-camera-kit/js-apis-camera.md#cameraoutputcapability)类中的photoProfiles属性,可获取当前设备支持的拍照输出流,通过[createPhotoOutput](../../reference/apis-camera-kit/js-apis-camera.md#createphotooutput11)方法传入支持的某一个输出流及步骤一获取的SurfaceId创建拍照输出流。 22 23 ```ts 24 function getPhotoOutput(cameraManager: camera.CameraManager, cameraOutputCapability: camera.CameraOutputCapability): camera.PhotoOutput | undefined { 25 let photoProfilesArray: Array<camera.Profile> = cameraOutputCapability.photoProfiles; 26 if (!photoProfilesArray) { 27 console.error("createOutput photoProfilesArray == null || undefined"); 28 } 29 let photoOutput: camera.PhotoOutput | undefined = undefined; 30 try { 31 photoOutput = cameraManager.createPhotoOutput(photoProfilesArray[0]); 32 } catch (error) { 33 let err = error as BusinessError; 34 console.error(`Failed to createPhotoOutput. error: ${err}`); 35 } 36 return photoOutput; 37 } 38 ``` 39 403. 设置拍照photoAvailable的回调,并将拍照的buffer保存为图片。 41 42 Context获取方式请参考:[获取UIAbility的上下文信息](../../application-models/uiability-usage.md#获取uiability的上下文信息)。 43 44 如需要在图库中看到所保存的图片、视频资源,需要将其保存到媒体库,保存方式请参考:[保存媒体库资源](../medialibrary/photoAccessHelper-savebutton.md)。 45 46 需要在[photoOutput.on('photoAvailable')](../../reference/apis-camera-kit/js-apis-camera.md#onphotoavailable11)接口获取到buffer时,将buffer在安全控件中保存到媒体库。 47 ```ts 48 function setPhotoOutputCb(photoOutput: camera.PhotoOutput, context: Context) { 49 //设置回调之后,调用photoOutput的capture方法,就会将拍照的buffer回传到回调中。 50 photoOutput.on('photoAvailable', (errCode: BusinessError, photo: camera.Photo): void => { 51 console.info('getPhoto start'); 52 console.info(`err: ${errCode}`); 53 if (errCode || photo === undefined) { 54 console.error('getPhoto failed'); 55 return; 56 } 57 let imageObj: image.Image = photo.main; 58 imageObj.getComponent(image.ComponentType.JPEG, (errCode: BusinessError, component: image.Component): void => { 59 console.info('getComponent start'); 60 if (errCode || component === undefined) { 61 console.error('getComponent failed'); 62 return; 63 } 64 let buffer: ArrayBuffer; 65 if (component.byteBuffer) { 66 buffer = component.byteBuffer; 67 } else { 68 console.error('byteBuffer is null'); 69 return; 70 } 71 // 如需要在图库中看到所保存的图片、视频资源,请使用用户无感的安全控件创建媒体资源。 72 73 // buffer处理结束后需要释放该资源,如果未正确释放资源会导致后续拍照获取不到buffer。 74 imageObj.release(); 75 }); 76 }); 77 } 78 ``` 79 804. 参数配置。 81 82 配置相机的参数可以调整拍照的一些功能,包括闪光灯、变焦、焦距等。 83 84 ```ts 85 function configuringSession(photoSession: camera.PhotoSession): void { 86 // 判断设备是否支持闪光灯。 87 let flashStatus: boolean = false; 88 try { 89 flashStatus = photoSession.hasFlash(); 90 } catch (error) { 91 let err = error as BusinessError; 92 console.error(`Failed to hasFlash. error: ${err}`); 93 } 94 console.info(`Returned with the flash light support status: ${flashStatus}`); 95 if (flashStatus) { 96 // 判断是否支持自动闪光灯模式。 97 let flashModeStatus: boolean = false; 98 try { 99 let status: boolean = photoSession.isFlashModeSupported(camera.FlashMode.FLASH_MODE_AUTO); 100 flashModeStatus = status; 101 } catch (error) { 102 let err = error as BusinessError; 103 console.error(`Failed to check whether the flash mode is supported. error: ${err}`); 104 } 105 if (flashModeStatus) { 106 // 设置自动闪光灯模式。 107 try { 108 photoSession.setFlashMode(camera.FlashMode.FLASH_MODE_AUTO); 109 } catch (error) { 110 let err = error as BusinessError; 111 console.error(`Failed to set the flash mode. error: ${err}`); 112 } 113 } 114 } 115 // 判断是否支持连续自动变焦模式。 116 let focusModeStatus: boolean = false; 117 try { 118 let status: boolean = photoSession.isFocusModeSupported(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO); 119 focusModeStatus = status; 120 } catch (error) { 121 let err = error as BusinessError; 122 console.error(`Failed to check whether the focus mode is supported. error: ${err}`); 123 } 124 if (focusModeStatus) { 125 // 设置连续自动变焦模式。 126 try { 127 photoSession.setFocusMode(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO); 128 } catch (error) { 129 let err = error as BusinessError; 130 console.error(`Failed to set the focus mode. error: ${err}`); 131 } 132 } 133 // 获取相机支持的可变焦距比范围。 134 let zoomRatioRange: Array<number> = []; 135 try { 136 zoomRatioRange = photoSession.getZoomRatioRange(); 137 } catch (error) { 138 let err = error as BusinessError; 139 console.error(`Failed to get the zoom ratio range. error: ${err}`); 140 } 141 if (zoomRatioRange.length <= 0 ) { 142 return; 143 } 144 // 设置可变焦距比。 145 try { 146 photoSession.setZoomRatio(zoomRatioRange[0]); 147 } catch (error) { 148 let err = error as BusinessError; 149 console.error(`Failed to set the zoom ratio value. error: ${err}`); 150 } 151 } 152 ``` 153 1545. 触发拍照。 155 156 通过photoOutput类的[capture](../../reference/apis-camera-kit/js-apis-camera.md#capture-2)方法,执行拍照任务。该方法有两个参数,第一个参数为拍照设置参数的setting,setting中可以设置照片的质量和旋转角度,第二参数为回调函数。 157 158 获取拍照旋转角度的方法为,通过通过[PhotoOutput](../../reference/apis-camera-kit/js-apis-camera.md#photooutput)类中的[getPhotoRotation](../../reference/apis-camera-kit/js-apis-camera.md#getphotorotation12)方法获取rotation实际的值。 159 160 ```ts 161 function capture(captureLocation: camera.Location, photoOutput: camera.PhotoOutput): void { 162 let settings: camera.PhotoCaptureSetting = { 163 quality: camera.QualityLevel.QUALITY_LEVEL_HIGH, // 设置图片质量高。 164 rotation: camera.ImageRotation.ROTATION_0, // 设置图片旋转角度的camera.ImageRotation.ROTATION_0是通过说明中获取拍照角度的getPhotoRotation方法获取的值进行设置。 165 location: captureLocation, // 设置图片地理位置。 166 mirror: false // 设置镜像使能开关(默认关)。 167 }; 168 photoOutput.capture(settings, (err: BusinessError) => { 169 if (err) { 170 console.error(`Failed to capture the photo. error: ${err}`); 171 return; 172 } 173 console.info('Callback invoked to indicate the photo capture request success.'); 174 }); 175 } 176 ``` 177 178## 状态监听 179 180在相机应用开发过程中,可以随时监听拍照输出流状态,包括拍照流开始、拍照帧的开始与结束、拍照输出流的错误。 181 182- 通过注册固定的captureStart回调函数获取监听拍照开始结果,photoOutput创建成功时即可监听,相机设备已经准备开始这次拍照时触发,该事件返回此次拍照的captureId。 183 184 ```ts 185 function onPhotoOutputCaptureStart(photoOutput: camera.PhotoOutput): void { 186 photoOutput.on('captureStartWithInfo', (err: BusinessError, captureStartInfo: camera.CaptureStartInfo) => { 187 if (err !== undefined && err.code !== 0) { 188 return; 189 } 190 console.info(`photo capture started, captureId : ${captureStartInfo.captureId}`); 191 }); 192 } 193 ``` 194 195- 通过注册固定的captureEnd回调函数获取监听拍照结束结果,photoOutput创建成功时即可监听,该事件返回结果为拍照完全结束后的相关信息[CaptureEndInfo](../../reference/apis-camera-kit/js-apis-camera.md#captureendinfo)。 196 197 ```ts 198 function onPhotoOutputCaptureEnd(photoOutput: camera.PhotoOutput): void { 199 photoOutput.on('captureEnd', (err: BusinessError, captureEndInfo: camera.CaptureEndInfo) => { 200 if (err !== undefined && err.code !== 0) { 201 return; 202 } 203 console.info(`photo capture end, captureId : ${captureEndInfo.captureId}`); 204 console.info(`frameCount : ${captureEndInfo.frameCount}`); 205 }); 206 } 207 ``` 208 209- 通过注册固定的captureReady回调函数获取监听可拍下一张结果,photoOutput创建成功时即可监听,当下一张可拍时触发,该事件返回结果为下一张可拍的相关信息。 210 211 ```ts 212 function onPhotoOutputCaptureReady(photoOutput: camera.PhotoOutput): void { 213 photoOutput.on('captureReady', (err: BusinessError) => { 214 if (err !== undefined && err.code !== 0) { 215 return; 216 } 217 console.info(`photo capture ready`); 218 }); 219 } 220 ``` 221 222- 通过注册固定的error回调函数获取监听拍照输出流的错误结果。回调返回拍照输出接口使用错误时的对应错误码,错误码类型参见[Camera错误码](../../reference/apis-camera-kit/js-apis-camera.md#cameraerrorcode)。 223 224 ```ts 225 function onPhotoOutputError(photoOutput: camera.PhotoOutput): void { 226 photoOutput.on('error', (error: BusinessError) => { 227 console.error(`Photo output error code: ${error.code}`); 228 }); 229 } 230 ``` 231