1# Photo Capture Practices (ArkTS) 2<!--Kit: Camera Kit--> 3<!--Subsystem: Multimedia--> 4<!--Owner: @qano--> 5<!--SE: @leo_ysl--> 6<!--TSE: @xchaosioda--> 7 8Before developing a camera application, request permissions by following the instructions provided in [Requesting Camera Development Permissions](camera-preparation.md). 9 10This topic provides sample code that covers the complete photo capture process to help you understand the complete API calling sequence. 11 12Before referring to the sample code, you are advised to read [Device Input Management](camera-device-input.md), [Camera Session Management](camera-session-management.md), [Photo Capture](camera-shooting.md), and other related topics in [Camera Development (ArkTS)](camera-preparation.md). 13 14## Development Process 15 16After obtaining the output stream capabilities supported by the camera, create a photo stream. The development process is as follows: 17 18 19 20## Sample Code 21 22For details about how to obtain the context, see [Obtaining the Context of UIAbility](../../application-models/uiability-usage.md#obtaining-the-context-of-uiability). 23 24To view the saved images and videos in Gallery, you must save them to the media library. For details, see [Saving Media Assets](../medialibrary/photoAccessHelper-savebutton.md). 25 26Specifically, when [photoOutput.on('photoAvailable')](../../reference/apis-camera-kit/arkts-apis-camera-PhotoOutput.md#onphotoavailable11) is called and a buffer is obtained, the buffer must be stored in the security component to the media library. 27```ts 28import { camera } from '@kit.CameraKit'; 29import { image } from '@kit.ImageKit'; 30import { BusinessError } from '@kit.BasicServicesKit'; 31 32function setPhotoOutputCb(photoOutput: camera.PhotoOutput): void { 33 // After the callback is set, call capture() of photoOutput to transfer the photo buffer back to the callback. 34 photoOutput.on('photoAvailable', (errCode: BusinessError, photo: camera.Photo): void => { 35 console.info('getPhoto start'); 36 console.error(`err: ${errCode}`); 37 if (errCode || photo === undefined) { 38 console.error('getPhoto failed'); 39 return; 40 } 41 let imageObj = photo.main; 42 imageObj.getComponent(image.ComponentType.JPEG, (errCode: BusinessError, component: image.Component): void => { 43 console.info('getComponent start'); 44 if (errCode || component === undefined) { 45 console.error('getComponent failed'); 46 return; 47 } 48 let buffer: ArrayBuffer; 49 if (component.byteBuffer) { 50 buffer = component.byteBuffer; 51 } else { 52 console.error('byteBuffer is null'); 53 return; 54 } 55 56 // To view the saved image and video resources in Gallery, use a security component to create media assets. 57 58 // After the buffer processing is complete, the buffer must be released. Otherwise, no buffer is available for subsequent photo capture. 59 imageObj.release(); 60 }); 61 }); 62} 63 64async function cameraShootingCase(context: Context, surfaceId: string): Promise<void> { 65 // Create a CameraManager object. 66 let cameraManager: camera.CameraManager = camera.getCameraManager(context); 67 if (!cameraManager) { 68 console.error("camera.getCameraManager error"); 69 return; 70 } 71 // Listen for camera status changes. 72 cameraManager.on('cameraStatus', (err: BusinessError, cameraStatusInfo: camera.CameraStatusInfo) => { 73 if (err !== undefined && err.code !== 0) { 74 console.error('cameraStatus with errorCode = ' + err.code); 75 return; 76 } 77 console.info(`camera : ${cameraStatusInfo.camera.cameraId}`); 78 console.info(`status: ${cameraStatusInfo.status}`); 79 }); 80 81 // Obtain the camera list. 82 let cameraArray: Array<camera.CameraDevice> = cameraManager.getSupportedCameras(); 83 if (cameraArray.length <= 0) { 84 console.error("cameraManager.getSupportedCameras error"); 85 return; 86 } 87 88 for (let index = 0; index < cameraArray.length; index++) { 89 console.info('cameraId : ' + cameraArray[index].cameraId); // Obtain the camera ID. 90 console.info('cameraPosition : ' + cameraArray[index].cameraPosition); // Obtain the camera position. 91 console.info('cameraType : ' + cameraArray[index].cameraType); // Obtain the camera type. 92 console.info('connectionType : ' + cameraArray[index].connectionType); // Obtain the camera connection type. 93 } 94 95 // Create a camera input stream. 96 let cameraInput: camera.CameraInput | undefined = undefined; 97 try { 98 cameraInput = cameraManager.createCameraInput(cameraArray[0]); 99 } catch (error) { 100 let err = error as BusinessError; 101 console.error('Failed to createCameraInput errorCode = ' + err.code); 102 } 103 if (cameraInput === undefined) { 104 return; 105 } 106 107 // Listen for camera input errors. 108 let cameraDevice: camera.CameraDevice = cameraArray[0]; 109 cameraInput.on('error', cameraDevice, (error: BusinessError) => { 110 console.error(`Camera input error code: ${error.code}`); 111 }) 112 113 // Open the camera. 114 await cameraInput.open(); 115 116 // Obtain the supported modes. 117 let sceneModes: Array<camera.SceneMode> = cameraManager.getSupportedSceneModes(cameraArray[0]); 118 let isSupportPhotoMode: boolean = sceneModes.indexOf(camera.SceneMode.NORMAL_PHOTO) >= 0; 119 if (!isSupportPhotoMode) { 120 console.error('photo mode not support'); 121 return; 122 } 123 // Obtain the output stream capability supported by the camera. 124 let cameraOutputCap: camera.CameraOutputCapability = cameraManager.getSupportedOutputCapability(cameraArray[0], camera.SceneMode.NORMAL_PHOTO); 125 if (!cameraOutputCap) { 126 console.error("cameraManager.getSupportedOutputCapability error"); 127 return; 128 } 129 console.info("outputCapability: " + JSON.stringify(cameraOutputCap)); 130 131 let previewProfilesArray: Array<camera.Profile> = cameraOutputCap.previewProfiles; 132 if (!previewProfilesArray) { 133 console.error("createOutput previewProfilesArray == null || undefined"); 134 } 135 136 let photoProfilesArray: Array<camera.Profile> = cameraOutputCap.photoProfiles; 137 if (!photoProfilesArray) { 138 console.error("createOutput photoProfilesArray == null || undefined"); 139 } 140 141 // Create a preview output stream. For details about the surfaceId parameter, see the XComponent. The preview stream uses the surface provided by the XComponent. 142 let previewOutput: camera.PreviewOutput | undefined = undefined; 143 try { 144 previewOutput = cameraManager.createPreviewOutput(previewProfilesArray[0], surfaceId); 145 } catch (error) { 146 let err = error as BusinessError; 147 console.error(`Failed to create the PreviewOutput instance. error code: ${err.code}`); 148 } 149 if (previewOutput === undefined) { 150 return; 151 } 152 // Listen for preview output errors. 153 previewOutput.on('error', (error: BusinessError) => { 154 console.error(`Preview output error code: ${error.code}`); 155 }); 156 157 // Create a photo output stream. 158 let photoOutput: camera.PhotoOutput | undefined = undefined; 159 try { 160 photoOutput = cameraManager.createPhotoOutput(photoProfilesArray[0]); 161 } catch (error) { 162 let err = error as BusinessError; 163 console.error('Failed to createPhotoOutput errorCode = ' + err.code); 164 } 165 if (photoOutput === undefined) { 166 return; 167 } 168 169 // Call the preceding callback to save the image. 170 setPhotoOutputCb(photoOutput); 171 172 // Create a session. 173 let photoSession: camera.PhotoSession | undefined = undefined; 174 try { 175 photoSession = cameraManager.createSession(camera.SceneMode.NORMAL_PHOTO) as camera.PhotoSession; 176 } catch (error) { 177 let err = error as BusinessError; 178 console.error('Failed to create the session instance. errorCode = ' + err.code); 179 } 180 if (photoSession === undefined) { 181 return; 182 } 183 // Listen for session errors. 184 photoSession.on('error', (error: BusinessError) => { 185 console.error(`Capture session error code: ${error.code}`); 186 }); 187 188 // Start configuration for the session. 189 try { 190 photoSession.beginConfig(); 191 } catch (error) { 192 let err = error as BusinessError; 193 console.error('Failed to beginConfig. errorCode = ' + err.code); 194 } 195 196 // Add the camera input stream to the session. 197 try { 198 photoSession.addInput(cameraInput); 199 } catch (error) { 200 let err = error as BusinessError; 201 console.error('Failed to addInput. errorCode = ' + err.code); 202 } 203 204 // Add the preview output stream to the session. 205 try { 206 photoSession.addOutput(previewOutput); 207 } catch (error) { 208 let err = error as BusinessError; 209 console.error('Failed to addOutput(previewOutput). errorCode = ' + err.code); 210 } 211 212 // Add the photo output stream to the session. 213 try { 214 photoSession.addOutput(photoOutput); 215 } catch (error) { 216 let err = error as BusinessError; 217 console.error('Failed to addOutput(photoOutput). errorCode = ' + err.code); 218 } 219 220 // Commit the session configuration. 221 await photoSession.commitConfig(); 222 223 // Start the session. 224 await photoSession.start().then(() => { 225 console.info('Promise returned to indicate the session start success.'); 226 }); 227 // Check whether the camera has flash. 228 let flashStatus: boolean = false; 229 try { 230 flashStatus = photoSession.hasFlash(); 231 } catch (error) { 232 let err = error as BusinessError; 233 console.error('Failed to hasFlash. errorCode = ' + err.code); 234 } 235 console.info('Returned with the flash light support status:' + flashStatus); 236 237 if (flashStatus) { 238 // Check whether the auto flash mode is supported. 239 let flashModeStatus: boolean = false; 240 try { 241 let status: boolean = photoSession.isFlashModeSupported(camera.FlashMode.FLASH_MODE_AUTO); 242 flashModeStatus = status; 243 } catch (error) { 244 let err = error as BusinessError; 245 console.error('Failed to check whether the flash mode is supported. errorCode = ' + err.code); 246 } 247 if(flashModeStatus) { 248 // Set the flash mode to auto. 249 try { 250 photoSession.setFlashMode(camera.FlashMode.FLASH_MODE_AUTO); 251 } catch (error) { 252 let err = error as BusinessError; 253 console.error('Failed to set the flash mode. errorCode = ' + err.code); 254 } 255 } 256 } 257 258 // Check whether the continuous auto focus is supported. 259 let focusModeStatus: boolean = false; 260 try { 261 let status: boolean = photoSession.isFocusModeSupported(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO); 262 focusModeStatus = status; 263 } catch (error) { 264 let err = error as BusinessError; 265 console.error('Failed to check whether the focus mode is supported. errorCode = ' + err.code); 266 } 267 268 if (focusModeStatus) { 269 // Set the focus mode to continuous auto focus. 270 try { 271 photoSession.setFocusMode(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO); 272 } catch (error) { 273 let err = error as BusinessError; 274 console.error('Failed to set the focus mode. errorCode = ' + err.code); 275 } 276 } 277 278 // Obtain the zoom ratio range supported by the camera. 279 let zoomRatioRange: Array<number> = []; 280 try { 281 zoomRatioRange = photoSession.getZoomRatioRange(); 282 } catch (error) { 283 let err = error as BusinessError; 284 console.error('Failed to get the zoom ratio range. errorCode = ' + err.code); 285 } 286 if (zoomRatioRange.length <= 0) { 287 return; 288 } 289 // Set a zoom ratio. 290 try { 291 photoSession.setZoomRatio(zoomRatioRange[0]); 292 } catch (error) { 293 let err = error as BusinessError; 294 console.error('Failed to set the zoom ratio value. errorCode = ' + err.code); 295 } 296 let photoCaptureSetting: camera.PhotoCaptureSetting = { 297 quality: camera.QualityLevel.QUALITY_LEVEL_HIGH, // Set the photo quality to high. 298 rotation: camera.ImageRotation.ROTATION_0 // Set the rotation angle of the photo to 0. 299 } 300 // Use the current photo capture settings to take photos. 301 photoOutput.capture(photoCaptureSetting, (err: BusinessError) => { 302 if (err) { 303 console.error(`Failed to capture the photo ${err.message}`); 304 return; 305 } 306 console.info('Callback invoked to indicate the photo capture request success.'); 307 }); 308 309 // After the photo capture is complete, call the following APIs to close the camera and release the session. Do not release the session before the photo capture is complete. 310 // Stop the session. 311 await photoSession.stop(); 312 313 // Release the camera input stream. 314 await cameraInput.close(); 315 316 // Release the preview output stream. 317 await previewOutput.release(); 318 319 // Release the photo output stream. 320 await photoOutput.release(); 321 322 // Release the session. 323 await photoSession.release(); 324 325 // Set the session to null. 326 photoSession = undefined; 327} 328``` 329