鸿蒙高级拍照功能实战:从基础拍照到高级特性
1. 拍照功能架构深度解析
1.1 拍照系统整体架构
鸿蒙相机拍照功能建立在完整的流水线架构之上,涉及多个组件的协同工作:
text
CameraInput → Session → PhotoOutput → Image Processing → Media Library
拍照数据流详解:
- 图像采集:CameraInput从相机硬件获取原始图像数据
- 流水线处理:Session管理多个输出流的协调和数据分发
- 图像编码:PhotoOutput负责将图像数据编码为指定格式
- 后处理:可选的美颜、滤镜、HDR等图像增强处理
- 存储管理:通过Media Library将照片保存到设备存储
1.2 拍照模式分类与选择策略
根据不同的使用场景,鸿蒙相机支持多种拍照模式:
typescript
enum PhotoCaptureMode {
STANDARD = 'standard', // 标准拍照
BURST = 'burst', // 连拍模式
HDR = 'hdr', // HDR拍照
NIGHT = 'night', // 夜景模式
PORTRAIT = 'portrait', // 人像模式
PROFESSIONAL = 'professional' // 专业模式
}
2. 基础拍照功能完整实现
2.1 PhotoOutput配置与管理
typescript
import { camera } from '@kit.CameraKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { image } from '@kit.ImageKit';
class AdvancedPhotoOutput {
private photoOutput: camera.PhotoOutput | null = null;
private captureInProgress: boolean = false;
private captureQueue: Array<() => Promise<void>> = [];
private maxQueueSize: number = 3;
// 创建拍照输出流
async createPhotoOutput(
cameraManager: camera.CameraManager,
capability: camera.CameraOutputCapability,
preferredQuality: camera.QualityLevel = camera.QualityLevel.QUALITY_LEVEL_HIGH
): Promise<boolean> {
try {
const photoProfile = this.selectOptimalPhotoProfile(
capability.photoProfiles,
preferredQuality
);
if (!photoProfile) {
console.error('No suitable photo profile found');
return false;
}
this.photoOutput = cameraManager.createPhotoOutput(photoProfile);
// 设置拍照监听器
this.setupPhotoListeners();
console.info('PhotoOutput created successfully');
return true;
} catch (error) {
console.error(`Create PhotoOutput failed: ${(error as BusinessError).message}`);
return false;
}
}
// 选择最优拍照配置
private selectOptimalPhotoProfile(
profiles: Array<camera.Profile>,
preferredQuality: camera.QualityLevel
): camera.Profile | null {
if (!profiles || profiles.length === 0) {
return null;
}
let bestProfile: camera.Profile | null = null;
let bestScore = -1;
for (const profile of profiles) {
let score = 0;
// 分辨率评分(倾向于更高分辨率)
const resolutionScore = (profile.size.width * profile.size.height) / (4000 * 3000);
// 质量偏好匹配
const qualityScore = this.getQualityMatchScore(profile, preferredQuality);
// 格式偏好
const formatScore = this.getPhotoFormatScore(profile.format);
// 综合评分
score = resolutionScore * 0.5 + qualityScore * 0.3 + formatScore * 0.2;
if (score > bestScore) {
bestScore = score;
bestProfile = profile;
}
}
if (bestProfile) {
console.info(`Selected photo profile: ${bestProfile.size.width}x${bestProfile.size.height}`);
}
return bestProfile;
}
// 获取质量匹配评分
private getQualityMatchScore(
profile: camera.Profile,
preferredQuality: camera.QualityLevel
): number {
// 根据配置的质量等级和实际profile的匹配程度评分
// 实际实现中需要更复杂的逻辑
return 0.8;
}
// 获取照片格式评分
private getPhotoFormatScore(format: number): number {
switch (format) {
case camera.CameraFormat.CAMERA_FORMAT_JPEG:
return 1.0;
case camera.CameraFormat.CAMERA_FORMAT_HEIF:
return 0.9;
default:
return 0.5;
}
}
// 设置拍照监听器
private setupPhotoListeners(): void {
if (!this.photoOutput) return;
// 拍照开始监听
this.photoOutput.on('captureStartWithInfo', (err: BusinessError, captureStartInfo: camera.CaptureStartInfo) => {
if (err) {
console.error(`Capture start error: ${err.code}`);
return;
}
this.onCaptureStart(captureStartInfo);
});
// 拍照结束监听
this.photoOutput.on('captureEnd', (err: BusinessError, captureEndInfo: camera.CaptureEndInfo) => {
if (err) {
console.error(`Capture end error: ${err.code}`);
return;
}
this.onCaptureEnd(captureEndInfo);
});
// 照片可用监听(传统方式)
this.photoOutput.on('photoAvailable', (err: BusinessError, photo: camera.Photo) => {
if (err) {
console.error(`Photo available error: ${err.code}`);
return;
}
this.onPhotoAvailable(photo);
});
// 拍照准备就绪监听
this.photoOutput.on('captureReady', (err: BusinessError) => {
if (err) {
console.error(`Capture ready error: ${err.code}`);
return;
}
this.onCaptureReady();
});
// 错误监听
this.photoOutput.on('error', (error: BusinessError) => {
console.error(`Photo output error: ${error.code}`);
this.onPhotoError(error);
});
}
// 拍照开始回调
private onCaptureStart(captureStartInfo: camera.CaptureStartInfo): void {
console.info(`Capture started, captureId: ${captureStartInfo.captureId}`);
this.captureInProgress = true;
}
// 拍照结束回调
private onCaptureEnd(captureEndInfo: camera.CaptureEndInfo): void {
console.info(`Capture ended, captureId: ${captureEndInfo.captureId}, frames: ${captureEndInfo.frameCount}`);
this.captureInProgress = false;
// 处理队列中的下一个拍照请求
this.processCaptureQueue();
}
// 照片可用回调
private async onPhotoAvailable(photo: camera.Photo): Promise<void> {
console.info('Photo available for processing');
try {
// 处理照片数据
await this.processPhotoData(photo);
// 释放照片资源
photo.release();
} catch (error) {
console.error(`Photo processing failed: ${(error as BusinessError).message}`);
photo.release();
}
}
// 拍照准备就绪回调
private onCaptureReady(): void {
console.info('Camera ready for next capture');
this.processCaptureQueue();
}
// 拍照错误处理
private onPhotoError(error: BusinessError): void {
console.error(`Photo capture error: ${error.code}`);
this.captureInProgress = false;
// 清空队列或进行错误恢复
this.handleCaptureError(error);
}
// 处理拍照错误
private handleCaptureError(error: BusinessError): void {
switch (error.code) {
case 5400201:
console.error('Capture failed: device error');
break;
case 5400202:
console.error('Capture failed: configuration error');
break;
case 5400203:
console.error('Capture failed: storage error');
break;
default:
console.error(`Capture failed: unknown error ${error.code}`);
}
// 清空拍照队列
this.captureQueue = [];
}
// 处理拍照队列
private async processCaptureQueue(): Promise<void> {
if (this.captureInProgress || this.captureQueue.length === 0) {
return;
}
const nextCapture = this.captureQueue.shift();
if (nextCapture) {
await nextCapture();
}
}
// 单次拍照
async capture(settings: camera.PhotoCaptureSetting): Promise<boolean> {
if (!this.photoOutput) {
console.error('PhotoOutput not initialized');
return false;
}
return new Promise((resolve) => {
this.photoOutput!.capture(settings, (err: BusinessError) => {
if (err) {
console.error(`Capture failed: ${err.message}`);
resolve(false);
} else {
console.info('Capture request sent successfully');
resolve(true);
}
});
});
}
// 排队拍照(防止过快连拍)
async captureWithQueue(settings: camera.PhotoCaptureSetting): Promise<boolean> {
if (this.captureQueue.length >= this.maxQueueSize) {
console.warn('Capture queue is full, request rejected');
return false;
}
return new Promise((resolve) => {
const captureTask = async () => {
const success = await this.capture(settings);
resolve(success);
};
this.captureQueue.push(captureTask);
// 如果当前没有拍照进行,立即开始
if (!this.captureInProgress) {
this.processCaptureQueue();
}
});
}
// 连拍模式
async burstCapture(
settings: camera.PhotoCaptureSetting,
count: number,
interval: number = 100
): Promise<boolean> {
if (count <= 0) {
console.error('Invalid burst count');
return false;
}
console.info(`Starting burst capture: ${count} photos`);
for (let i = 0; i < count; i++) {
const success = await this.captureWithQueue(settings);
if (!success) {
console.error(`Burst capture failed at photo ${i + 1}`);
return false;
}
// 连拍间隔
if (i < count - 1) {
await new Promise(resolve => setTimeout(resolve, interval));
}
}
console.info('Burst capture completed');
return true;
}
// 处理照片数据
private async processPhotoData(photo: camera.Photo): Promise<void> {
try {
// 获取主图像组件
const mainComponent = await photo.main.getComponent(image.ComponentType.JPEG);
if (!mainComponent || !mainComponent.byteBuffer) {
console.error('Failed to get main photo component');
return;
}
// 创建照片处理器
const photoProcessor = new PhotoProcessor();
// 处理照片(保存、应用滤镜等)
await photoProcessor.processPhoto(photo, mainComponent.byteBuffer);
} catch (error) {
console.error(`Photo data processing failed: ${(error as BusinessError).message}`);
}
}
// 释放资源
async release(): Promise<void> {
this.captureQueue = [];
if (this.photoOutput) {
await this.photoOutput.release();
this.photoOutput = null;
}
console.info('AdvancedPhotoOutput released');
}
}
2.2 照片处理器实现
typescript
import { image } from '@kit.ImageKit';
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { fileIo, fileUri } from '@kit.CoreFileKit';
class PhotoProcessor {
private context: Context;
constructor(context: Context) {
this.context = context;
}
// 处理照片
async processPhoto(photo: camera.Photo, imageData: ArrayBuffer): Promise<void> {
try {
// 1. 创建PixelMap进行图像处理
const pixelMap = await this.createPixelMapFromPhoto(photo, imageData);
// 2. 应用图像处理(可选)
const processedPixelMap = await this.applyImageProcessing(pixelMap);
// 3. 保存照片
await this.savePhoto(processedPixelMap || pixelMap, photo);
// 4. 释放资源
pixelMap.release();
if (processedPixelMap && processedPixelMap !== pixelMap) {
processedPixelMap.release();
}
console.info('Photo processed successfully');
} catch (error) {
console.error(`Photo processing failed: ${error.message}`);
throw error;
}
}
// 从照片创建PixelMap
private async createPixelMapFromPhoto(
photo: camera.Photo,
imageData: ArrayBuffer
): Promise<image.PixelMap> {
const photoSize = await photo.main.getSize();
return await image.createPixelMap(imageData, {
size: {
width: photoSize.size.width,
height: photoSize.size.height
},
srcPixelFormat: image.PixelMapFormat.RGBA_8888,
editable: true
});
}
// 应用图像处理
private async applyImageProcessing(pixelMap: image.PixelMap): Promise<image.PixelMap | null> {
// 这里可以实现各种图像处理效果
// 例如:美颜、滤镜、HDR、锐化等
// 示例:简单的亮度调整
// return await this.adjustBrightness(pixelMap, 1.1);
return null; // 不进行处理,直接返回原图
}
// 调整亮度(示例)
private async adjustBrightness(
pixelMap: image.PixelMap,
factor: number
): Promise<image.PixelMap> {
// 实际实现需要使用图像处理算法
// 这里返回原图作为示例
return pixelMap;
}
// 保存照片到媒体库
private async savePhoto(pixelMap: image.PixelMap, photo: camera.Photo): Promise<void> {
try {
const photoAccessHelper = photoAccessHelper.getPhotoAccessHelper(this.context);
// 创建文件名
const timestamp = new Date().getTime();
const fileName = `IMG_${timestamp}.jpg`;
// 创建资源
const photoAsset = await photoAccessHelper.createAsset(fileName);
// 创建修改请求
const changeRequest = new photoAccessHelper.MediaAssetChangeRequest(photoAsset);
// 设置照片数据
await changeRequest.setPixelMapData(pixelMap);
// 添加EXIF信息(可选)
await this.addExifData(changeRequest, photo);
// 应用更改
await photoAccessHelper.applyChanges(changeRequest);
console.info(`Photo saved successfully: ${photoAsset.uri}`);
} catch (error) {
console.error(`Save photo to media library failed: ${error.message}`);
// 回退到文件系统保存
await this.saveToFileSystem(pixelMap);
}
}
// 添加EXIF数据
private async addExifData(
changeRequest: photoAccessHelper.MediaAssetChangeRequest,
photo: camera.Photo
): Promise<void> {
try {
// 获取照片的EXIF信息
const exifData = await this.extractExifData(photo);
// 设置EXIF数据到媒体库
// 具体实现取决于MediaAssetChangeRequest的API
} catch (error) {
console.warn(`Add EXIF data failed: ${error.message}`);
}
}
// 提取EXIF数据
private async extractExifData(photo: camera.Photo): Promise<any> {
// 从照片中提取EXIF信息
// 实际实现需要访问照片的元数据
return {
DateTime: new Date().toISOString(),
// 其他EXIF字段...
};
}
// 保存到文件系统(备用方案)
private async saveToFileSystem(pixelMap: image.PixelMap): Promise<void> {
try {
const timestamp = new Date().getTime();
const fileName = `IMG_${timestamp}.jpg`;
const filePath = `${this.context.filesDir}/${fileName}`;
// 创建图片打包器
const imagePacker = image.createImagePacker();
// 打包选项
const packOptions = {
format: "image/jpeg",
quality: 98
};
// 打包并保存
await imagePacker.packing(pixelMap, packOptions, filePath);
console.info(`Photo saved to file system: ${filePath}`);
} catch (error) {
console.error(`Save to file system failed: ${error.message}`);
throw error;
}
}
}
3. 分段式拍照深度实现
3.1 分段式拍照架构解析
分段式拍照(Deferred Capture)将拍照过程分为两个阶段:
- 第一阶段:快速返回轻量处理的缩略图
- 第二阶段:后台处理全质量图片并替换
typescript
import { camera } from '@kit.CameraKit';
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { BusinessError } from '@kit.BasicServicesKit';
class DeferredCaptureManager {
private photoOutput: camera.PhotoOutput | null = null;
private isDeferredEnabled: boolean = false;
// 启用分段式拍照
enableDeferredCapture(): void {
if (!this.photoOutput) {
console.error('PhotoOutput not initialized');
return;
}
try {
// 检查是否支持分段式拍照
const isSupported = this.photoOutput.isDeferredImageDeliverySupported(
camera.DeferredDeliveryImageType.PHOTO
);
if (isSupported) {
this.photoOutput.deferImageDelivery(camera.DeferredDeliveryImageType.PHOTO);
this.isDeferredEnabled = true;
console.info('Deferred capture enabled');
} else {
console.warn('Deferred capture not supported on this device');
}
} catch (error) {
console.error(`Enable deferred capture failed: ${(error as BusinessError).message}`);
}
}
// 设置分段式拍照监听器
setupDeferredListeners(context: Context): void {
if (!this.photoOutput) return;
// 缩略图代理可用监听
this.photoOutput.on('deferredPhotoProxyAvailable',
(err: BusinessError, proxyObj: camera.DeferredPhotoProxy) => {
if (err) {
console.error(`Deferred photo proxy error: ${err.message}`);
return;
}
this.onDeferredPhotoProxyAvailable(proxyObj, context);
}
);
// PhotoAsset可用监听(分段式拍照的主要接口)
this.photoOutput.on('photoAssetAvailable',
(err: BusinessError, photoAsset: photoAccessHelper.PhotoAsset) => {
if (err) {
console.error(`Photo asset available error: ${err.message}`);
return;
}
this.onPhotoAssetAvailable(photoAsset, context);
}
);
}
// 处理缩略图代理
private async onDeferredPhotoProxyAvailable(
proxyObj: camera.DeferredPhotoProxy,
context: Context
): Promise<void> {
try {
console.info('Deferred photo proxy available');
// 获取缩略图
const thumbnail = await proxyObj.getThumbnail();
// 处理缩略图(显示、保存等)
await this.processThumbnail(thumbnail, context);
// 保存代理对象到媒体库
await this.saveDeferredProxy(proxyObj, context);
} catch (error) {
console.error(`Process deferred photo proxy failed: ${(error as BusinessError).message}`);
}
}
// 处理PhotoAsset
private async onPhotoAssetAvailable(
photoAsset: photoAccessHelper.PhotoAsset,
context: Context
): Promise<void> {
try {
console.info('Photo asset available for deferred capture');
// 使用媒体库保存照片
await this.savePhotoAsset(photoAsset, context);
} catch (error) {
console.error(`Process photo asset failed: ${(error as BusinessError).message}`);
}
}
// 处理缩略图
private async processThumbnail(
thumbnail: image.PixelMap,
context: Context
): Promise<void> {
// 在实际应用中,可以:
// 1. 立即显示缩略图给用户
// 2. 进行快速图像分析
// 3. 生成预览效果
console.info('Thumbnail processed, ready for display');
// 释放缩略图资源
thumbnail.release();
}
// 保存代理对象到媒体库
private async saveDeferredProxy(
proxyObj: camera.DeferredPhotoProxy,
context: Context
): Promise<void> {
try {
const accessHelper = photoAccessHelper.getPhotoAccessHelper(context);
const fileName = `DEFERRED_${Date.now()}.jpg`;
// 创建照片资源
const photoAsset = await accessHelper.createAsset(fileName);
// 创建修改请求
const changeRequest = new photoAccessHelper.MediaAssetChangeRequest(photoAsset);
// 添加代理资源
changeRequest.addResource(photoAccessHelper.ResourceType.PHOTO_PROXY, proxyObj);
// 应用更改
await accessHelper.applyChanges(changeRequest);
console.info('Deferred photo proxy saved to media library');
// 释放代理对象
proxyObj.release();
} catch (error) {
console.error(`Save deferred proxy failed: ${(error as BusinessError).message}`);
proxyObj.release();
}
}
// 保存PhotoAsset
private async savePhotoAsset(
photoAsset: photoAccessHelper.PhotoAsset,
context: Context
): Promise<void> {
try {
const accessHelper = photoAccessHelper.getPhotoAccessHelper(context);
// 创建修改请求
const changeRequest = new photoAccessHelper.MediaAssetChangeRequest(photoAsset);
// 标记为相机照片
changeRequest.saveCameraPhoto();
// 应用更改
await accessHelper.applyChanges(changeRequest);
console.info('Photo asset saved successfully');
} catch (error) {
console.error(`Save photo asset failed: ${(error as BusinessError).message}`);
}
}
// 检查分段式拍照状态
checkDeferredStatus(): {
isEnabled: boolean;
isSupported: boolean;
} {
if (!this.photoOutput) {
return { isEnabled: false, isSupported: false };
}
const isSupported = this.photoOutput.isDeferredImageDeliverySupported(
camera.DeferredDeliveryImageType.PHOTO
);
const isEnabled = isSupported &&
this.photoOutput.isDeferredImageDeliveryEnabled(camera.DeferredDeliveryImageType.PHOTO);
return { isEnabled, isSupported };
}
}
3.2 分段式拍照完整工作流
typescript
class DeferredCaptureWorkflow {
private deferredManager: DeferredCaptureManager;
private photoOutput: AdvancedPhotoOutput;
private context: Context;
constructor(context: Context, photoOutput: AdvancedPhotoOutput) {
this.context = context;
this.photoOutput = photoOutput;
this.deferredManager = new DeferredCaptureManager();
}
// 初始化分段式拍照
async initializeDeferredCapture(): Promise<boolean> {
try {
// 设置监听器
this.deferredManager.setupDeferredListeners(this.context);
// 启用分段式拍照
this.deferredManager.enableDeferredCapture();
// 检查状态
const status = this.deferredManager.checkDeferredStatus();
if (status.isEnabled) {
console.info('Deferred capture initialized successfully');
return true;
} else {
console.warn('Deferred capture not available, falling back to standard capture');
return false;
}
} catch (error) {
console.error(`Initialize deferred capture failed: ${error.message}`);
return false;
}
}
// 执行分段式拍照
async captureWithDeferred(settings: camera.PhotoCaptureSetting): Promise<boolean> {
// 检查分段式拍照状态
const status = this.deferredManager.checkDeferredStatus();
if (!status.isEnabled) {
console.warn('Deferred capture not enabled, using standard capture');
return await this.photoOutput.capture(settings);
}
console.info('Starting deferred capture');
return await this.photoOutput.capture(settings);
}
// 获取分段式拍照统计信息
getDeferredStatistics(): DeferredCaptureStats {
// 返回分段式拍照的性能统计
return {
enabled: this.deferredManager.checkDeferredStatus().isEnabled,
thumbnailResponseTime: 0, // 实际统计
fullImageResponseTime: 0 // 实际统计
};
}
}
interface DeferredCaptureStats {
enabled: boolean;
thumbnailResponseTime: number;
fullImageResponseTime: number;
}
4. 高性能拍照实现(系统应用)
4.1 快速缩略图技术
typescript
class QuickThumbnailManager {
private photoOutput: camera.PhotoOutput | null = null;
private quickThumbnailEnabled: boolean = false;
// 启用快速缩略图
enableQuickThumbnail(): boolean {
if (!this.photoOutput) {
console.error('PhotoOutput not initialized');
return false;
}
try {
// 检查是否支持快速缩略图
const isSupported = this.photoOutput.isQuickThumbnailSupported();
if (isSupported) {
this.photoOutput.enableQuickThumbnail(true);
this.quickThumbnailEnabled = true;
// 设置快速缩略图监听器
this.setupQuickThumbnailListener();
console.info('Quick thumbnail enabled');
return true;
} else {
console.warn('Quick thumbnail not supported');
return false;
}
} catch (error) {
console.error(`Enable quick thumbnail failed: ${(error as BusinessError).message}`);
return false;
}
}
// 设置快速缩略图监听器
private setupQuickThumbnailListener(): void {
if (!this.photoOutput) return;
this.photoOutput.on('quickThumbnail', (err: BusinessError, pixelMap: image.PixelMap) => {
if (err) {
console.error(`Quick thumbnail error: ${err.message}`);
return;
}
this.onQuickThumbnailAvailable(pixelMap);
});
}
// 处理快速缩略图
private async onQuickThumbnailAvailable(pixelMap: image.PixelMap): Promise<void> {
try {
console.info('Quick thumbnail available');
// 立即显示给用户
await this.displayQuickThumbnail(pixelMap);
// 可以进行快速图像分析
await this.analyzeQuickThumbnail(pixelMap);
// 释放资源
pixelMap.release();
} catch (error) {
console.error(`Process quick thumbnail failed: ${error.message}`);
pixelMap.release();
}
}
// 显示快速缩略图
private async displayQuickThumbnail(pixelMap: image.PixelMap): Promise<void> {
// 在实际应用中,可以:
// 1. 更新UI显示快速预览
// 2. 提供即时反馈给用户
// 3. 用于快速分享等场景
console.info('Quick thumbnail displayed to user');
}
// 分析快速缩略图
private async analyzeQuickThumbnail(pixelMap: image.PixelMap): Promise<void> {
// 可以进行快速图像分析,例如:
// - 人脸检测
// - 场景识别
// - 图像质量评估
// - 自动分类
console.info('Quick thumbnail analysis completed');
}
// 获取快速缩略图状态
getQuickThumbnailStatus(): { enabled: boolean; supported: boolean } {
if (!this.photoOutput) {
return { enabled: false, supported: false };
}
const supported = this.photoOutput.isQuickThumbnailSupported();
const enabled = supported && this.quickThumbnailEnabled;
return { enabled, supported };
}
}
4.2 预热启动优化
typescript
class PrelaunchOptimization {
private cameraManager: camera.CameraManager;
private context: Context;
constructor(context: Context, cameraManager: camera.CameraManager) {
this.context = context;
this.cameraManager = cameraManager;
}
// 配置预热参数
configurePrelaunch(cameraDevice: camera.CameraDevice): boolean {
try {
// 检查是否支持预热启动
const isSupported = this.cameraManager.isPrelaunchSupported(cameraDevice);
if (isSupported) {
const prelaunchConfig: camera.PrelaunchConfig = {
cameraDevice: cameraDevice
// 可以添加其他预热参数
};
this.cameraManager.setPrelaunchConfig(prelaunchConfig);
console.info('Prelaunch configuration set successfully');
return true;
} else {
console.warn('Prelaunch not supported on this device');
return false;
}
} catch (error) {
console.error(`Configure prelaunch failed: ${(error as BusinessError).message}`);
return false;
}
}
// 执行预热启动(由桌面应用调用)
executePrelaunch(): void {
try {
this.cameraManager.prelaunch();
console.info('Prelaunch executed successfully');
} catch (error) {
console.error(`Execute prelaunch failed: ${(error as BusinessError).message}`);
}
}
// 获取预热启动状态
getPrelaunchStatus(cameraDevice: camera.CameraDevice): PrelaunchStatus {
const supported = this.cameraManager.isPrelaunchSupported(cameraDevice);
return {
supported,
configured: supported // 简化实现,实际需要更复杂的状态跟踪
};
}
}
interface PrelaunchStatus {
supported: boolean;
configured: boolean;
}
5. 动态照片拍摄技术
5.1 动态照片管理器
typescript
class MovingPhotoManager {
private photoOutput: camera.PhotoOutput | null = null;
private movingPhotoEnabled: boolean = false;
// 启用动态照片
enableMovingPhoto(): boolean {
if (!this.photoOutput) {
console.error('PhotoOutput not initialized');
return false;
}
try {
// 检查是否支持动态照片
const isSupported = this.photoOutput.isMovingPhotoSupported();
if (isSupported) {
this.photoOutput.enableMovingPhoto(true);
this.movingPhotoEnabled = true;
console.info('Moving photo enabled');
return true;
} else {
console.warn('Moving photo not supported');
return false;
}
} catch (error) {
console.error(`Enable moving photo failed: ${(error as BusinessError).message}`);
return false;
}
}
// 设置动态照片监听器
setupMovingPhotoListener(context: Context): void {
if (!this.photoOutput) return;
this.photoOutput.on('photoAssetAvailable',
(err: BusinessError, photoAsset: photoAccessHelper.PhotoAsset) => {
if (err) {
console.error(`Moving photo asset error: ${err.message}`);
return;
}
this.onMovingPhotoAssetAvailable(photoAsset, context);
}
);
}
// 处理动态照片资源
private async onMovingPhotoAssetAvailable(
photoAsset: photoAccessHelper.PhotoAsset,
context: Context
): Promise<void> {
try {
console.info('Moving photo asset available');
// 保存动态照片到媒体库
await this.saveMovingPhoto(photoAsset, context);
} catch (error) {
console.error(`Process moving photo failed: ${error.message}`);
}
}
// 保存动态照片
private async saveMovingPhoto(
photoAsset: photoAccessHelper.PhotoAsset,
context: Context
): Promise<void> {
try {
const accessHelper = photoAccessHelper.getPhotoAccessHelper(context);
// 创建修改请求
const changeRequest = new photoAccessHelper.MediaAssetChangeRequest(photoAsset);
// 标记为相机照片(包含动态照片数据)
changeRequest.saveCameraPhoto();
// 应用更改
await accessHelper.applyChanges(changeRequest);
console.info('Moving photo saved successfully');
} catch (error) {
console.error(`Save moving photo failed: ${error.message}`);
}
}
// 获取动态照片状态
getMovingPhotoStatus(): { enabled: boolean; supported: boolean } {
if (!this.photoOutput) {
return { enabled: false, supported: false };
}
const supported = this.photoOutput.isMovingPhotoSupported();
const enabled = supported && this.movingPhotoEnabled;
return { enabled, supported };
}
}
6. 完整拍照会话管理
6.1 高级拍照会话控制器
typescript
class AdvancedPhotoSession {
private sessionManager: AdvancedSessionManager;
private photoOutput: AdvancedPhotoOutput;
private deferredManager: DeferredCaptureManager;
private quickThumbnailManager: QuickThumbnailManager;
private movingPhotoManager: MovingPhotoManager;
private prelaunchOptimization: PrelaunchOptimization;
private currentMode: PhotoCaptureMode = PhotoCaptureMode.STANDARD;
private isInitialized: boolean = false;
constructor(
context: Context,
cameraManager: camera.CameraManager,
sessionManager: AdvancedSessionManager,
photoOutput: AdvancedPhotoOutput
) {
this.sessionManager = sessionManager;
this.photoOutput = photoOutput;
this.deferredManager = new DeferredCaptureManager();
this.quickThumbnailManager = new QuickThumbnailManager();
this.movingPhotoManager = new MovingPhotoManager();
this.prelaunchOptimization = new PrelaunchOptimization(context, cameraManager);
}
// 初始化拍照会话
async initialize(cameraDevice: camera.CameraDevice): Promise<boolean> {
try {
// 配置预热启动(如果支持)
this.prelaunchOptimization.configurePrelaunch(cameraDevice);
// 设置分段式拍照
this.deferredManager.setupDeferredListeners(this.context);
// 设置动态照片
this.movingPhotoManager.setupMovingPhotoListener(this.context);
this.isInitialized = true;
console.info('Advanced photo session initialized');
return true;
} catch (error) {
console.error(`Initialize advanced photo session failed: ${error.message}`);
return false;
}
}
// 设置拍照模式
setCaptureMode(mode: PhotoCaptureMode, settings: PhotoModeSettings = {}): void {
this.currentMode = mode;
switch (mode) {
case PhotoCaptureMode.STANDARD:
this.configureStandardMode(settings);
break;
case PhotoCaptureMode.BURST:
this.configureBurstMode(settings);
break;
case PhotoCaptureMode.HDR:
this.configureHdrMode(settings);
break;
case PhotoCaptureMode.NIGHT:
this.configureNightMode(settings);
break;
case PhotoCaptureMode.PORTRAIT:
this.configurePortraitMode(settings);
break;
case PhotoCaptureMode.PROFESSIONAL:
this.configureProfessionalMode(settings);
break;
}
console.info(`Capture mode set to: ${mode}`);
}
// 配置标准模式
private configureStandardMode(settings: PhotoModeSettings): void {
// 启用分段式拍照以获得更好体验
this.deferredManager.enableDeferredCapture();
// 启用快速缩略图
this.quickThumbnailManager.enableQuickThumbnail();
}
// 配置连拍模式
private configureBurstMode(settings: PhotoModeSettings): void {
const burstSettings = settings as BurstModeSettings;
// 连拍模式下通常禁用分段式拍照
// 启用快速缩略图用于即时反馈
this.quickThumbnailManager.enableQuickThumbnail();
}
// 配置HDR模式
private configureHdrMode(settings: PhotoModeSettings): void {
const hdrSettings = settings as HdrModeSettings;
// HDR模式可能需要特殊处理
// 保持分段式拍照启用以获得更好画质
this.deferredManager.enableDeferredCapture();
}
// 配置夜景模式
private configureNightMode(settings: PhotoModeSettings): void {
const nightSettings = settings as NightModeSettings;
// 夜景模式通常需要长时间曝光
// 可能禁用某些优化以获得更好画质
}
// 配置人像模式
private configurePortraitMode(settings: PhotoModeSettings): void {
const portraitSettings = settings as PortraitModeSettings;
// 启用背景虚化等效果
// 可能启用深度数据流
}
// 配置专业模式
private configureProfessionalMode(settings: PhotoModeSettings): void {
const proSettings = settings as ProfessionalModeSettings;
// 专业模式下给予用户完全控制
// 可能禁用所有自动化优化
}
// 执行拍照
async capture(settings: camera.PhotoCaptureSetting): Promise<boolean> {
if (!this.isInitialized) {
console.error('Photo session not initialized');
return false;
}
// 根据当前模式调整设置
const adjustedSettings = this.adjustSettingsForMode(settings);
// 执行拍照
return await this.photoOutput.capture(adjustedSettings);
}
// 根据模式调整设置
private adjustSettingsForMode(settings: camera.PhotoCaptureSetting): camera.PhotoCaptureSetting {
const adjustedSettings = { ...settings };
switch (this.currentMode) {
case PhotoCaptureMode.HDR:
adjustedSettings.quality = camera.QualityLevel.QUALITY_LEVEL_HIGH;
break;
case PhotoCaptureMode.NIGHT:
// 夜景模式可能需要调整曝光等参数
break;
case PhotoCaptureMode.PORTRAIT:
adjustedSettings.rotation = camera.ImageRotation.ROTATION_0;
break;
}
return adjustedSettings;
}
// 获取当前状态
getSessionStatus(): PhotoSessionStatus {
const deferredStatus = this.deferredManager.checkDeferredStatus();
const quickThumbStatus = this.quickThumbnailManager.getQuickThumbnailStatus();
const movingPhotoStatus = this.movingPhotoManager.getMovingPhotoStatus();
return {
initialized: this.isInitialized,
currentMode: this.currentMode,
deferredCapture: deferredStatus,
quickThumbnail: quickThumbStatus,
movingPhoto: movingPhotoStatus
};
}
// 释放资源
async release(): Promise<void> {
await this.photoOutput.release();
this.isInitialized = false;
console.info('Advanced photo session released');
}
}
// 拍照模式设置接口
interface PhotoModeSettings {
// 通用设置
quality?: camera.QualityLevel;
enableFlash?: boolean;
}
interface BurstModeSettings extends PhotoModeSettings {
burstCount?: number;
burstInterval?: number;
}
interface HdrModeSettings extends PhotoModeSettings {
hdrStrength?: number;
}
interface NightModeSettings extends PhotoModeSettings {
exposureTime?: number;
iso?: number;
}
interface PortraitModeSettings extends PhotoModeSettings {
blurStrength?: number;
enableBeauty?: boolean;
}
interface ProfessionalModeSettings extends PhotoModeSettings {
manualExposure?: boolean;
manualWhiteBalance?: boolean;
manualFocus?: boolean;
}
// 拍照会话状态
interface PhotoSessionStatus {
initialized: boolean;
currentMode: PhotoCaptureMode;
deferredCapture: {
isEnabled: boolean;
isSupported: boolean;
};
quickThumbnail: {
enabled: boolean;
supported: boolean;
};
movingPhoto: {
enabled: boolean;
supported: boolean;
};
}
7. 企业级拍照应用示例
7.1 完整拍照功能集成
typescript
@Entry
@Component
struct EnterpriseCameraApp {
@State currentMode: string = '标准';
@State photoCount: number = 0;
@State lastPhotoUri: string = '';
@State captureStatus: string = 'ready';
private cameraSystem: AdvancedCameraSystem;
private photoSession: AdvancedPhotoSession;
build() {
Column() {
// 模式选择器
this.buildModeSelector()
// 拍照预览
this.buildCameraPreview()
// 拍照控制
this.buildCaptureControls()
// 状态显示
this.buildStatusDisplay()
}
}
@Builder
buildModeSelector() {
Row({ space: 10 }) {
Button('标准').onClick(() => this.changeMode('standard'))
Button('连拍').onClick(() => this.changeMode('burst'))
Button('人像').onClick(() => this.changeMode('portrait'))
Button('夜景').onClick(() => this.changeMode('night'))
Button('专业').onClick(() => this.changeMode('professional'))
}
}
@Builder
buildCaptureControls() {
Row({ space: 20 }) {
Button('拍照')
.onClick(() => this.capturePhoto())
.enabled(this.captureStatus === 'ready')
Button('连拍')
.onClick(() => this.captureBurst())
Button('设置')
.onClick(() => this.showSettings())
}
}
private async changeMode(mode: string): Promise<void> {
this.currentMode = mode;
const photoMode = this.mapToPhotoMode(mode);
this.photoSession.setCaptureMode(photoMode);
}
private mapToPhotoMode(mode: string): PhotoCaptureMode {
switch (mode) {
case 'burst': return PhotoCaptureMode.BURST;
case 'portrait': return PhotoCaptureMode.PORTRAIT;
case 'night': return PhotoCaptureMode.NIGHT;
case 'professional': return PhotoCaptureMode.PROFESSIONAL;
default: return PhotoCaptureMode.STANDARD;
}
}
private async capturePhoto(): Promise<void> {
this.captureStatus = 'capturing';
const settings: camera.PhotoCaptureSetting = {
quality: camera.QualityLevel.QUALITY_LEVEL_HIGH,
rotation: camera.ImageRotation.ROTATION_0
};
const success = await this.photoSession.capture(settings);
if (success) {
this.photoCount++;
this.captureStatus = 'success';
} else {
this.captureStatus = 'error';
}
// 重置状态
setTimeout(() => {
this.captureStatus = 'ready';
}, 1000);
}
private async captureBurst(): Promise<void> {
this.captureStatus = 'burst_capturing';
const settings: camera.PhotoCaptureSetting = {
quality: camera.QualityLevel.QUALITY_LEVEL_MEDIUM,
rotation: camera.ImageRotation.ROTATION_0
};
const burstManager = new BurstCaptureManager(this.photoSession);
const success = await burstManager.captureBurst(settings, 5, 200);
if (success) {
this.photoCount += 5;
this.captureStatus = 'burst_success';
} else {
this.captureStatus = 'error';
}
setTimeout(() => {
this.captureStatus = 'ready';
}, 2000);
}
}
// 连拍管理器
class BurstCaptureManager {
private photoSession: AdvancedPhotoSession;
constructor(photoSession: AdvancedPhotoSession) {
this.photoSession = photoSession;
}
async captureBurst(
settings: camera.PhotoCaptureSetting,
count: number,
interval: number
): Promise<boolean> {
console.info(`Starting burst capture: ${count} photos`);
for (let i = 0; i < count; i++) {
const success = await this.photoSession.capture(settings);
if (!success) {
console.error(`Burst capture failed at photo ${i + 1}`);
return false;
}
// 连拍间隔(除了最后一张)
if (i < count - 1) {
await new Promise(resolve => setTimeout(resolve, interval));
}
}
console.info('Burst capture completed successfully');
return true;
}
}
总结
本章深入探讨了鸿蒙相机高级拍照功能的完整实现,涵盖了:
- 基础拍照架构 - PhotoOutput的深度配置和管理
- 分段式拍照 - 两阶段拍照优化用户体验
- 高性能拍照 - 快速缩略图和预热启动技术
- 动态照片 - 带视频片段的照片拍摄
- 多模式支持 - 标准、连拍、人像、夜景、专业等模式
- 企业级实现 - 完整的拍照会话管理和错误处理