• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 拍照实现方案
2
3## 开发流程
4
5在获取到相机支持的输出流能力后,开始创建拍照流,开发流程如下。
6
7![Photographing Development Process](figures/photographing-development-process.png)
8
9## 完整示例
10[BaseContext获取方式](../reference/apis/js-apis-inner-application-baseContext.md)。
11```ts
12import camera from '@ohos.multimedia.camera';
13import image from '@ohos.multimedia.image';
14import { BusinessError } from '@ohos.base';
15import common from '@ohos.app.ability.common';
16
17async function cameraShootingCase(baseContext: common.BaseContext, surfaceId: string): Promise<void> {
18  // 创建CameraManager对象
19  let cameraManager: camera.CameraManager = camera.getCameraManager(baseContext);
20  if (!cameraManager) {
21    console.error("camera.getCameraManager error");
22    return;
23  }
24  // 监听相机状态变化
25  cameraManager.on('cameraStatus', (err: BusinessError, cameraStatusInfo: camera.CameraStatusInfo) => {
26    console.info(`camera : ${cameraStatusInfo.camera.cameraId}`);
27    console.info(`status: ${cameraStatusInfo.status}`);
28  });
29
30  // 获取相机列表
31  let cameraArray: Array<camera.CameraDevice> = cameraManager.getSupportedCameras();
32  if (cameraArray.length <= 0) {
33    console.error("cameraManager.getSupportedCameras error");
34    return;
35  }
36
37  for (let index = 0; index < cameraArray.length; index++) {
38    console.info('cameraId : ' + cameraArray[index].cameraId);                          // 获取相机ID
39    console.info('cameraPosition : ' + cameraArray[index].cameraPosition);              // 获取相机位置
40    console.info('cameraType : ' + cameraArray[index].cameraType);                      // 获取相机类型
41    console.info('connectionType : ' + cameraArray[index].connectionType);              // 获取相机连接类型
42  }
43
44  // 创建相机输入流
45  let cameraInput: camera.CameraInput | undefined = undefined;
46  try {
47    cameraInput = cameraManager.createCameraInput(cameraArray[0]);
48  } catch (error) {
49    let err = error as BusinessError;
50    console.error('Failed to createCameraInput errorCode = ' + err.code);
51  }
52  if (cameraInput === undefined) {
53    return;
54  }
55
56  // 监听cameraInput错误信息
57  let cameraDevice: camera.CameraDevice = cameraArray[0];
58  cameraInput.on('error', cameraDevice, (error: BusinessError) => {
59    console.info(`Camera input error code: ${error.code}`);
60  })
61
62  // 打开相机
63  await cameraInput.open();
64
65  // 获取相机设备支持的输出流能力
66  let cameraOutputCap: camera.CameraOutputCapability = cameraManager.getSupportedOutputCapability(cameraArray[0]);
67  if (!cameraOutputCap) {
68    console.error("cameraManager.getSupportedOutputCapability error");
69    return;
70  }
71  console.info("outputCapability: " + JSON.stringify(cameraOutputCap));
72
73  let previewProfilesArray: Array<camera.Profile> = cameraOutputCap.previewProfiles;
74  if (!previewProfilesArray) {
75    console.error("createOutput previewProfilesArray == null || undefined");
76  }
77
78  let photoProfilesArray: Array<camera.Profile> = cameraOutputCap.photoProfiles;
79  if (!photoProfilesArray) {
80    console.error("createOutput photoProfilesArray == null || undefined");
81  }
82
83  // 创建预览输出流,其中参数 surfaceId 参考上文 XComponent 组件,预览流为XComponent组件提供的surface
84  let previewOutput: camera.PreviewOutput | undefined = undefined;
85  try {
86    previewOutput = cameraManager.createPreviewOutput(previewProfilesArray[0], surfaceId);
87  } catch (error) {
88    let err = error as BusinessError;
89    console.error(`Failed to create the PreviewOutput instance. error code: ${err.code}`);
90  }
91  if (previewOutput === undefined) {
92    return;
93  }
94  // 监听预览输出错误信息
95  previewOutput.on('error', (error: BusinessError) => {
96    console.info(`Preview output error code: ${error.code}`);
97  });
98
99  // 创建ImageReceiver对象,并设置照片参数:分辨率大小是根据前面 photoProfilesArray 获取的当前设备所支持的拍照分辨率大小去设置
100  let imageReceiver: image.ImageReceiver = image.createImageReceiver(1920, 1080, 4, 8);
101  // 获取照片显示SurfaceId
102  let photoSurfaceId: string = await imageReceiver.getReceivingSurfaceId();
103  // 创建拍照输出流
104  let photoOutput: camera.PhotoOutput | undefined = undefined;
105  try {
106    photoOutput = cameraManager.createPhotoOutput(photoProfilesArray[0], photoSurfaceId);
107  } catch (error) {
108    let err = error as BusinessError;
109    console.error('Failed to createPhotoOutput errorCode = ' + err.code);
110  }
111  if (photoOutput === undefined) {
112    return;
113  }
114  //创建会话
115  let captureSession: camera.CaptureSession | undefined = undefined;
116  try {
117    captureSession = cameraManager.createCaptureSession();
118  } catch (error) {
119    let err = error as BusinessError;
120    console.error('Failed to create the CaptureSession instance. errorCode = ' + err.code);
121  }
122  if (captureSession === undefined) {
123    return;
124  }
125  // 监听session错误信息
126  captureSession.on('error', (error: BusinessError) => {
127    console.info(`Capture session error code: ${error.code}`);
128  });
129
130  // 开始配置会话
131  try {
132    captureSession.beginConfig();
133  } catch (error) {
134    let err = error as BusinessError;
135    console.error('Failed to beginConfig. errorCode = ' + err.code);
136  }
137
138  // 向会话中添加相机输入流
139  try {
140    captureSession.addInput(cameraInput);
141  } catch (error) {
142    let err = error as BusinessError;
143    console.error('Failed to addInput. errorCode = ' + err.code);
144  }
145
146  // 向会话中添加预览输出流
147  try {
148    captureSession.addOutput(previewOutput);
149  } catch (error) {
150    let err = error as BusinessError;
151    console.error('Failed to addOutput(previewOutput). errorCode = ' + err.code);
152  }
153
154  // 向会话中添加拍照输出流
155  try {
156    captureSession.addOutput(photoOutput);
157  } catch (error) {
158    let err = error as BusinessError;
159    console.error('Failed to addOutput(photoOutput). errorCode = ' + err.code);
160  }
161
162  // 提交会话配置
163  await captureSession.commitConfig();
164
165  // 启动会话
166  await captureSession.start().then(() => {
167    console.info('Promise returned to indicate the session start success.');
168  });
169  // 判断设备是否支持闪光灯
170  let flashStatus: boolean = false;
171  try {
172    flashStatus = captureSession.hasFlash();
173  } catch (error) {
174    let err = error as BusinessError;
175    console.error('Failed to hasFlash. errorCode = ' + err.code);
176  }
177  console.info('Promise returned with the flash light support status:' + flashStatus);
178
179  if (flashStatus) {
180    // 判断是否支持自动闪光灯模式
181    let flashModeStatus: boolean = false;
182    try {
183      let status: boolean = captureSession.isFlashModeSupported(camera.FlashMode.FLASH_MODE_AUTO);
184      flashModeStatus = status;
185    } catch (error) {
186      let err = error as BusinessError;
187      console.error('Failed to check whether the flash mode is supported. errorCode = ' + err.code);
188    }
189    if(flashModeStatus) {
190      // 设置自动闪光灯模式
191      try {
192        captureSession.setFlashMode(camera.FlashMode.FLASH_MODE_AUTO);
193      } catch (error) {
194        let err = error as BusinessError;
195        console.error('Failed to set the flash mode. errorCode = ' + err.code);
196      }
197    }
198  }
199
200  // 判断是否支持连续自动变焦模式
201  let focusModeStatus: boolean = false;
202  try {
203    let status: boolean = captureSession.isFocusModeSupported(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO);
204    focusModeStatus = status;
205  } catch (error) {
206    let err = error as BusinessError;
207    console.error('Failed to check whether the focus mode is supported. errorCode = ' + err.code);
208  }
209
210  if (focusModeStatus) {
211    // 设置连续自动变焦模式
212    try {
213      captureSession.setFocusMode(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO);
214    } catch (error) {
215      let err = error as BusinessError;
216      console.error('Failed to set the focus mode. errorCode = ' + err.code);
217    }
218  }
219
220  // 获取相机支持的可变焦距比范围
221  let zoomRatioRange: Array<number> = [];
222  try {
223    zoomRatioRange = captureSession.getZoomRatioRange();
224  } catch (error) {
225    let err = error as BusinessError;
226    console.error('Failed to get the zoom ratio range. errorCode = ' + err.code);
227  }
228  if (zoomRatioRange.length <= 0) {
229    return;
230  }
231  // 设置可变焦距比
232  try {
233    captureSession.setZoomRatio(zoomRatioRange[0]);
234  } catch (error) {
235    let err = error as BusinessError;
236    console.error('Failed to set the zoom ratio value. errorCode = ' + err.code);
237  }
238  let photoCaptureSetting: camera.PhotoCaptureSetting = {
239    quality: camera.QualityLevel.QUALITY_LEVEL_HIGH,                                     // 设置图片质量高
240    rotation: camera.ImageRotation.ROTATION_0                                            // 设置图片旋转角度0
241  }
242  // 使用当前拍照设置进行拍照
243  photoOutput.capture(photoCaptureSetting, (err: BusinessError) => {
244    if (err) {
245      console.error('Failed to capture the photo ${err.message}');
246      return;
247    }
248    console.info('Callback invoked to indicate the photo capture request success.');
249  });
250  // 停止当前会话
251  captureSession.stop();
252
253  // 释放相机输入流
254  cameraInput.close();
255
256  // 释放预览输出流
257  previewOutput.release();
258
259  // 释放拍照输出流
260  photoOutput.release();
261
262  // 释放会话
263  captureSession.release();
264
265  // 会话置空
266  captureSession = undefined;
267}
268```
269
270