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