diff --git a/zh-cn/application-dev/media/Readme-CN.md b/zh-cn/application-dev/media/Readme-CN.md index 9050ccfd492d294e9537283f0b8bf5c5ec955704..b4dd333e70bfad8a72214ef3b87db4a49fc28e00 100755 --- a/zh-cn/application-dev/media/Readme-CN.md +++ b/zh-cn/application-dev/media/Readme-CN.md @@ -62,7 +62,8 @@ - 相机最佳实践 - [拍照实现方案](camera-shooting-case.md) - [录像实现方案](camera-recording-case.md) - - [人像模式拍照实现方案](camera-mode.md) + - [使用人像模式拍照](camera-mode.md) + - [双路预览](dual-channel-preview.md) - [性能提升方案(仅对系统应用开放)](camera-performance-improvement.md) - 图片 - [图片开发概述](image-overview.md) diff --git a/zh-cn/application-dev/media/camera-mode.md b/zh-cn/application-dev/media/camera-mode.md index 5bd22a536e87e5f9976508407bb17cb51d22153e..65d62f4bcb5ea2e7675b188cc9a074f5e741c3f1 100644 --- a/zh-cn/application-dev/media/camera-mode.md +++ b/zh-cn/application-dev/media/camera-mode.md @@ -1,4 +1,4 @@ -# 人像模式拍照实现方案 +# 人像模式拍照 ## 开发流程 diff --git a/zh-cn/application-dev/media/dual-channel-preview.md b/zh-cn/application-dev/media/dual-channel-preview.md new file mode 100644 index 0000000000000000000000000000000000000000..e5f29744c4d985085075bb1dabdbdd0bed99eeb4 --- /dev/null +++ b/zh-cn/application-dev/media/dual-channel-preview.md @@ -0,0 +1,151 @@ +# 双路预览 + +相机应用通过控制相机,实现图像显示(预览)、照片保存(拍照)、视频录制(录像)等基础操作。相机开发模型为Surface模型,即应用通过Surface进行数据传递,通过ImageReceiver的surface获取拍照流的数据、通过XComponent的surface获取预览流的数据。 + +如果要实现双路预览,即将拍照流改为预览流,将拍照流中的surface改为预览流的surface,通过ImageReceiver的surface创建previewOutput,其余流程与拍照流和预览流一致。 + +详细的API说明请参考[Camera API参考](../reference/apis/js-apis-camera.md)。 + +## 约束与限制 + +- 暂不支持动态添加流,即不能在没有调用session.stop的情况下,调用addOutput添加流。 +- 对ImageReceiver组件获取到的图像数据处理后,需要将对应的图像Buffer释放,确保Surface的BufferQueue正常轮转。 + +## 开发步骤 + +1. 导入image接口。 + + 创建双路预览流的SurfaceId,除XComponent组件的SurfaceId外,还需要使用ImageReceiver组件创建生成的SurfaceId,需要使用image模块提供的接口。 + + ```js + import image from '@ohos.multimedia.image'; + ``` + +2. 创建ImageReceiver组件Surface。 + + ```js + function getImageReceiverSurfaceId() { + let receiver = image.createImageReceiver(640, 480, 4, 8); + console.info('before ImageReceiver check'); + if (receiver !== undefined) { + console.info('ImageReceiver is ok'); + let ImageReceiverSurfaceId = receiver.getReceivingSurfaceId(); + console.info('ImageReceived id: ' + JSON.stringify(ImageReceiverSurfaceId)); + } else { + console.info('ImageReceiver is not ok'); + } + } + ``` + +3. 创建XComponent组件Surface。 + + 可参考[相机预览指导文档](camera-preview.md)。 + + ```js + // 创建XComponentController + mXComponentController: XComponentController = new XComponentController; + build() { + Flex() { + // 创建XComponent + XComponent({ + id: '', + type: 'surface', + libraryname: '', + controller: this.mXComponentController + }) + .onLoad(() => { + // 设置Surface宽高(1920*1080),预览尺寸设置参考前面 previewProfilesArray 获取的当前设备所支持的预览分辨率大小去设置 + this.mXComponentController.setXComponentSurfaceSize({surfaceWidth:1920,surfaceHeight:1080}); + // 获取Surface ID + globalThis.XComponentsurfaceId = this.mXComponentController.getXComponentSurfaceId(); + }) + .width('100%') + .height('100%') + } + } + ``` + +4. 实现双路预览。 + + 将步骤2、3生成的两路SurfaceId通过createPreviewOutput方法传递到相机服务,创建两路预览流,其余流程按照正常预览流程开发。 + + ```js + let cameraManager = camera.getCameraManager(globalThis.abilityContext); + let CamerasDevices = cameraManager.getSupportedCameras(); // 获取支持的相机设备对象 + + // 正常写法通过下面方式获取实际情况下的profile对象 + // let profiles = await this.cameraManager.getSupportedOutputCapability(CamerasDevices[cameraDeviceIndex]); // 获取对应相机设备profiles + // let previewProfiles = profiles.previewProfiles; + + // 预览流1 + let previewProfilesObj: camera.Profile; + previewProfilesObj.size.width = 640; + previewProfilesObj.size.height = 480; + previewProfilesObj.format = 3; + + // 预览流2 + let previewProfilesObj2: camera.Profile; + previewProfilesObj2.size.width = 640; + previewProfilesObj2.size.height = 480; + previewProfilesObj2.format = 3; + + // 创建 预览流1 输出对象 + let previewOutput = cameraManager.createPreviewOutput(previewProfilesObj, XComponentsurfaceId); + + // 创建 预览流2 输出对象 + let imageReceiverSurfaceId: string = await this.mReceiver.getReceivingSurfaceId(); + let previewOutput2 = cameraManager.createPreviewOutput(previewProfilesObj2, imageReceiverSurfaceId); + + // 创建cameraInput输出对象 + let cameraInput = cameraManager.createCameraInput(CamerasDevices[cameraDeviceIndex]); + + // 打开相机 + await cameraInput.open(); + + // 会话流程 + let captureSession = await cameraManager.createCaptureSession(); + + // 开始配置会话 + captureSession.beginConfig(); + + // 把CameraInput加入到会话 + captureSession.addInput(cameraInput); + + // 把 预览流1 加入到会话 + captureSession.addOutput(previewOutput) + + // 把 预览流2 加入到会话 + captureSession.addOutput(previewOutput2); + + // 提交配置信息 + await captureSession.commitConfig(); + + // 会话开始 + await captureSession.start(); + ``` + +5. 通过ImageReceiver实时获取预览图像。 + + 通过ImageReceiver组件中imageArrival事件监听获取底层返回的图像数据,详细的API说明请参考[Image API参考](../reference/apis/js-apis-image.md)。 + + ```js + this.receiver.on('imageArrival', () => { + this.receiver.readNextImage((err, nextImage: image.Image) => { + if (err || nextImage === undefined) { + return; + } + nextImage.getComponent(image.ComponentType.JPEG, (errMsg, img) => { + if (errMsg || img === undefined) { + return; + } + let buffer; + if (img.byteBuffer) { + buffer = img.byteBuffer; + } else { + return; + } + // do something...; + }) + }) + }) + ``` diff --git a/zh-cn/application-dev/media/figures/photographing-development-process.png b/zh-cn/application-dev/media/figures/photographing-development-process.png index c4e765c855692df379e6a866f45624279986dd8e..57fb4a9d152fb8faf6dfe87cf639a57bad3936db 100644 Binary files a/zh-cn/application-dev/media/figures/photographing-development-process.png and b/zh-cn/application-dev/media/figures/photographing-development-process.png differ diff --git a/zh-cn/application-dev/media/figures/recording-development-process.png b/zh-cn/application-dev/media/figures/recording-development-process.png index e983bc5c35f7aa9489798292ff0b8897a64ab6af..78be8cf562fd452012ffdab4ee1f9cd8c24b80c9 100644 Binary files a/zh-cn/application-dev/media/figures/recording-development-process.png and b/zh-cn/application-dev/media/figures/recording-development-process.png differ