HarmonyOS鸿蒙Next中拍照比较慢的原因及优化方案
HarmonyOS鸿蒙Next中拍照比较慢的原因及优化方案 通过以下的代码获取拍照后的照片,速度比较慢,从capture后至少3秒才会回调获取到照片,照片大小 1440*1920
photoOutput.on("photoAvailable",
async (errCode: BusinessError, photo: camera.Photo): Promise<void> => {
})
photoOutput: 是camera.PhotoOutput
有没有什么办法capture后可以更快的获取照片,2秒左右,提升用户体验
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中,拍照较慢的原因可能涉及以下几个方面:
-
图像处理算法复杂度:鸿蒙Next可能采用了更复杂的图像处理算法来提升照片质量,如多帧合成、降噪、HDR等,这些算法需要更多时间处理数据。
-
硬件性能限制:如果设备的处理器、内存或存储性能较弱,可能会导致拍照过程中的数据处理和存储速度变慢。
-
相机启动时间:相机应用的启动时间可能较长,尤其是在后台有其他应用占用资源时,相机应用的初始化会受到影响。
-
对焦和曝光调整:鸿蒙Next可能在对焦和曝光调整上花费更多时间,以确保拍摄效果最佳,特别是在复杂光线条件下。
-
系统资源调度:鸿蒙Next的系统资源调度机制可能优先保证其他系统任务的执行,导致相机应用的资源分配不足,从而影响拍照速度。
-
软件优化不足:鸿蒙Next作为新系统,可能在相机应用的优化上还不够完善,存在性能瓶颈。
优化方案可能包括:
-
算法优化:对图像处理算法进行优化,减少处理时间,同时保持或提升图像质量。
-
硬件升级:提升设备的硬件性能,如使用更快的处理器、更大的内存和更快的存储设备。
-
相机启动优化:优化相机应用的启动流程,减少初始化时间,提升启动速度。
-
对焦和曝光优化:优化对焦和曝光算法,减少调整时间,同时确保拍摄效果。
-
资源调度优化:改进系统资源调度机制,确保相机应用在拍照时能获得足够的资源。
-
软件迭代更新:通过系统更新和软件迭代,持续优化相机应用的性能,解决已知问题。
这些优化措施可能会在未来的系统更新中逐步实现,以提升鸿蒙Next的拍照体验。
在HarmonyOS鸿蒙Next中,拍照速度慢可能由以下原因导致:
- 相机启动时间较长,可能与系统资源调度或硬件性能有关;
- 图像处理算法复杂,如HDR、夜景模式等增加了处理时间;
- 存储速度慢,尤其是低端设备的存储性能不足;
- 后台进程占用资源,影响相机性能。
优化方案包括:
- 优化相机启动流程,减少初始化时间;
- 简化图像处理算法,或提供快速拍照模式;
- 提升存储性能,或优化写入策略;
- 资源管理优化,确保相机运行时优先分配系统资源。

