1# High-Performance Camera Photographing Sample (for System Applications Only) (ArkTS) 2 3This topic provides sample code that covers the complete high-performance photographing process to help you understand the complete API calling sequence. 4 5Before referring to the sample code, you are advised to read [High-Performance Camera Photographing (for System Applications Only) (ArkTS)] (camera-deferred-photo.md), [Device Input Management](camera-device-input.md), [Camera Session Management](camera-session-management.md), and [Camera Photographing](camera-shooting.md). 6 7## Development Process 8 9After obtaining the output stream capabilities supported by the camera, create a photo stream. The development process is as follows: 10 11 12 13## Sample Code 14 15For details about how to obtain the context, see [Obtaining the Context of UIAbility](../application-models/uiability-usage.md#obtaining-the-context-of-uiability). 16 17```ts 18import camera from '@ohos.multimedia.camera'; 19import image from '@ohos.multimedia.image'; 20import { BusinessError } from '@ohos.base'; 21import common from '@ohos.app.ability.common'; 22import fs from '@ohos.file.fs'; 23import PhotoAccessHelper from '@ohos.file.photoAccessHelper'; 24 25let context = getContext(this); 26 27// Flush the original image in write-file mode. 28async function savePicture(photoObj: camera.Photo): Promise<void> { 29 let photoAccessHelper = PhotoAccessHelper.getPhotoAccessHelper(context); 30 let testFileName = 'testFile' + Date.now() + '.jpg'; 31 // To call createAsset(), the application must have the ohos.permission.READ_IMAGEVIDEO and ohos.permission.WRITE_IMAGEVIDEO permissions. 32 let photoAsset = await photoAccessHelper.createAsset(testFileName); 33 const fd = await photoAsset.open('rw'); 34 let buffer: ArrayBuffer | undefined = undefined; 35 photoObj.main.getComponent(image.ComponentType.JPEG, (errCode: BusinessError, component: image.Component): void => { 36 if (errCode || component === undefined) { 37 console.error('getComponent failed'); 38 return; 39 } 40 if (component.byteBuffer) { 41 buffer = component.byteBuffer; 42 } else { 43 console.error('byteBuffer is null'); 44 return; 45 } 46 }); 47 if (buffer) { 48 await fs.write(fd, buffer); 49 } 50 await photoAsset.close(fd); 51 await photoObj.release(); 52} 53 54// Flush the thumbnail by calling the mediaLibrary API. 55async function saveDeferredPhoto(proxyObj: camera.DeferredPhotoProxy): Promise<void> { 56 try { 57 // Create a photoAsset. 58 let photoAccessHelper = PhotoAccessHelper.getPhotoAccessHelper(context); 59 let testFileName = 'testFile' + Date.now() + '.jpg'; 60 let photoAsset = await photoAccessHelper.createAsset(testFileName); 61 // Pass the thumbnail proxy class object to the mediaLibrary. 62 let mediaRequest: PhotoAccessHelper.MediaAssetChangeRequest = new PhotoAccessHelper.MediaAssetChangeRequest(photoAsset); 63 mediaRequest.addResource(PhotoAccessHelper.ResourceType.PHOTO_PROXY, proxyObj); 64 let res = await photoAccessHelper.applyChanges(mediaRequest); 65 console.info('saveDeferredPhoto success.'); 66 } catch (err) { 67 console.error(`Failed to saveDeferredPhoto. error: ${JSON.stringify(err)}`); 68 } 69} 70 71async function deferredPhotoCase(baseContext: common.BaseContext, surfaceId: string): Promise<void> { 72 // Create a CameraManager object. 73 let cameraManager: camera.CameraManager = camera.getCameraManager(baseContext); 74 if (!cameraManager) { 75 console.error("camera.getCameraManager error"); 76 return; 77 } 78 // Listen for camera status changes. 79 cameraManager.on('cameraStatus', (err: BusinessError, cameraStatusInfo: camera.CameraStatusInfo) => { 80 console.info(`camera : ${cameraStatusInfo.camera.cameraId}`); 81 console.info(`status: ${cameraStatusInfo.status}`); 82 }); 83 84 // Obtain the camera list. 85 let cameraArray: Array<camera.CameraDevice> = cameraManager.getSupportedCameras(); 86 if (cameraArray.length <= 0) { 87 console.error("cameraManager.getSupportedCameras error"); 88 return; 89 } 90 91 for (let index = 0; index < cameraArray.length; index++) { 92 console.info('cameraId : ' + cameraArray[index].cameraId); // Obtain the camera ID. 93 console.info('cameraPosition : ' + cameraArray[index].cameraPosition); // Obtain the camera position. 94 console.info('cameraType : ' + cameraArray[index].cameraType); // Obtain the camera type. 95 console.info('connectionType : ' + cameraArray[index].connectionType); // Obtain the camera connection type. 96 } 97 98 // Create a camera input stream. 99 let cameraInput: camera.CameraInput | undefined = undefined; 100 try { 101 cameraInput = cameraManager.createCameraInput(cameraArray[0]); 102 } catch (error) { 103 let err = error as BusinessError; 104 console.error('Failed to createCameraInput errorCode = ' + err.code); 105 } 106 if (cameraInput === undefined) { 107 return; 108 } 109 110 // Listen for camera input errors. 111 let cameraDevice: camera.CameraDevice = cameraArray[0]; 112 cameraInput.on('error', cameraDevice, (error: BusinessError) => { 113 console.error(`Camera input error code: ${error.code}`); 114 }) 115 116 // Open a camera. 117 await cameraInput.open(); 118 119 // Obtain the supported modes. 120 let sceneModes: Array<camera.SceneMode> = cameraManager.getSupportedSceneModes(cameraArray[0]); 121 let isSupportPhotoMode: boolean = sceneModes.indexOf(camera.SceneMode.NORMAL_PHOTO) >= 0; 122 if (!isSupportPhotoMode) { 123 console.error('photo mode not support'); 124 return; 125 } 126 // Obtain the output streams supported by the camera. 127 let cameraOutputCap: camera.CameraOutputCapability = cameraManager.getSupportedOutputCapability(cameraArray[0], camera.SceneMode.NORMAL_PHOTO); 128 if (!cameraOutputCap) { 129 console.error("cameraManager.getSupportedOutputCapability error"); 130 return; 131 } 132 console.info("outputCapability: " + JSON.stringify(cameraOutputCap)); 133 134 let previewProfilesArray: Array<camera.Profile> = cameraOutputCap.previewProfiles; 135 if (!previewProfilesArray) { 136 console.error("createOutput previewProfilesArray == null || undefined"); 137 } 138 139 let photoProfilesArray: Array<camera.Profile> = cameraOutputCap.photoProfiles; 140 if (!photoProfilesArray) { 141 console.error("createOutput photoProfilesArray == null || undefined"); 142 } 143 144 // Create a preview output stream. For details about the surfaceId parameter, see the XComponent. The preview stream uses the surface provided by the XComponent. 145 let previewOutput: camera.PreviewOutput | undefined = undefined; 146 try { 147 previewOutput = cameraManager.createPreviewOutput(previewProfilesArray[0], surfaceId); 148 } catch (error) { 149 let err = error as BusinessError; 150 console.error(`Failed to create the PreviewOutput instance. error code: ${err.code}`); 151 } 152 if (previewOutput === undefined) { 153 return; 154 } 155 // Listen for preview output errors. 156 previewOutput.on('error', (error: BusinessError) => { 157 console.error(`Preview output error code: ${error.code}`); 158 }); 159 // Create a photo output stream. 160 let photoOutput: camera.PhotoOutput | undefined = undefined; 161 try { 162 photoOutput = cameraManager.createPhotoOutput(photoProfilesArray[0]); 163 } catch (error) { 164 let err = error as BusinessError; 165 console.error('Failed to createPhotoOutput errorCode = ' + err.code); 166 } 167 if (photoOutput === undefined) { 168 return; 169 } 170 // Create a session. 171 let photoSession: camera.PhotoSession | undefined = undefined; 172 try { 173 photoSession = cameraManager.createSession(camera.SceneMode.NORMAL_PHOTO) as camera.PhotoSession; 174 } catch (error) { 175 let err = error as BusinessError; 176 console.error('Failed to create the photoSession instance. errorCode = ' + err.code); 177 } 178 if (photoSession === undefined) { 179 return; 180 } 181 // Listen for session errors. 182 photoSession.on('error', (error: BusinessError) => { 183 console.error(`Capture session error code: ${error.code}`); 184 }); 185 186 // Start configuration for the session. 187 try { 188 photoSession.beginConfig(); 189 } catch (error) { 190 let err = error as BusinessError; 191 console.error('Failed to beginConfig. errorCode = ' + err.code); 192 } 193 194 // Add the camera input stream to the session. 195 try { 196 photoSession.addInput(cameraInput); 197 } catch (error) { 198 let err = error as BusinessError; 199 console.error('Failed to addInput. errorCode = ' + err.code); 200 } 201 202 // Add the preview output stream to the session. 203 try { 204 photoSession.addOutput(previewOutput); 205 } catch (error) { 206 let err = error as BusinessError; 207 console.error('Failed to addOutput(previewOutput). errorCode = ' + err.code); 208 } 209 210 // Add the photo output stream to the session. 211 try { 212 photoSession.addOutput(photoOutput); 213 } catch (error) { 214 let err = error as BusinessError; 215 console.error('Failed to addOutput(photoOutput). errorCode = ' + err.code); 216 } 217 218 // Register a callback to listen for original images. 219 photoOutput.on('photoAvailable', (err: BusinessError, photoObj: camera.Photo): void => { 220 if (err) { 221 console.info(`photoAvailable error: ${JSON.stringify(err)}.`); 222 return; 223 } 224 savePicture(photoObj).then(() => { 225 // Release the photo object after the flushing is complete. 226 photoObj.release(); 227 }); 228 }); 229 230 // Register a callback to listen for thumbnail proxies. 231 photoOutput.on('deferredPhotoProxyAvailable', (err: BusinessError, proxyObj: camera.DeferredPhotoProxy): void => { 232 if (err) { 233 console.info(`deferredPhotoProxyAvailable error: ${JSON.stringify(err)}.`); 234 return; 235 } 236 console.info('photoOutPutCallBack deferredPhotoProxyAvailable'); 237 // Obtain the pixel map of a thumbnail. 238 proxyObj.getThumbnail().then((thumbnail: image.PixelMap) => { 239 AppStorage.setOrCreate('proxyThumbnail', thumbnail); 240 }); 241 // Call the mediaLibrary API to flush the thumbnail. 242 saveDeferredPhoto(proxyObj).then(() => { 243 // Release the thumbnail proxy class object after the flushing is complete. 244 proxyObj.release(); 245 }); 246 }); 247 248 // Check whether deferred delivery is supported. 249 let isSupportDeferred: boolean = photoOutput.isDeferredImageDeliverySupported(camera.DeferredDeliveryImageType.PHOTO); 250 console.info('isDeferredImageDeliverySupported res:' + isSupportDeferred); 251 if (isSupportDeferred) { 252 // Enable deferred delivery. 253 photoOutput.deferImageDelivery(camera.DeferredDeliveryImageType.PHOTO); 254 // Check whether deferred delivery is enabled. 255 let isSupportEnabled: boolean = photoOutput.isDeferredImageDeliveryEnabled(camera.DeferredDeliveryImageType.PHOTO); 256 console.info('isDeferredImageDeliveryEnabled res:' + isSupportEnabled); 257 } 258 259 // Commit the session configuration. 260 await photoSession.commitConfig(); 261 262 // Start the session. 263 await photoSession.start().then(() => { 264 console.info('Promise returned to indicate the session start success.'); 265 }); 266 // Check whether the camera has flash. 267 let flashStatus: boolean = false; 268 try { 269 flashStatus = photoSession.hasFlash(); 270 } catch (error) { 271 let err = error as BusinessError; 272 console.error('Failed to hasFlash. errorCode = ' + err.code); 273 } 274 console.info('Returned with the flash light support status:' + flashStatus); 275 276 if (flashStatus) { 277 // Check whether the auto flash mode is supported. 278 let flashModeStatus: boolean = false; 279 try { 280 let status: boolean = photoSession.isFlashModeSupported(camera.FlashMode.FLASH_MODE_AUTO); 281 flashModeStatus = status; 282 } catch (error) { 283 let err = error as BusinessError; 284 console.error('Failed to check whether the flash mode is supported. errorCode = ' + err.code); 285 } 286 if(flashModeStatus) { 287 // Set the flash mode to auto. 288 try { 289 photoSession.setFlashMode(camera.FlashMode.FLASH_MODE_AUTO); 290 } catch (error) { 291 let err = error as BusinessError; 292 console.error('Failed to set the flash mode. errorCode = ' + err.code); 293 } 294 } 295 } 296 297 // Check whether the continuous auto focus is supported. 298 let focusModeStatus: boolean = false; 299 try { 300 let status: boolean = photoSession.isFocusModeSupported(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO); 301 focusModeStatus = status; 302 } catch (error) { 303 let err = error as BusinessError; 304 console.error('Failed to check whether the focus mode is supported. errorCode = ' + err.code); 305 } 306 307 if (focusModeStatus) { 308 // Set the focus mode to continuous auto focus. 309 try { 310 photoSession.setFocusMode(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO); 311 } catch (error) { 312 let err = error as BusinessError; 313 console.error('Failed to set the focus mode. errorCode = ' + err.code); 314 } 315 } 316 317 // Obtain the zoom ratio range supported by the camera. 318 let zoomRatioRange: Array<number> = []; 319 try { 320 zoomRatioRange = photoSession.getZoomRatioRange(); 321 } catch (error) { 322 let err = error as BusinessError; 323 console.error('Failed to get the zoom ratio range. errorCode = ' + err.code); 324 } 325 if (zoomRatioRange.length <= 0) { 326 return; 327 } 328 // Set a zoom ratio. 329 try { 330 photoSession.setZoomRatio(zoomRatioRange[0]); 331 } catch (error) { 332 let err = error as BusinessError; 333 console.error('Failed to set the zoom ratio value. errorCode = ' + err.code); 334 } 335 let photoCaptureSetting: camera.PhotoCaptureSetting = { 336 quality: camera.QualityLevel.QUALITY_LEVEL_HIGH, // Set the photo quality to high. 337 rotation: camera.ImageRotation.ROTATION_0 // Set the rotation angle of the photo to 0. 338 } 339 // Use the current photographing settings to take photos. 340 photoOutput.capture(photoCaptureSetting, (err: BusinessError) => { 341 if (err) { 342 console.error(`Failed to capture the photo ${err.message}`); 343 return; 344 } 345 console.info('Callback invoked to indicate the photo capture request success.'); 346 }); 347 // Stop the session. 348 photoSession.stop(); 349 350 // Release the camera input stream. 351 cameraInput.close(); 352 353 // Release the preview output stream. 354 previewOutput.release(); 355 356 // Release the photo output stream. 357 photoOutput.release(); 358 359 // Release the session. 360 photoSession.release(); 361 362 // Set the session to null. 363 photoSession = undefined; 364} 365``` 366 367 <!--no_check-->