将带人像效果遮罩的图像保存到PHPhotoLibrary是否无法实现?
问题结论
该能力不是苹果自带相机的专属API,你遇到的元数据丢失问题是PHAssetCreationRequest接口的调用方式不对导致的。
核心原因
直接调用addResource(with:data:options:)传入AVCapturePhoto的内存数据时,系统会默认过滤第三方写入的辅助元数据,仅保留视差数据,人像遮罩、深度数据都会被剥离。
两种可行解决方案
方案1:通过临时文件导入(操作最简单,兼容性最好)
你已经验证过序列化后的AVCapturePhoto写入本地文件后所有元数据完整,可以直接用这个特性实现:
- 将
AVCapturePhoto的fileDataRepresentation()输出的原始数据直接写入沙盒临时目录,不要做任何压缩、转码操作 - 调用
PHAssetCreationRequest的addResource(with:fileURL:options:)方法,传入临时文件的本地URL - 相册写入完成后删除临时文件即可
这个方式会让系统直接读取文件内的完整元数据,不会主动剥离人像遮罩和深度数据。
方案2:手动添加人像遮罩作为独立辅助资源
如果不想生成临时文件,可以在创建相册资源时手动添加人像遮罩数据:
PHPhotoLibrary.shared().performChanges { let request = PHAssetCreationRequest.forAsset() // 先添加主照片资源 guard let photoData = photo.fileDataRepresentation() else { return } let mainOpts = PHAssetResourceCreationOptions() mainOpts.shouldMoveFile = false request.addResource(with: .photo, data: photoData, options: mainOpts) // 单独添加人像遮罩资源 if let matte = photo.portraitEffectsMatte, let matteData = matte.mattingData { let matteOpts = PHAssetResourceCreationOptions() matteOpts.uniformTypeIdentifier = kUTTypePortraitEffectsMatte as String request.addResource(with: .auxiliary, data: matteData, options: matteOpts) } } completionHandler: { success, error in // 处理结果 }
[PHPhotoLibrary.sharedPhotoLibrary performChanges:^{ PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAsset]; NSData *photoData = [photo fileDataRepresentation]; if (!photoData) return; // 添加主图 PHAssetResourceCreationOptions *mainOpts = [[PHAssetResourceCreationOptions alloc] init]; mainOpts.shouldMoveFile = NO; [request addResourceWithType:PHAssetResourceTypePhoto data:photoData options:mainOpts]; // 添加人像遮罩 AVPortraitEffectsMatte *matte = photo.portraitEffectsMatte; NSData *matteData = matte.mattingData; if (matte && matteData) { PHAssetResourceCreationOptions *matteOpts = [[PHAssetResourceCreationOptions alloc] init]; matteOpts.uniformTypeIdentifier = (__bridge NSString *)kUTTypePortraitEffectsMatte; [request addResourceWithType:PHAssetResourceTypeAuxiliary data:matteData options:matteOpts]; } } completionHandler:^(BOOL success, NSError * _Nullable error) { // 处理结果 }];
注意事项
- 仅iOS 13及以上系统支持第三方应用写入人像遮罩数据,更低版本的系统确实只有系统相机可以写入该类元数据
- 写入后可以通过
PHAssetResource.assetResources(for: asset)遍历资源,检查是否存在UTI为portraitEffectsMatte的辅助资源,确认写入成功
内容的提问来源于stack exchange,提问作者Ari J.R.
相关产品推荐
相关产品推荐

