• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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![Photographing Development Process](figures/photographing-development-process.png)
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