1# 拍照(ArkTS)
2
3拍照是相机的最重要功能之一,拍照模块基于相机复杂的逻辑,为了保证用户拍出的照片质量,在中间步骤可以设置分辨率、闪光灯、焦距、照片质量及旋转角度等信息。
4
5## 开发步骤
6
7详细的API说明请参考[Camera API参考](../../reference/apis-camera-kit/js-apis-camera.md)。
8
91. 导入image接口。创建拍照输出流的SurfaceId以及拍照输出的数据,都需要用到系统提供的image接口能力,导入image接口的方法如下。
10
11   ```ts
12   import { image } from '@kit.ImageKit';
13   import { camera } from '@kit.CameraKit';
14   import { fileIo as fs } from '@kit.CoreFileKit';
15   import { photoAccessHelper } from '@kit.MediaLibraryKit';
16   import { BusinessError } from '@kit.BasicServicesKit';
17   ```
18
192. 创建拍照输出流。
20
21   通过[CameraOutputCapability](../../reference/apis-camera-kit/js-apis-camera.md#cameraoutputcapability)类中的photoProfiles属性,可获取当前设备支持的拍照输出流,通过[createPhotoOutput](../../reference/apis-camera-kit/js-apis-camera.md#createphotooutput11)方法传入支持的某一个输出流及步骤一获取的SurfaceId创建拍照输出流。
22
23   ```ts
24   function getPhotoOutput(cameraManager: camera.CameraManager, cameraOutputCapability: camera.CameraOutputCapability): camera.PhotoOutput | undefined {
25     let photoProfilesArray: Array<camera.Profile> = cameraOutputCapability.photoProfiles;
26     if (!photoProfilesArray) {
27       console.error("createOutput photoProfilesArray == null || undefined");
28     }
29     let photoOutput: camera.PhotoOutput | undefined = undefined;
30     try {
31       photoOutput = cameraManager.createPhotoOutput(photoProfilesArray[0]);
32     } catch (error) {
33       let err = error as BusinessError;
34       console.error(`Failed to createPhotoOutput. error: ${JSON.stringify(err)}`);
35     }
36     return photoOutput;
37   }
38   ```
39
403. 设置拍照photoAvailable的回调,并将拍照的buffer保存为图片。
41
42    Context获取方式请参考:[获取UIAbility的上下文信息](../../application-models/uiability-usage.md#获取uiability的上下文信息)。
43
44    如需要在图库中看到所保存的图片、视频资源,需要将其保存到媒体库,保存方式请参考:[保存媒体库资源](../medialibrary/photoAccessHelper-savebutton.md)。
45
46    需要在[photoOutput.on('photoAvailable')](../../reference/apis-camera-kit/js-apis-camera.md#onphotoavailable11)接口获取到buffer时,将buffer在安全控件中保存到媒体库。
47   ```ts
48   let context = getContext(this);
49
50   function setPhotoOutputCb(photoOutput: camera.PhotoOutput) {
51   //设置回调之后,调用photoOutput的capture方法,就会将拍照的buffer回传到回调中
52     photoOutput.on('photoAvailable', (errCode: BusinessError, photo: camera.Photo): void => {
53        console.info('getPhoto start');
54        console.info(`err: ${JSON.stringify(errCode)}`);
55        if (errCode || photo === undefined) {
56          console.error('getPhoto failed');
57          return;
58        }
59        let imageObj: image.Image = photo.main;
60        imageObj.getComponent(image.ComponentType.JPEG, (errCode: BusinessError, component: image.Component): void => {
61          console.info('getComponent start');
62          if (errCode || component === undefined) {
63            console.error('getComponent failed');
64            return;
65          }
66          let buffer: ArrayBuffer;
67          if (component.byteBuffer) {
68            buffer = component.byteBuffer;
69          } else {
70            console.error('byteBuffer is null');
71            return;
72          }
73          // 如需要在图库中看到所保存的图片、视频资源,请使用用户无感的安全控件创建媒体资源。
74
75          // buffer处理结束后需要释放该资源,如果未正确释放资源会导致后续拍照获取不到buffer
76          imageObj.release();
77        });
78      });
79   }
80   ```
81
824. 参数配置。
83
84   配置相机的参数可以调整拍照的一些功能,包括闪光灯、变焦、焦距等。
85
86   ```ts
87   function configuringSession(photoSession: camera.PhotoSession): void {
88     // 判断设备是否支持闪光灯
89     let flashStatus: boolean = false;
90     try {
91       flashStatus = photoSession.hasFlash();
92     } catch (error) {
93       let err = error as BusinessError;
94       console.error(`Failed to hasFlash. error: ${JSON.stringify(err)}`);
95     }
96     console.info(`Returned with the flash light support status: ${flashStatus}`);
97     if (flashStatus) {
98       // 判断是否支持自动闪光灯模式
99       let flashModeStatus: boolean = false;
100       try {
101         let status: boolean = photoSession.isFlashModeSupported(camera.FlashMode.FLASH_MODE_AUTO);
102         flashModeStatus = status;
103       } catch (error) {
104         let err = error as BusinessError;
105         console.error(`Failed to check whether the flash mode is supported. error: ${JSON.stringify(err)}`);
106       }
107       if (flashModeStatus) {
108         // 设置自动闪光灯模式
109         try {
110           photoSession.setFlashMode(camera.FlashMode.FLASH_MODE_AUTO);
111         } catch (error) {
112           let err = error as BusinessError;
113           console.error(`Failed to set the flash mode. error: ${JSON.stringify(err)}`);
114         }
115       }
116     }
117     // 判断是否支持连续自动变焦模式
118     let focusModeStatus: boolean = false;
119     try {
120       let status: boolean = photoSession.isFocusModeSupported(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO);
121       focusModeStatus = status;
122     } catch (error) {
123       let err = error as BusinessError;
124       console.error(`Failed to check whether the focus mode is supported. error: ${JSON.stringify(err)}`);
125     }
126     if (focusModeStatus) {
127       // 设置连续自动变焦模式
128       try {
129         photoSession.setFocusMode(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO);
130       } catch (error) {
131         let err = error as BusinessError;
132         console.error(`Failed to set the focus mode. error: ${JSON.stringify(err)}`);
133       }
134     }
135     // 获取相机支持的可变焦距比范围
136     let zoomRatioRange: Array<number> = [];
137     try {
138       zoomRatioRange = photoSession.getZoomRatioRange();
139     } catch (error) {
140       let err = error as BusinessError;
141       console.error(`Failed to get the zoom ratio range. error: ${JSON.stringify(err)}`);
142     }
143     if (zoomRatioRange.length <= 0 ) {
144       return;
145     }
146     // 设置可变焦距比
147     try {
148       photoSession.setZoomRatio(zoomRatioRange[0]);
149     } catch (error) {
150       let err = error as BusinessError;
151       console.error(`Failed to set the zoom ratio value. error: ${JSON.stringify(err)}`);
152     }
153   }
154   ```
155
1565. 触发拍照。
157
158   通过photoOutput类的[capture](../../reference/apis-camera-kit/js-apis-camera.md#capture-2)方法,执行拍照任务。该方法有两个参数,第一个参数为拍照设置参数的setting,setting中可以设置照片的质量和旋转角度,第二参数为回调函数。
159
160   获取拍照旋转角度的方法为,通过通过[PhotoOutput](../../reference/apis-camera-kit/js-apis-camera.md#photooutput)类中的[getPhotoRotation](../../reference/apis-camera-kit/js-apis-camera.md#getphotorotation12)方法获取rotation实际的值
161
162   ```ts
163   function capture(captureLocation: camera.Location, photoOutput: camera.PhotoOutput): void {
164     let settings: camera.PhotoCaptureSetting = {
165       quality: camera.QualityLevel.QUALITY_LEVEL_HIGH,  // 设置图片质量高
166       rotation: camera.ImageRotation.ROTATION_0,  // 设置图片旋转角度的camera.ImageRotation.ROTATION_0是通过说明中获取拍照角度的getPhotoRotation方法获取的值进行设置
167       location: captureLocation,  // 设置图片地理位置
168       mirror: false  // 设置镜像使能开关(默认关)
169     };
170     photoOutput.capture(settings, (err: BusinessError) => {
171       if (err) {
172         console.error(`Failed to capture the photo. error: ${JSON.stringify(err)}`);
173         return;
174       }
175       console.info('Callback invoked to indicate the photo capture request success.');
176     });
177   }
178   ```
179
180## 状态监听
181
182在相机应用开发过程中,可以随时监听拍照输出流状态,包括拍照流开始、拍照帧的开始与结束、拍照输出流的错误。
183
184- 通过注册固定的captureStart回调函数获取监听拍照开始结果,photoOutput创建成功时即可监听,相机设备已经准备开始这次拍照时触发,该事件返回此次拍照的captureId。
185
186  ```ts
187  function onPhotoOutputCaptureStart(photoOutput: camera.PhotoOutput): void {
188    photoOutput.on('captureStartWithInfo', (err: BusinessError, captureStartInfo: camera.CaptureStartInfo) => {
189      if (err !== undefined && err.code !== 0) {
190        return;
191      }
192      console.info(`photo capture started, captureId : ${captureStartInfo.captureId}`);
193    });
194  }
195  ```
196
197- 通过注册固定的captureEnd回调函数获取监听拍照结束结果,photoOutput创建成功时即可监听,该事件返回结果为拍照完全结束后的相关信息[CaptureEndInfo](../../reference/apis-camera-kit/js-apis-camera.md#captureendinfo)。
198
199  ```ts
200  function onPhotoOutputCaptureEnd(photoOutput: camera.PhotoOutput): void {
201    photoOutput.on('captureEnd', (err: BusinessError, captureEndInfo: camera.CaptureEndInfo) => {
202      if (err !== undefined && err.code !== 0) {
203        return;
204      }
205      console.info(`photo capture end, captureId : ${captureEndInfo.captureId}`);
206      console.info(`frameCount : ${captureEndInfo.frameCount}`);
207    });
208  }
209  ```
210
211- 通过注册固定的captureReady回调函数获取监听可拍下一张结果,photoOutput创建成功时即可监听,当下一张可拍时触发,该事件返回结果为下一张可拍的相关信息。
212
213  ```ts
214  function onPhotoOutputCaptureReady(photoOutput: camera.PhotoOutput): void {
215    photoOutput.on('captureReady', (err: BusinessError) => {
216      if (err !== undefined && err.code !== 0) {
217        return;
218      }
219      console.info(`photo capture ready`);
220    });
221  }
222  ```
223
224- 通过注册固定的error回调函数获取监听拍照输出流的错误结果。回调返回拍照输出接口使用错误时的对应错误码,错误码类型参见[Camera错误码](../../reference/apis-camera-kit/js-apis-camera.md#cameraerrorcode)。
225
226  ```ts
227  function onPhotoOutputError(photoOutput: camera.PhotoOutput): void {
228    photoOutput.on('error', (error: BusinessError) => {
229      console.error(`Photo output error code: ${error.code}`);
230    });
231  }
232  ```
233