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: ${JSON.stringify(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 let context = getContext(this); 49 50 function setPhotoOutputCb(photoOutput: camera.PhotoOutput) { 51 //设置回调之后,调用photoOutput的capture方法,就会将拍照的buffer回传到回调中 52 photoOutput.on('photoAvailable', (errCode: BusinessError, photo: camera.Photo): void => { 53 console.info('getPhoto start'); 54 console.info(`err: ${JSON.stringify(errCode)}`); 55 if (errCode || photo === undefined) { 56 console.error('getPhoto failed'); 57 return; 58 } 59 let imageObj: image.Image = photo.main; 60 imageObj.getComponent(image.ComponentType.JPEG, (errCode: BusinessError, component: image.Component): void => { 61 console.info('getComponent start'); 62 if (errCode || component === undefined) { 63 console.error('getComponent failed'); 64 return; 65 } 66 let buffer: ArrayBuffer; 67 if (component.byteBuffer) { 68 buffer = component.byteBuffer; 69 } else { 70 console.error('byteBuffer is null'); 71 return; 72 } 73 // 如需要在图库中看到所保存的图片、视频资源,请使用用户无感的安全控件创建媒体资源。 74 75 // buffer处理结束后需要释放该资源,如果未正确释放资源会导致后续拍照获取不到buffer 76 imageObj.release(); 77 }); 78 }); 79 } 80 ``` 81 824. 参数配置。 83 84 配置相机的参数可以调整拍照的一些功能,包括闪光灯、变焦、焦距等。 85 86 ```ts 87 function configuringSession(photoSession: camera.PhotoSession): void { 88 // 判断设备是否支持闪光灯 89 let flashStatus: boolean = false; 90 try { 91 flashStatus = photoSession.hasFlash(); 92 } catch (error) { 93 let err = error as BusinessError; 94 console.error(`Failed to hasFlash. error: ${JSON.stringify(err)}`); 95 } 96 console.info(`Returned with the flash light support status: ${flashStatus}`); 97 if (flashStatus) { 98 // 判断是否支持自动闪光灯模式 99 let flashModeStatus: boolean = false; 100 try { 101 let status: boolean = photoSession.isFlashModeSupported(camera.FlashMode.FLASH_MODE_AUTO); 102 flashModeStatus = status; 103 } catch (error) { 104 let err = error as BusinessError; 105 console.error(`Failed to check whether the flash mode is supported. error: ${JSON.stringify(err)}`); 106 } 107 if (flashModeStatus) { 108 // 设置自动闪光灯模式 109 try { 110 photoSession.setFlashMode(camera.FlashMode.FLASH_MODE_AUTO); 111 } catch (error) { 112 let err = error as BusinessError; 113 console.error(`Failed to set the flash mode. error: ${JSON.stringify(err)}`); 114 } 115 } 116 } 117 // 判断是否支持连续自动变焦模式 118 let focusModeStatus: boolean = false; 119 try { 120 let status: boolean = photoSession.isFocusModeSupported(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO); 121 focusModeStatus = status; 122 } catch (error) { 123 let err = error as BusinessError; 124 console.error(`Failed to check whether the focus mode is supported. error: ${JSON.stringify(err)}`); 125 } 126 if (focusModeStatus) { 127 // 设置连续自动变焦模式 128 try { 129 photoSession.setFocusMode(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO); 130 } catch (error) { 131 let err = error as BusinessError; 132 console.error(`Failed to set the focus mode. error: ${JSON.stringify(err)}`); 133 } 134 } 135 // 获取相机支持的可变焦距比范围 136 let zoomRatioRange: Array<number> = []; 137 try { 138 zoomRatioRange = photoSession.getZoomRatioRange(); 139 } catch (error) { 140 let err = error as BusinessError; 141 console.error(`Failed to get the zoom ratio range. error: ${JSON.stringify(err)}`); 142 } 143 if (zoomRatioRange.length <= 0 ) { 144 return; 145 } 146 // 设置可变焦距比 147 try { 148 photoSession.setZoomRatio(zoomRatioRange[0]); 149 } catch (error) { 150 let err = error as BusinessError; 151 console.error(`Failed to set the zoom ratio value. error: ${JSON.stringify(err)}`); 152 } 153 } 154 ``` 155 1565. 触发拍照。 157 158 通过photoOutput类的[capture](../../reference/apis-camera-kit/js-apis-camera.md#capture-2)方法,执行拍照任务。该方法有两个参数,第一个参数为拍照设置参数的setting,setting中可以设置照片的质量和旋转角度,第二参数为回调函数。 159 160 获取拍照旋转角度的方法为,通过通过[PhotoOutput](../../reference/apis-camera-kit/js-apis-camera.md#photooutput)类中的[getPhotoRotation](../../reference/apis-camera-kit/js-apis-camera.md#getphotorotation12)方法获取rotation实际的值 161 162 ```ts 163 function capture(captureLocation: camera.Location, photoOutput: camera.PhotoOutput): void { 164 let settings: camera.PhotoCaptureSetting = { 165 quality: camera.QualityLevel.QUALITY_LEVEL_HIGH, // 设置图片质量高 166 rotation: camera.ImageRotation.ROTATION_0, // 设置图片旋转角度的camera.ImageRotation.ROTATION_0是通过说明中获取拍照角度的getPhotoRotation方法获取的值进行设置 167 location: captureLocation, // 设置图片地理位置 168 mirror: false // 设置镜像使能开关(默认关) 169 }; 170 photoOutput.capture(settings, (err: BusinessError) => { 171 if (err) { 172 console.error(`Failed to capture the photo. error: ${JSON.stringify(err)}`); 173 return; 174 } 175 console.info('Callback invoked to indicate the photo capture request success.'); 176 }); 177 } 178 ``` 179 180## 状态监听 181 182在相机应用开发过程中,可以随时监听拍照输出流状态,包括拍照流开始、拍照帧的开始与结束、拍照输出流的错误。 183 184- 通过注册固定的captureStart回调函数获取监听拍照开始结果,photoOutput创建成功时即可监听,相机设备已经准备开始这次拍照时触发,该事件返回此次拍照的captureId。 185 186 ```ts 187 function onPhotoOutputCaptureStart(photoOutput: camera.PhotoOutput): void { 188 photoOutput.on('captureStartWithInfo', (err: BusinessError, captureStartInfo: camera.CaptureStartInfo) => { 189 if (err !== undefined && err.code !== 0) { 190 return; 191 } 192 console.info(`photo capture started, captureId : ${captureStartInfo.captureId}`); 193 }); 194 } 195 ``` 196 197- 通过注册固定的captureEnd回调函数获取监听拍照结束结果,photoOutput创建成功时即可监听,该事件返回结果为拍照完全结束后的相关信息[CaptureEndInfo](../../reference/apis-camera-kit/js-apis-camera.md#captureendinfo)。 198 199 ```ts 200 function onPhotoOutputCaptureEnd(photoOutput: camera.PhotoOutput): void { 201 photoOutput.on('captureEnd', (err: BusinessError, captureEndInfo: camera.CaptureEndInfo) => { 202 if (err !== undefined && err.code !== 0) { 203 return; 204 } 205 console.info(`photo capture end, captureId : ${captureEndInfo.captureId}`); 206 console.info(`frameCount : ${captureEndInfo.frameCount}`); 207 }); 208 } 209 ``` 210 211- 通过注册固定的captureReady回调函数获取监听可拍下一张结果,photoOutput创建成功时即可监听,当下一张可拍时触发,该事件返回结果为下一张可拍的相关信息。 212 213 ```ts 214 function onPhotoOutputCaptureReady(photoOutput: camera.PhotoOutput): void { 215 photoOutput.on('captureReady', (err: BusinessError) => { 216 if (err !== undefined && err.code !== 0) { 217 return; 218 } 219 console.info(`photo capture ready`); 220 }); 221 } 222 ``` 223 224- 通过注册固定的error回调函数获取监听拍照输出流的错误结果。回调返回拍照输出接口使用错误时的对应错误码,错误码类型参见[Camera错误码](../../reference/apis-camera-kit/js-apis-camera.md#cameraerrorcode)。 225 226 ```ts 227 function onPhotoOutputError(photoOutput: camera.PhotoOutput): void { 228 photoOutput.on('error', (error: BusinessError) => { 229 console.error(`Photo output error code: ${error.code}`); 230 }); 231 } 232 ``` 233