HarmonyOS鸿蒙Next中拍照比较慢的原因及优化方案

HarmonyOS鸿蒙Next中拍照比较慢的原因及优化方案 通过以下的代码获取拍照后的照片,速度比较慢,从capture后至少3秒才会回调获取到照片,照片大小 1440*1920

photoOutput.on("photoAvailable",
async (errCode: BusinessError, photo: camera.Photo): Promise<void> => {
})

photoOutput: 是camera.PhotoOutput

有没有什么办法capture后可以更快的获取照片,2秒左右,提升用户体验

3 回复

import camera from ‘@ohos.multimedia.camera’; import image from ‘@ohos.multimedia.image’; import abilityAccessCtrl from ‘@ohos.abilityAccessCtrl’; import common from ‘@ohos.app.ability.common’; import fs from ‘@ohos.file.fs’; import { BusinessError } from ‘@kit.BasicServicesKit’; import PhotoAccessHelper from ‘@ohos.file.photoAccessHelper’; import { ifaa } from ‘@kit.OnlineAuthenticationKit’;

@Entry @Component struct Index3 { @State message: string = ‘Hello World’ private mXComponentController: XComponentController = new XComponentController; private surfaceId: string = ‘-1’; @State imgUrl: PixelMap | undefined = undefined; private context: ESObject = undefined private previewProfilesObj2: camera.Profile | undefined = undefined; private receiver: image.ImageReceiver | undefined = undefined; @State pixma: PixelMap | undefined = undefined @State photoOutput: camera.PhotoOutput | undefined = undefined;

aboutToAppear() { let context = getContext() as common.UIAbilityContext; abilityAccessCtrl.createAtManager().requestPermissionsFromUser(context, [‘ohos.permission.CAMERA’]).then(() => { this.createDualChannelPreview(this.surfaceId); }); }

onPageShow(): void { this.createDualChannelPreview(this.surfaceId); }

async createDualChannelPreview(XComponentSurfaceId: string): Promise<void> { let cameraManager = await camera.getCameraManager(getContext() as ESObject); let camerasDevices: Array<camera.CameraDevice> = cameraManager.getSupportedCameras(); let profiles: camera.CameraOutputCapability = cameraManager.getSupportedOutputCapability(camerasDevices[0]); let previewProfiles: Array<camera.Profile> = profiles.previewProfiles; this.previewProfilesObj2 = previewProfiles[0]; this.receiver = image.createImageReceiver(this.previewProfilesObj2.size.width, this.previewProfilesObj2.size.height, 2000, 8);

let imageReceiverSurfaceId: string = await this.receiver.getReceivingSurfaceId();
let previewOutput2: camera.PreviewOutput = cameraManager.createPreviewOutput(this.previewProfilesObj2, imageReceiverSurfaceId);

let photoProfilesArray: Array<camera.Profile> = profiles.photoProfiles;
try {
  this.photoOutput = cameraManager.createPhotoOutput(photoProfilesArray[0]);
} catch (error) {
  let err = error as BusinessError;
  console.error('Failed to createPhotoOutput errorCode = ' + err.code);
}

if (this.photoOutput === undefined) {
  return;
}

let cameraInput: camera.CameraInput = cameraManager.createCameraInput(camerasDevices[0]);
await cameraInput.open();

let captureSession: camera.CaptureSession = cameraManager.createCaptureSession();
captureSession.beginConfig();
captureSession.addInput(cameraInput);
captureSession.addOutput(previewOutput2);
try {
  captureSession.addOutput(this.photoOutput);
} catch (error) {
  let err = error as BusinessError;
  console.error('Failed to addOutput(photoOutput). errorCode = ' + err.code);
}
await captureSession.commitConfig();
await captureSession.start();
this.onImageArrival(this.receiver);
this.setPhotoOutputCb(this.photoOutput)

}

async savePicture(buffer: ArrayBuffer, img: image.Image) { const context = getContext(this); let photoAccessHelper: PhotoAccessHelper.PhotoAccessHelper = PhotoAccessHelper.getPhotoAccessHelper(context); let options: PhotoAccessHelper.CreateOptions = { title: Date.now().toString() }; let photoUri: string = await photoAccessHelper.createAsset(PhotoAccessHelper.PhotoType.IMAGE, ‘jpg’, options); let file: fs.File = fs.openSync(photoUri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); await fs.write(file.fd, buffer); fs.closeSync(file); img.release(); }

setPhotoOutputCb(photoOutput: camera.PhotoOutput) { photoOutput.on(‘photoAvailable’, (errCode: BusinessError, photo: camera.Photo): void => { console.info(‘getPhoto start’); console.info(err: ${JSON.stringify(errCode)}); if (errCode || photo === undefined) { console.error(‘getPhoto failed’); return; } let imageObj = photo.main; imageObj.getComponent(image.ComponentType.JPEG, (errCode: BusinessError, component: image.Component): void => { console.info(‘getComponent start’); if (errCode || component === undefined) { console.error(‘getComponent failed’); return; } let buffer: ArrayBuffer; if (component.byteBuffer) { buffer = component.byteBuffer; if (component.byteBuffer as ArrayBuffer) { let sourceOptions: image.SourceOptions = { sourceDensity: 120, sourceSize: { height: 240, width: 320 }, }; try { let imageResource = image.createImageSource(component.byteBuffer); imageResource.createPixelMap({}).then((res)=>{ this.pixma = res; }); } catch (error) { let err = error as BusinessError; console.error('Failed to addOutput(photoOutput). errorCode = ’ + err.code); } } else { return; } } else { console.error(‘byteBuffer is null’); return; } this.savePicture(buffer, imageObj); }); }); }

async onImageArrival(receiver: image.ImageReceiver): Promise<void> { receiver.on(‘imageArrival’, () => { console.error(“imageArrival callback”); receiver.readLatestImage((err, nextImage: image.Image) => { if (err || nextImage === undefined) { return; } nextImage.getComponent(image.ComponentType.JPEG, async (err, imgComponent: image.Component) => { if (err || imgComponent === undefined) { return; } this.saveImageToFile(imgComponent.byteBuffer); if (imgComponent.byteBuffer as ArrayBuffer) { let sourceOptions: image.SourceOptions = { sourceDensity: 120, sourcePixelFormat: 8, // NV21 sourceSize: { height: this.previewProfilesObj2!.size.height, width: this.previewProfilesObj2!.size.width }, }; let imageResource = image.createImageSource(imgComponent.byteBuffer, sourceOptions); let decodingOptions : image.DecodingOptions = { editable: true, desiredPixelFormat: 3, }; imageResource.createPixelMap(decodingOptions).then((res)=>{ this.imgUrl = res; }); } else { return; } nextImage.release(); }) }) }) }

saveImageToFile(data: ArrayBuffer) { const context = getContext(this); let filePath = context.tempDir + “/test.jpg”; console.info("path is " + filePath); let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); fs.write(file.fd, data, (err, writeLen) => { if (err) { console.info("write failed with error message: " + err.message + ", error code: " + err.code); } else { console.info(“write data to file succeed and size is:” + writeLen); fs.closeSync(file); } }); }

build() { Column() { Row() { Image(this.imgUrl).objectFit(ImageFit.None) }.width(‘100%’).height(‘50%’).backgroundColor(’#F0F0F0’) Row() { Button() { Text(“拍照”) .fontColor(Color.Black) .alignSelf(ItemAlign.Center) .onClick(() => { let settings: camera.PhotoCaptureSetting = { quality: camera.QualityLevel.QUALITY_LEVEL_HIGH, // 设置图片质量高 rotation: camera.ImageRotation.ROTATION_0, // 设置图片旋转角度0 mirror: false // 设置镜像使能开关(默认关) }; if (this.photoOutput){ this.photoOutput.capture(settings, (err: BusinessError) => { if (err) { console.error(Failed to capture the photo. error: ${JSON.stringify(err)}); return; } console.info(‘Callback invoked to indicate the photo capture request success.’); }); } }) }.width(100).height(100) Image(this.pixma) .width(200) .height(200) } } } }

更多关于HarmonyOS鸿蒙Next中拍照比较慢的原因及优化方案的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,拍照较慢的原因可能涉及以下几个方面:

  1. 图像处理算法复杂度:鸿蒙Next可能采用了更复杂的图像处理算法来提升照片质量,如多帧合成、降噪、HDR等,这些算法需要更多时间处理数据。

  2. 硬件性能限制:如果设备的处理器、内存或存储性能较弱,可能会导致拍照过程中的数据处理和存储速度变慢。

  3. 相机启动时间:相机应用的启动时间可能较长,尤其是在后台有其他应用占用资源时,相机应用的初始化会受到影响。

  4. 对焦和曝光调整:鸿蒙Next可能在对焦和曝光调整上花费更多时间,以确保拍摄效果最佳,特别是在复杂光线条件下。

  5. 系统资源调度:鸿蒙Next的系统资源调度机制可能优先保证其他系统任务的执行,导致相机应用的资源分配不足,从而影响拍照速度。

  6. 软件优化不足:鸿蒙Next作为新系统,可能在相机应用的优化上还不够完善,存在性能瓶颈。

优化方案可能包括:

  1. 算法优化:对图像处理算法进行优化,减少处理时间,同时保持或提升图像质量。

  2. 硬件升级:提升设备的硬件性能,如使用更快的处理器、更大的内存和更快的存储设备。

  3. 相机启动优化:优化相机应用的启动流程,减少初始化时间,提升启动速度。

  4. 对焦和曝光优化:优化对焦和曝光算法,减少调整时间,同时确保拍摄效果。

  5. 资源调度优化:改进系统资源调度机制,确保相机应用在拍照时能获得足够的资源。

  6. 软件迭代更新:通过系统更新和软件迭代,持续优化相机应用的性能,解决已知问题。

这些优化措施可能会在未来的系统更新中逐步实现,以提升鸿蒙Next的拍照体验。

在HarmonyOS鸿蒙Next中,拍照速度慢可能由以下原因导致:

  1. 相机启动时间较长,可能与系统资源调度或硬件性能有关;
  2. 图像处理算法复杂,如HDR、夜景模式等增加了处理时间;
  3. 存储速度慢,尤其是低端设备的存储性能不足;
  4. 后台进程占用资源,影响相机性能。

优化方案包括:

  1. 优化相机启动流程,减少初始化时间;
  2. 简化图像处理算法,或提供快速拍照模式;
  3. 提升存储性能,或优化写入策略;
  4. 资源管理优化,确保相机运行时优先分配系统资源。
回到顶部