相机框架提供动态照片拍摄能力,业务应用可以类似拍摄普通照片一样,一键式拍摄得到动态照片。
应用开发动态照片主要分为以下步骤:
详细的API说明请参考@ohos.multimedia.camera (相机管理)。
导入依赖,需要导入相机框架、媒体库、图片相关领域依赖。
import { camera } from '@kit.CameraKit';
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { BusinessError } from '@kit.BasicServicesKit'; 确定拍照输出流。
通过CameraOutputCapability中的photoProfiles属性,可获取当前设备支持的拍照输出流,通过createPhotoOutput方法创建拍照输出流。
getPhotoOutput(cameraManager: camera.CameraManager,
cameraOutputCapability: camera.CameraOutputCapability): camera.PhotoOutput | undefined {
let photoProfilesArray: camera.Profile[] = cameraOutputCapability.photoProfiles;
if (!photoProfilesArray || photoProfilesArray.length === 0) {
console.error('photoProfilesArray is null or []');
}
let photoOutput: camera.PhotoOutput | undefined = undefined;
try {
this.photoProfileObj = photoProfilesArray[0]
photoOutput = cameraManager.createPhotoOutput(photoProfilesArray[0]);
} catch (error) {
let err = error as BusinessError;
console.error(`Failed to createPhotoOutput. error: ${err}`);
}
return photoOutput;
} 查询当前设备当前模式是否支持动态照片能力。
isMovingPhotoSupported(): boolean {
let isSupported: boolean = false;
try {
if (this.photoOutput == undefined) {
console.error(`photoOutput is nullptr.`);
return false;
}
isSupported = this.photoOutput.isMovingPhotoSupported();
} catch (error) {
// 失败返回错误码error.code并处理。
let err = error as BusinessError;
console.error(`The isMovingPhotoSupported call failed. error code: ${err.code}`);
}
return isSupported;
} 使能动态照片拍照能力。
enableMovingPhoto(enable: boolean): void {
try {
if (this.photoOutput != undefined) {
console.info(TAG, `enableMovingPhoto: ${enable}`);
this.photoOutput.enableMovingPhoto(enable);
}
} catch (error) {
// 失败返回错误码error.code并处理。
let err = error as BusinessError;
console.error(`The enableMovingPhoto call failed. error code: ${err.code}`);
}
} 触发拍照,与普通拍照方式相同,请参考拍照。
在相机应用开发过程中,可以随时监听动态照片拍照输出流状态。通过注册photoAsset的回调函数获取监听结果,photoOutput创建成功时即可监听。
onPhotoOutputPhotoAssetAvailable(photoOutput: camera.PhotoOutput, context: Context): void {
photoOutput.on('photoAssetAvailable', (err: BusinessError, photoAsset: photoAccessHelper.PhotoAsset) => {
if (err) {
console.error(`photoAssetAvailable error: ${err}.`);
return;
}
console.info('photoOutputCallBack photoAssetAvailable');
// 开发者可通过photoAsset调用媒体库相关接口,自定义处理图片。
// 处理方式一:调用媒体库落盘接口保存一阶段图,二阶段图就绪后媒体库会主动帮应用替换落盘图片。
let accessHelper: photoAccessHelper.PhotoAccessHelper =
photoAccessHelper.getPhotoAccessHelper(this.context);
this.mediaLibSavePhoto(photoAsset, accessHelper);
// 处理方式二:调用媒体库接口请求图片并注册一阶段图或二阶段图buffer回调,自定义使用。
this.mediaLibRequestBuffer(photoAsset, context, this.callback);
});
}
async mediaLibSavePhoto(photoAsset: photoAccessHelper.PhotoAsset,
phAccessHelper: photoAccessHelper.PhotoAccessHelper): Promise<void> {
try {
let assetChangeRequest: photoAccessHelper.MediaAssetChangeRequest =
new photoAccessHelper.MediaAssetChangeRequest(photoAsset);
assetChangeRequest.saveCameraPhoto();
await phAccessHelper.applyChanges(assetChangeRequest);
phAccessHelper.release().catch(() => {
console.error(`release failed.`);
});
} catch (error) {
Logger.error(`apply saveCameraPhoto failed with error: ${error.code}, ${error.message}`);
}
}
async mediaLibRequestBuffer(photoAsset: photoAccessHelper.PhotoAsset, context: Context,
callback: (pixelMap: image.PixelMap, url: string) => void) {
class MediaDataHandler implements photoAccessHelper.MediaAssetDataHandler<ArrayBuffer> {
onDataPrepared(data: ArrayBuffer) {
if (data === undefined) {
Logger.error('Error occurred when preparing data');
return;
}
let imageSource = image.createImageSource(data);
imageSource.createPixelMap().then((pixelMap: image.PixelMap) => {
callback(pixelMap, photoAsset.uri);
}).catch((err: BusinessError) => {
Logger.error(`createPixelMap err:${err.code}`);
})
}
}
let requestOptions: photoAccessHelper.RequestOptions = {
deliveryMode: photoAccessHelper.DeliveryMode.FAST_MODE,
}
const handler = new MediaDataHandler();
try {
await photoAccessHelper.MediaAssetManager.requestImageData(context, photoAsset, requestOptions, handler);
} catch (error) {
console.error(`requestImageData failed, err: ${error.code}`);
}
} 从API version 23开始,相机提供HDR动态照片拍摄能力,即组成动态照片的静态图片与动态短视频均为高动态范围(HDR)内容,能够在高光与暗部细节、色彩层次和整体质感方面优于SDR成片效果。
应用可以通过配置预览输出格式(Profile.format)和色彩空间(ColorSpace)灵活决定输出SDR/HDR动态照片。具体对应关系如下表所示,所有能力需先查后用,支持的预览输出格式通过接口getSupportedFullOutputCapability查询,支持的色彩空间通过接口getSupportedColorSpaces查询。
| 静图动态范围 | 短视频动态范围 | 预览输出格式 | 色彩空间 |
|---|---|---|---|
| SDR | SDR | CAMERA_FORMAT_YUV_420_SP | SRGB |
| HDR | SDR | CAMERA_FORMAT_YUV_420_SP | DISPLAY_P3 |
| HDR | HDR | CAMERA_FORMAT_YCRCB_P010、 CAMERA_FORMAT_YCBCR_P010 | BT2020_HLG |
HDR配置说明