鸿蒙高级拍照功能实战:从基础拍照到高级特性

64 阅读8分钟

鸿蒙高级拍照功能实战:从基础拍照到高级特性

1. 拍照功能架构深度解析

1.1 拍照系统整体架构

鸿蒙相机拍照功能建立在完整的流水线架构之上,涉及多个组件的协同工作:

text

CameraInput → Session → PhotoOutput → Image Processing → Media Library

拍照数据流详解:

  1. 图像采集:CameraInput从相机硬件获取原始图像数据
  2. 流水线处理:Session管理多个输出流的协调和数据分发
  3. 图像编码:PhotoOutput负责将图像数据编码为指定格式
  4. 后处理:可选的美颜、滤镜、HDR等图像增强处理
  5. 存储管理:通过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;
  }
}

总结

本章深入探讨了鸿蒙相机高级拍照功能的完整实现,涵盖了:

  1. 基础拍照架构 - PhotoOutput的深度配置和管理
  2. 分段式拍照 - 两阶段拍照优化用户体验
  3. 高性能拍照 - 快速缩略图和预热启动技术
  4. 动态照片 - 带视频片段的照片拍摄
  5. 多模式支持 - 标准、连拍、人像、夜景、专业等模式
  6. 企业级实现 - 完整的拍照会话管理和错误处理