diff --git a/AppScope/resources/base/element/string.json b/AppScope/resources/base/element/string.json index 89beb4728756f3bcc6eb4cd02df49d6d4055b0a7..a7437967f92d1ebd76dd33be837b81ad0ed736be 100644 --- a/AppScope/resources/base/element/string.json +++ b/AppScope/resources/base/element/string.json @@ -2,7 +2,7 @@ "string": [ { "name": "app_name", - "value": "camerademo" + "value": "Camera" } ] } diff --git a/README.en.md b/README.en.md new file mode 100644 index 0000000000000000000000000000000000000000..18e9059bd52eb4691ad0b3dae7645afb6b906924 --- /dev/null +++ b/README.en.md @@ -0,0 +1,89 @@ +# Collecting and Saving Camera Data + +### Overview + +This sample demonstrates +the preview and photographing functions of a camera app. + +### Preview + +| Preview | +|------------------------------------------------| +| ![auth](screenshot/device/cameraSample.en.png) | + +### How to Use +1. A message is displayed, asking you whether to allow Camera to use the camera. Touch **Allow**. +2. A message is displayed, asking you whether to allow Camera to use the microphone. Touch **Allow**. +3. Access the preview screen. It is displayed normally. After you touch **Photo**, the photo preview screen is displayed, showing the photo just taken. +4. Access the preview screen. It is displayed normally. After you touch **Photo**, the photo preview screen is displayed, showing the photo just taken. Exit the app and access Gallery. The first photo in Gallery is the photo just taken. +5. Touch the back button in the upper left corner of the photo preview screen to access the preview screen again. The preview is normal. +6. Access the preview screen. It is displayed normally. When you slide the zoom bar, a zoom value is displayed above the zoom bar, and the preview screen is zoomed in or out as you slide. +7. Access the preview screen. It is displayed normally. When you touch anywhere in the viewfinder, a focus area is displayed. +8. Access the preview screen. It is displayed normally. Touch **Video** to switch from photo mode to video mode. The preview is normal. Touch the video button to start recording, and video recording is normal. Touch the video button to stop recording. The video preview screen is displayed. Touch the video playback button. The video is played normally. + +### Project Directory + +``` +├──entry/src/main/ets +│ ├──common +│ │ ├──utils +│ │ │ ├──Logger.ets // Log utility +│ │ │ └──DateTimeUtil.ets // Date utility +│ │ │ └──GlobalContext.ets // Global context utility +│ │ └──Constants.ets // Enumeration of basic parameters, including the resolution, icon size, and button margin +│ ├──entryability +│ │ └──EntryAbility.ets // Entry ability lifecycle callbacks +│ ├──pages +│ │ ├──Index.ets // App entry, that is, the home page of the camera app +│ │ └──EditPage.ets // Photo preview and edit page +│ ├──mode +│ │ └──CameraService.ets // Camera initialization, resolution selection, opening the camera, and focal length adjustment +│ └──views +│ ├──ModeComponent.ets // Photographing and recording components +│ ├──FlashingLightComponent.ets // Flashlight components +│ ├──FocusAreaComponent.ets // Focus area logic calculation components +│ ├──FocusComponent.ets // Focus frame components +│ └──SlideComponent.ets // Zoom slider component, which can be used to change the focal length of the preview screen +└──entry/src/main/resources // Static resources + +``` + +### How to Implement +* The camera functional interfaces are implemented in **CameraService.ets**. For details about the source code, see [CameraService.ets](entry/src/main/ets/mode/CameraService.ets). + * Camera initialization is implemented in the **initCamera** function of **CameraService**. The process is as follows: Call **getCameraManager** to obtain a camera manager, call **getSupportedCameras** to obtain the supported camera devices, call **getSupportedOutputCapability** to obtain the supported camera capabilities, call **createPreviewOutput** to create a preview output, call **createCameraInput** to create a camera input, call **open** of **CameraInput** to open the camera input, call **onCameraStatusChange** to register a callback for the camera manager, and call **sessionFlowFn** to create and start a session. + * **sessionFlowFn** is an action for starting a session and enabling preview. The process is as follows: Call **createSession** to create a session, call **beginConfig** to start session configuration, call **addInput** to add a camera input to the session, call **addPreviewOutput** to add a preview output to the session, call **commitConfig** to commit the configuration, and call **start** to start the session. + * Camera release is initialized in the **releaseCamera** function of **CameraService**. The process is as follows: Call **release** of **output** to release the stream, call **close** of **CameraInput** to close the camera, and call **release** of **session** to release the session. + + * Callback interface settings: + * **onCameraStatusChange**: listens for the camera status. This callback is triggered when the camera is open, closed, or switched. + * **onCameraInputChange**: triggered when a camera input error occurs. + * **photoOutputCallBack**: triggered when photographing starts. + * **previewOutputCallBack**: triggered when preview starts. + * **onCaptureSessionErrorChange**: triggered when an exception occurs in the session. + +* Camera preview, photographing, and recording are implemented in **Index.ets** and **ModeComponent.ets**. For details about the source code, see [Index.ets](entry/src/main/ets/pages/Index.ets) and [ModeComponent.ets](entry/src/main/ets/views/ModeComponent.ets). + * Preview: enabled in the **onLoad** callback of the **XComponent** in **Index.ets**. In this callback, the **CameraService.initCamera** method is called to pass in the preview surface ID and camera device to start the camera and preview. + * Photographing: enabled in the **onClick** callback of the **Photo** button in **ModeComponent.ets**. In this callback, the **takePicture** method in the **CameraManager** object is called to implement the photographing operation. + +* Camera zoom is implemented in **SlideComponent.ets**. For details about the source code, see [SlideComponent.ets](entry/src/main/ets/views/SlideComponent.ets). + * Zoom: enabled in the **onChange** callback of the **Slider** component in **SlideComponent.ets**. In this callback, the **CameraService.setZoomRatioFn** method is used to adjust the zoom ratio. + +* Camera focus is implemented in **FocusAreaComponent.ets** and **FocusComponent.ets**. For details about the source code, see [FocusAreaComponent.ets](entry/src/main/ets/views/FocusAreaComponent.ets) and [FocusComponent.ets](entry/src/main/ets/views/FocusComponent.ets). + * Focus: enabled in the **onTouch** callback of the **FocusAreaComponent** in **FocusAreaComponent.ets**. In this callback, the **CameraService.setFocusPoint** method is used to adjust the focused image of the preview screen. + + +### Required Permissions + +* ohos.permission.CAMERA +* ohos.permission.MICROPHONE + +### Dependencies + +N/A + +### Constraints + +1. The sample app is supported only on Huawei phones running the standard system. +2. The HarmonyOS version must be HarmonyOS NEXT Developer Beta1 or later. +3. The DevEco Studio version must be DevEco Studio NEXT Developer Beta1 or later. +4. The HarmonyOS SDK version must be HarmonyOS NEXT Developer Beta1 or later. diff --git a/README.md b/README.md index caeba3e1577e9ef4daf4fa602b10934f7ad18aad..6876ba3727d27f80214b31eb2abe80aae377a04e 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,8 @@ | ![auth](screenshot/device/cameraSample.png) | 使用说明 -1. 弹出是否允许“CameraSample”使用相机?点击“允许” -2. 弹出是否允许“CameraSample”使用麦克风?点击“允许” +1. 弹出是否允许“Camera”使用相机?点击“允许” +2. 弹出是否允许“Camera”使用麦克风?点击“允许” 3. 进入预览界面,预览正常,点击拍照按钮,跳转到图片预览页面,跳转正常,图片预览页面显示当前所拍照的图片,显示正常 4. 进入预览界面,预览正常,点击拍照按钮,跳转到图片预览页面,跳转正常,图片预览页面显示当前所拍照的图片,显示正常,退出应用并进入图库应用,第一张图片显示为刚刚拍照的图片,拍照正常 5. 点击图片预览页面的左上角返回按钮,重新进入预览页面,预览正常 diff --git a/entry/src/main/ets/common/utils/DateTimeUtil.ets b/entry/src/main/ets/common/utils/DateTimeUtil.ets index e58d698606c5145f5715bedc5b8da5c8913b612b..eb5ff3ef7867b2b49430afd1ec1a6f5ace9e5f9f 100644 --- a/entry/src/main/ets/common/utils/DateTimeUtil.ets +++ b/entry/src/main/ets/common/utils/DateTimeUtil.ets @@ -14,12 +14,12 @@ */ /** - * @file 日期工具 + * @file DateTimeUtil */ export default class DateTimeUtil { /** - * 时分秒 + * Hour, minute, second */ getTime(): string { const DATETIME = new Date(); @@ -27,7 +27,7 @@ export default class DateTimeUtil { } /** - * 年月日 + * Specific date */ getDate(): string { const DATETIME = new Date(); @@ -35,16 +35,16 @@ export default class DateTimeUtil { } /** - * 日期不足两位补充0 - * @param value-数据值 + * If the date is less than two digits, add 0. + * @param value */ fill(value: number): string { let maxNumber = 9; return (value > maxNumber ? '' : '0') + value; } /** - * 录制时间定时器 - * @param millisecond-数据值 + * Recording Time Timer + * @param millisecond */ getVideoTime(millisecond: number): string { let millisecond2minute = 60000; @@ -54,7 +54,7 @@ export default class DateTimeUtil { return `${this.fill(minute)} : ${this.fill(second)}`; } /** - * 年月日格式修饰 + * Format Modification of Year Month Day. * @param year * @param month * @param date @@ -64,7 +64,7 @@ export default class DateTimeUtil { } /** - * 时分秒格式修饰 + * Hour minute second format modification. * @param hours * @param minutes * @param seconds diff --git a/entry/src/main/ets/entryability/EntryAbility.ets b/entry/src/main/ets/entryability/EntryAbility.ets index f1b527ce0014e16cb0e73fa307d1b36fa008dc23..58891ad731afba615be680995a091c1f9d7f3e90 100644 --- a/entry/src/main/ets/entryability/EntryAbility.ets +++ b/entry/src/main/ets/entryability/EntryAbility.ets @@ -73,7 +73,7 @@ export default class EntryAbility extends UIAbility { } /** - * 获取权限 + * Request permission */ requestPermissionsFn(): void { let atManager = abilityAccessCtrl.createAtManager(); diff --git a/entry/src/main/ets/mode/CameraService.ets b/entry/src/main/ets/mode/CameraService.ets index db564087dcc08cbca3cdcfdbf1d4440c26e00206..a72acb8b76078699eee8927eb8afd49940f21909 100644 --- a/entry/src/main/ets/mode/CameraService.ets +++ b/entry/src/main/ets/mode/CameraService.ets @@ -44,7 +44,7 @@ class CameraService { }; private curCameraDevice: camera.CameraDevice | undefined = undefined; private isRecording: boolean = false; - // 推荐拍照分辨率之一 + // One of the recommended camera resolutions. private photoProfileObj: camera.Profile = { format: 2000, size: { @@ -52,7 +52,7 @@ class CameraService { height: 1080 } }; - // 推荐预览分辨率之一 + // One of the recommended preview resolutions. private previewProfileObj: camera.Profile = { format: 1003, size: { @@ -60,7 +60,7 @@ class CameraService { height: 1080 } }; - // 推荐录像分辨率之一 + // One of the recommended video resolutions. private videoProfileObj: camera.VideoProfile = { format: 1003, size: { @@ -157,22 +157,22 @@ class CameraService { } /** - * 初始化相机功能 - * @param surfaceId - Surface 的 ID - * @param cameraDeviceIndex - 相机设备索引 - * @returns 无返回值 + * Initialize camera function + * @param surfaceId - Surface ID + * @param cameraDeviceIndex - Camera device index + * @returns No return value */ async initCamera(surfaceId: string, cameraDeviceIndex: number): Promise { Logger.debug(TAG, `initCamera cameraDeviceIndex: ${cameraDeviceIndex}`); try { await this.releaseCamera(); - // 获取相机管理器实例 + // Get Camera Manager instance. this.cameraManager = this.getCameraManagerFn(); if (this.cameraManager === undefined) { Logger.error(TAG, 'cameraManager is undefined'); return; } - // 获取支持指定的相机设备对象 + // Get support for specified camera device objects. this.cameras = this.getSupportedCamerasFn(this.cameraManager); if (this.cameras.length < 1 || this.cameras.length < cameraDeviceIndex + 1) { return; @@ -191,13 +191,13 @@ class CameraService { return; } this.previewProfileObj = previewProfile; - // 创建previewOutput输出对象 + // Create previewOutput output object. this.previewOutput = this.createPreviewOutputFn(this.cameraManager, this.previewProfileObj, surfaceId); if (this.previewOutput === undefined) { Logger.error(TAG, 'Failed to create the preview stream.'); return; } - // 监听预览事件 + // Monitor preview events. this.previewOutputCallBack(this.previewOutput); if (this.curSceneMode === camera.SceneMode.NORMAL_PHOTO) { let photoProfile = this.getPhotoProfile(cameraOutputCapability); @@ -206,7 +206,7 @@ class CameraService { return; } this.photoProfileObj = photoProfile; - // 创建photoOutPut输出对象 + // Create photoOutput output object. this.photoOutput = this.createPhotoOutputFn(this.cameraManager, this.photoProfileObj); if (this.photoOutput === undefined) { Logger.error(TAG, 'Failed to create the photo stream.'); @@ -226,30 +226,30 @@ class CameraService { } await this.prepareAVRecorder(); let videoSurfaceId = await this.avRecorder.getInputSurface(); - // 创建videoOutPut输出对象 + // Create videoOutput output object. this.videoOutput = this.createVideoOutputFn(this.cameraManager, this.videoProfileObj, videoSurfaceId); if (this.videoOutput === undefined) { Logger.error(TAG, 'Failed to create the video stream.'); return; } } - // 创建cameraInput输出对象 + // Create cameraInput output object. this.cameraInput = this.createCameraInputFn(this.cameraManager, this.curCameraDevice); if (this.cameraInput === undefined) { Logger.error(TAG, 'Failed to create the camera input.'); return; } - // 打开相机 + // Open the camera. let isOpenSuccess = await this.cameraInputOpenFn(this.cameraInput); if (!isOpenSuccess) { Logger.error(TAG, 'Failed to open the camera.'); return; } - // 镜头状态回调 + // Camera status callback. this.onCameraStatusChange(this.cameraManager); - // 监听CameraInput的错误事件 + // Monitor error events from CameraInput. this.onCameraInputChange(this.cameraInput, this.curCameraDevice); - // 会话流程 + // Conversation process. await this.sessionFlowFn(this.cameraManager, this.cameraInput, this.previewOutput, this.photoOutput, this.videoOutput); } catch (error) { @@ -259,7 +259,7 @@ class CameraService { } /** - * 获取可变焦距范围 + * Obtain variable focal length range. */ getZoomRatioRange(): Array { let zoomRatioRange: Array = []; @@ -270,11 +270,11 @@ class CameraService { } /** - * 变焦 + * Zoom */ setZoomRatioFn(zoomRatio: number): void { Logger.info(TAG, `setZoomRatioFn value ${zoomRatio}`); - // 获取支持的变焦范围 + // Obtain supported zoom range. try { let zoomRatioRange = this.getZoomRatioRange(); Logger.info(TAG, `getZoomRatioRange success: ${JSON.stringify(zoomRatioRange)}`); @@ -293,7 +293,7 @@ class CameraService { } /** - * 以指定参数触发一次拍照 + * Trigger a photo with specified parameters. */ async takePicture(): Promise { Logger.info(TAG, 'takePicture start'); @@ -322,7 +322,7 @@ class CameraService { } /** - * 释放会话及其相关参数 + * Release the session and its related parameters. */ async releaseCamera(): Promise { Logger.info(TAG, 'releaseCamera is called'); @@ -380,7 +380,7 @@ class CameraService { } /** - * 获取相机管理器实例 + * Get Camera Manager instance. */ getCameraManagerFn(): camera.CameraManager | undefined { if (this.cameraManager) { @@ -398,7 +398,7 @@ class CameraService { } /** - * 获取支持指定的相机设备对象 + * Get support for specified camera device objects. */ getSupportedCamerasFn(cameraManager: camera.CameraManager): Array { let supportedCameras: Array = []; @@ -413,7 +413,7 @@ class CameraService { } /** - * 创建previewOutput输出对象 + * Create previewOutput output object. */ createPreviewOutputFn(cameraManager: camera.CameraManager, previewProfileObj: camera.Profile, surfaceId: string): camera.PreviewOutput | undefined { @@ -429,7 +429,7 @@ class CameraService { } /** - * 创建photoOutPut输出对象 + * Create photoOutPut output object. */ createPhotoOutputFn(cameraManager: camera.CameraManager, photoProfileObj: camera.Profile): camera.PhotoOutput | undefined { @@ -445,7 +445,7 @@ class CameraService { } /** - * 创建videoOutPut输出对象 + * Create videoOutPut output object. */ createVideoOutputFn(cameraManager: camera.CameraManager, videoProfileObj: camera.VideoProfile, surfaceId: string): camera.VideoOutput | undefined { @@ -461,7 +461,7 @@ class CameraService { } /** - * 创建cameraInput输出对象 + * Create cameraInput output object. */ createCameraInputFn(cameraManager: camera.CameraManager, cameraDevice: camera.CameraDevice): camera.CameraInput | undefined { @@ -478,7 +478,7 @@ class CameraService { } /** - * 打开相机 + * Open the camera. */ async cameraInputOpenFn(cameraInput: camera.CameraInput): Promise { let isOpenSuccess = false; @@ -494,13 +494,12 @@ class CameraService { } /** - * 会话流程 + * Conversation process. */ async sessionFlowFn(cameraManager: camera.CameraManager, cameraInput: camera.CameraInput, previewOutput: camera.PreviewOutput, photoOutput: camera.PhotoOutput | undefined, videoOutput: camera.VideoOutput | undefined): Promise { try { - // 创建CaptureSession实例 if (this.curSceneMode === camera.SceneMode.NORMAL_PHOTO) { this.session = cameraManager.createSession(this.curSceneMode) as camera.PhotoSession; } else if (this.curSceneMode === camera.SceneMode.NORMAL_VIDEO) { @@ -510,35 +509,27 @@ class CameraService { return; } this.onSessionErrorChange(this.session); - // 开始配置会话 this.session.beginConfig(); - // 把CameraInput加入到会话 this.session.addInput(cameraInput); - // 把previewOutput加入到会话 this.session.addOutput(previewOutput); if (this.curSceneMode === camera.SceneMode.NORMAL_PHOTO) { if (photoOutput === undefined) { return; } - // 拍照监听事件 this.photoOutputCallBack(photoOutput); - // 把photoOutPut加入到会话 this.session.addOutput(photoOutput); } else if (this.curSceneMode === camera.SceneMode.NORMAL_VIDEO) { if (videoOutput === undefined) { return; } - // 把photoOutPut加入到会话 this.session.addOutput(videoOutput); } - // 提交配置信息 await this.session.commitConfig(); if (this.curSceneMode === camera.SceneMode.NORMAL_VIDEO) { this.setVideoStabilizationFn(this.session as camera.VideoSession, camera.VideoStabilizationMode.MIDDLE); } this.updateSliderValue(); this.setFocusMode(camera.FocusMode.FOCUS_MODE_AUTO); - // 开始会话工作 await this.session.start(); Logger.info(TAG, 'sessionFlowFn success'); } catch (error) { @@ -548,7 +539,7 @@ class CameraService { } setVideoStabilizationFn(session: camera.VideoSession, videoStabilizationMode: camera.VideoStabilizationMode): void { - // 查询是否支持指定的视频防抖模式 + // Check if the specified video stabilization mode is supported. let isVideoStabilizationModeSupported: boolean = session.isVideoStabilizationModeSupported(videoStabilizationMode); if (isVideoStabilizationModeSupported) { session.setVideoStabilizationMode(videoStabilizationMode); @@ -557,7 +548,7 @@ class CameraService { } /** - * 更新滑动条数据 + * Update slider data. */ updateSliderValue(): void { let zoomRatioRange = this.getZoomRatioRange(); @@ -575,25 +566,21 @@ class CameraService { } /** - * 监听拍照事件 + * Monitoring and photography events. */ photoOutputCallBack(photoOutput: camera.PhotoOutput): void { try { - // 监听拍照开始 photoOutput.on('captureStartWithInfo', (err: BusinessError, captureStartInfo: camera.CaptureStartInfo): void => { Logger.info(TAG, `photoOutputCallBack captureStartWithInfo success: ${JSON.stringify(captureStartInfo)}`); }); - // 监听拍照帧输出捕获 photoOutput.on('frameShutter', (err: BusinessError, frameShutterInfo: camera.FrameShutterInfo): void => { Logger.info(TAG, `photoOutputCallBack frameShutter captureId: ${frameShutterInfo.captureId}, timestamp: ${frameShutterInfo.timestamp}`); }); - // 监听拍照结束 photoOutput.on('captureEnd', (err: BusinessError, captureEndInfo: camera.CaptureEndInfo): void => { Logger.info(TAG, `photoOutputCallBack captureEnd captureId: ${captureEndInfo.captureId}, frameCount: ${captureEndInfo.frameCount}`); }); - // 监听拍照异常 photoOutput.on('error', (data: BusinessError): void => { Logger.info(TAG, `photoOutPut data: ${JSON.stringify(data)}`); }); @@ -611,7 +598,7 @@ class CameraService { } /** - * 监听预览事件 + * Monitor preview events. */ previewOutputCallBack(previewOutput: camera.PreviewOutput): void { Logger.info(TAG, 'previewOutputCallBack is called'); @@ -631,19 +618,19 @@ class CameraService { } /** - * 注册相机状态变化的回调函数 - * @param err - 错误信息(如果有) - * @param cameraStatusInfo - 相机状态信息 - * @returns 无返回值 + * Callback function for registering camera status changes. + * @param err + * @param cameraStatusInfo + * @returns */ registerCameraStatusChange(err: BusinessError, cameraStatusInfo: camera.CameraStatusInfo): void { Logger.info(TAG, `cameraId: ${cameraStatusInfo.camera.cameraId},status: ${cameraStatusInfo.status}`); } /** - * 监听相机状态变化 - * @param cameraManager - 相机管理器对象 - * @returns 无返回值 + * Monitor camera status changes. + * @param cameraManager + * @returns */ onCameraStatusChange(cameraManager: camera.CameraManager): void { Logger.info(TAG, 'onCameraStatusChange is called'); @@ -655,8 +642,8 @@ class CameraService { } /** - * 停止监听相机状态变化 - * @returns 无返回值 + * Stop monitoring camera status changes. + * @returns */ offCameraStatusChange(): void { Logger.info(TAG, 'offCameraStatusChange is called'); @@ -664,10 +651,10 @@ class CameraService { } /** - * 监听相机输入变化 - * @param cameraInput - 相机输入对象 - * @param cameraDevice - 相机设备对象 - * @returns 无返回值 + * Monitor camera input changes. + * @param cameraInput + * @param cameraDevice + * @returns */ onCameraInputChange(cameraInput: camera.CameraInput, cameraDevice: camera.CameraDevice): void { Logger.info(TAG, `onCameraInputChange is called`); @@ -681,9 +668,8 @@ class CameraService { } /** - * 监听捕获会话错误变化 - * @param session - 相机捕获会话对象 - * @returns 无返回值 + * @param session + * @returns */ onSessionErrorChange(session: camera.PhotoSession | camera.VideoSession): void { try { @@ -742,9 +728,6 @@ class CameraService { }); } - /** - * 启动录制 - */ async startVideo(): Promise { Logger.info(TAG, 'startVideo is called'); try { @@ -758,9 +741,6 @@ class CameraService { Logger.info(TAG, 'startVideo End of call'); } - /** - * 停止录制 - */ async stopVideo(): Promise { Logger.info(TAG, 'stopVideo is called'); if (!this.isRecording) { @@ -783,37 +763,32 @@ class CameraService { } /** - * 闪关灯 + * Flashing lights */ hasFlashFn(flashMode: camera.FlashMode): void { - // 检测是否有闪关灯 let hasFlash = this.session?.hasFlash(); Logger.debug(TAG, `hasFlash success, hasFlash: ${hasFlash}`); - // 检测闪光灯模式是否支持 let isFlashModeSupported = this.session?.isFlashModeSupported(flashMode); Logger.debug(TAG, `isFlashModeSupported success, isFlashModeSupported: ${isFlashModeSupported}`); - // 设置闪光灯模式 this.session?.setFlashMode(flashMode); } /** - * 焦点 + * Set the current focus */ setFocusPoint(point: camera.Point): void { - // 设置焦点 this.session?.setFocusPoint(point); Logger.info(TAG, `setFocusPoint success point: ${JSON.stringify(point)}`); - // 获取当前的焦点 + // Get the current focus let nowPoint: camera.Point | undefined = undefined; nowPoint = this.session?.getFocusPoint(); Logger.info(TAG, `getFocusPoint success, nowPoint: ${JSON.stringify(nowPoint)}`); } /** - * 曝光区域 + * Exposure area */ isMeteringPoint(point: camera.Point): void { - // 获取当前曝光模式 let exposureMode: camera.ExposureMode | undefined = undefined; exposureMode = this.session?.getExposureMode(); Logger.info(TAG, `getExposureMode success, exposureMode: ${exposureMode}`); @@ -824,27 +799,20 @@ class CameraService { } /** - * 曝光补偿 + * Exposure compensation */ isExposureBiasRange(exposureBias: number): void { Logger.debug(TAG, `setExposureBias value ${exposureBias}`); - // 查询曝光补偿范围 let biasRangeArray: Array | undefined = []; biasRangeArray = this.session?.getExposureBiasRange(); Logger.debug(TAG, `getExposureBiasRange success, biasRangeArray: ${JSON.stringify(biasRangeArray)}`); - // 设置曝光补偿 this.session?.setExposureBias(exposureBias); } - /** - * 对焦模式 - */ setFocusMode(focusMode: camera.FocusMode): void { - // 检测对焦模式是否支持 Logger.info(TAG, `setFocusMode is called`); let isSupported = this.session?.isFocusModeSupported(focusMode); Logger.info(TAG, `setFocusMode isSupported: ${isSupported}`); - // 设置对焦模式 if (!isSupported) { return; } diff --git a/entry/src/main/ets/pages/Index.ets b/entry/src/main/ets/pages/Index.ets index dd9a912c0ad5b34664c2ad8e0217615742a00eaa..fc7952320b62d70e73b92e7f39ff1daef31a6f02 100644 --- a/entry/src/main/ets/pages/Index.ets +++ b/entry/src/main/ets/pages/Index.ets @@ -29,13 +29,13 @@ const TAG = 'Index'; @Entry @Component struct Index { - // 主页面是否显示 + // Is the main page displayed. @StorageLink('isShow') isShow: boolean = false; @StorageLink('isOpenEditPage') isOpenEditPage: boolean = false; // Flash Mode @State flashMode: camera.FlashMode = camera.FlashMode.FLASH_MODE_CLOSE; @State focusPointBol: boolean = false; - // 曝光区域手指点击坐标 + // Finger click coordinates in the exposure area. @State focusPointVal: Array = [0, 0]; @State xComponentAspectRatio: number = 1; private mXComponentController: XComponentController = new XComponentController(); @@ -96,13 +96,13 @@ struct Index { .width(px2vp(Constants.X_COMPONENT_SURFACE_HEIGHT)) .height(px2vp(Constants.X_COMPONENT_SURFACE_WIDTH)) } - // 曝光框和对焦框 + // Exposure frame and focus frame. FocusComponent({ focusPointBol: $focusPointBol, focusPointVal: $focusPointVal }) - // 曝光对焦手指点击区域 + // Exposure focus finger click area. FocusAreaComponent({ focusPointBol: $focusPointBol, focusPointVal: $focusPointVal, @@ -112,11 +112,10 @@ struct Index { // slide SlideComponent() - // 拍照 + // photograph ModeComponent() Row({ space: Constants.ROW_SPACE_24 }) { - // 闪光灯 FlashingLightComponent({ flashMode: $flashMode }) diff --git a/entry/src/main/ets/views/FlashingLightComponent.ets b/entry/src/main/ets/views/FlashingLightComponent.ets index 8df784262cbef57ba4c98c8bfd37d4c045b90729..6b631c8e6de2a5607d52d1819d77845ab144e80f 100644 --- a/entry/src/main/ets/views/FlashingLightComponent.ets +++ b/entry/src/main/ets/views/FlashingLightComponent.ets @@ -19,10 +19,8 @@ import CameraService from '../mode/CameraService'; const TAG: string = 'FlashingLightComponent'; -// 闪关灯页面 @Component export struct FlashingLightComponent { - // 闪光灯模式 @Link @Watch('flashModeChange') flashMode: camera.FlashMode; @State flashIconResource: Resource = $r('app.media.ic_camera_public_flash_off'); diff --git a/entry/src/main/ets/views/FocusAreaComponent.ets b/entry/src/main/ets/views/FocusAreaComponent.ets index fb1df1712fae6881a55c20e2233abe37a662b08a..4a9cd823002d682566a0bc5c3860ed3cf9bf557b 100644 --- a/entry/src/main/ets/views/FocusAreaComponent.ets +++ b/entry/src/main/ets/views/FocusAreaComponent.ets @@ -18,14 +18,12 @@ import CameraService from '../mode/CameraService'; const TAG: string = 'FocusAreaComponent'; -// 对焦区域 @Component export struct FocusAreaComponent { @Link focusPointBol: boolean; @Link focusPointVal: Array; @Prop xComponentWidth: number; @Prop xComponentHeight: number; - // 对焦区域显示框定时器 private areaTimer: number = -1; private focusFrameDisplayDuration: number = 3500; @@ -40,7 +38,10 @@ export struct FocusAreaComponent { this.focusPointBol = true; this.focusPointVal[0] = e.touches[0].windowX; this.focusPointVal[1] = e.touches[0].windowY; - // 归一化焦点。 设置的焦点与相机sensor角度和窗口方向有关(相机sensor角度可通过CameraDevice的cameraOrientation属性获取),下面焦点是以竖屏窗口,相机sensor角度为90度场景下的焦点设置 + // Normalized focus. + // The focus set is related to the camera sensor angle and window direction + // (the camera sensor angle can be obtained through the CameraOrientation property of CameraDevice). + // The following focus is set for a vertical window with a camera sensor angle of 90 degrees in the scene. CameraService.setFocusPoint({ x: e.touches[0].y / this.xComponentHeight, y: 1 - (e.touches[0].x / this.xComponentWidth) diff --git a/entry/src/main/ets/views/FocusComponent.ets b/entry/src/main/ets/views/FocusComponent.ets index 340bab409fcc4f20938ee425e921547c98ed1d30..9a1af0e9d80328ddcc9f51dea06c446edefa400d 100644 --- a/entry/src/main/ets/views/FocusComponent.ets +++ b/entry/src/main/ets/views/FocusComponent.ets @@ -13,7 +13,6 @@ * limitations under the License. */ -// 曝光选择 @Component export struct FocusComponent { @Link focusPointBol: boolean; @@ -27,7 +26,7 @@ export struct FocusComponent { build() { if (this.focusPointBol) { Row() { - // 对焦框 + // Focusing frame Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.SpaceBetween }) { Flex({ justifyContent: FlexAlign.SpaceBetween }) { Row() { diff --git a/entry/src/main/ets/views/ModeComponent.ets b/entry/src/main/ets/views/ModeComponent.ets index 10dd3842a83221a0066593e13b73cfffa6916236..ad2480af4cba7a41465b627ca61b64707d42a318 100644 --- a/entry/src/main/ets/views/ModeComponent.ets +++ b/entry/src/main/ets/views/ModeComponent.ets @@ -55,7 +55,6 @@ export struct ModeComponent { onJumpClick(): void { GlobalContext.get().setObject('sceneMode', this.sceneMode); - // 目标url router.pushUrl({ url: 'pages/EditPage' }, router.RouterMode.Single, (err) => { if (err) { Logger.error(TAG, `Invoke pushUrl failed, code is ${err.code}, message is ${err.message}`); @@ -69,7 +68,7 @@ export struct ModeComponent { Column() { Row({ space: Constants.COLUMN_SPACE_24 }) { Column() { - Text('拍照') + Text($r('app.string.take_photos')) .fontSize(Constants.FONT_SIZE_14) .fontColor(Color.White) } @@ -87,9 +86,8 @@ export struct ModeComponent { await CameraService.initCamera(surfaceId, cameraDeviceIndex); }) - // 录像 Column() { - Text('录像') + Text($r('app.string.videotape')) .fontSize(Constants.FONT_SIZE_14) .fontColor(Color.White) } @@ -117,7 +115,7 @@ export struct ModeComponent { } .width($r('app.string.200px')) - // 拍照-录像 按键 + // Photo or video button Column() { if (!this.isRecording) { Row() { @@ -148,7 +146,6 @@ export struct ModeComponent { } } else { Row() { - // 录像停止键 Button() { Image($r('app.media.ic_camera_video_close')) .size({ width: Constants.IMAGE_SIZE, height: Constants.IMAGE_SIZE }) @@ -172,7 +169,7 @@ export struct ModeComponent { } } - // 前后置摄像头切换 + // Switching between front and rear cameras. Column() { Row() { Button() { diff --git a/entry/src/main/ets/views/SlideComponent.ets b/entry/src/main/ets/views/SlideComponent.ets index d537f5cdddcbcbf754a1c08877bdddb659531df8..2a0ae970736836b7ab6f783d7f6927711694fa4c 100644 --- a/entry/src/main/ets/views/SlideComponent.ets +++ b/entry/src/main/ets/views/SlideComponent.ets @@ -19,10 +19,8 @@ import { Constants } from '../common/Constants'; const TAG: string = 'SlideComponent'; -// 变焦组件 @Component export struct SlideComponent { - // slide滑块 @StorageLink('zoomRatio') zoomRatio: number = 1; @StorageLink('sliderValue') sliderValue: SliderValue | undefined = undefined; private fractionDigits = 2; diff --git a/entry/src/main/module.json5 b/entry/src/main/module.json5 index afb756abc55771d5480d20b893ef51739fbdb567..54e265f61ece6bd1931f63415367ee4ce0db5880 100644 --- a/entry/src/main/module.json5 +++ b/entry/src/main/module.json5 @@ -35,7 +35,7 @@ "requestPermissions": [ { "name": "ohos.permission.CAMERA", - "reason": "$string:reason", + "reason": "$string:reason_camera", "usedScene": { "abilities": [ "EntryAbility" @@ -45,7 +45,7 @@ }, { "name": "ohos.permission.MICROPHONE", - "reason": "$string:reason", + "reason": "$string:reason_microphone", "usedScene": { "abilities": [ "EntryAbility" diff --git a/entry/src/main/resources/base/element/string.json b/entry/src/main/resources/base/element/string.json index d9e6dd33511401634158f96f013bf05e73a94359..e6f2537b96a6a289b2ef3b4698a8d6e50c7050d0 100644 --- a/entry/src/main/resources/base/element/string.json +++ b/entry/src/main/resources/base/element/string.json @@ -10,11 +10,15 @@ }, { "name": "EntryAbility_label", - "value": "cameraDemo" + "value": "Camera" }, { - "name": "reason", - "value": "test" + "name": "reason_camera", + "value": "Allow the app to use the camera for photo and video recording scenarios" + }, + { + "name": "reason_microphone", + "value": "Allow the app to use the microphone for video recording scenarios" }, { "name": "200px", @@ -42,7 +46,15 @@ }, { "name": "save", - "value": "保存" + "value": "save" + }, + { + "name": "take_photos", + "value": "Photo" + }, + { + "name": "videotape", + "value": "Video" } ] } \ No newline at end of file diff --git a/entry/src/main/resources/en_US/element/string.json b/entry/src/main/resources/en_US/element/string.json index 7d880a88a2bb73f25219e811412a52214ae9926b..e6f2537b96a6a289b2ef3b4698a8d6e50c7050d0 100644 --- a/entry/src/main/resources/en_US/element/string.json +++ b/entry/src/main/resources/en_US/element/string.json @@ -10,11 +10,15 @@ }, { "name": "EntryAbility_label", - "value": "cameraDemo" + "value": "Camera" }, { - "name": "reason", - "value": "test" + "name": "reason_camera", + "value": "Allow the app to use the camera for photo and video recording scenarios" + }, + { + "name": "reason_microphone", + "value": "Allow the app to use the microphone for video recording scenarios" }, { "name": "200px", @@ -43,6 +47,14 @@ { "name": "save", "value": "save" + }, + { + "name": "take_photos", + "value": "Photo" + }, + { + "name": "videotape", + "value": "Video" } ] } \ No newline at end of file diff --git a/entry/src/main/resources/zh_CN/element/string.json b/entry/src/main/resources/zh_CN/element/string.json index 1908692b7a42a27f046a3a9e22c8d48576686d97..3d7e78aa68b9382e205d21a24ae377c26a4977ea 100644 --- a/entry/src/main/resources/zh_CN/element/string.json +++ b/entry/src/main/resources/zh_CN/element/string.json @@ -13,8 +13,12 @@ "value": "cameraDemo" }, { - "name": "reason", - "value": "test" + "name": "reason_camera", + "value": "允许应用在拍照录像场景中使用相机" + }, + { + "name": "reason_microphone", + "value": "允许应用在录像场景中使用麦克风" }, { "name": "200px", @@ -43,6 +47,14 @@ { "name": "save", "value": "保存" + }, + { + "name": "take_photos", + "value": "拍照" + }, + { + "name": "videotape", + "value": "录像" } ] } \ No newline at end of file diff --git a/screenshot/device/cameraSample.en.png b/screenshot/device/cameraSample.en.png new file mode 100644 index 0000000000000000000000000000000000000000..10d03d9c3f4a80979ecbd565e54b38db2206441d Binary files /dev/null and b/screenshot/device/cameraSample.en.png differ