如何将 PHLivePhoto 转换为 UIImage?

How can I convert a PHLivePhoto to UIImage?

在我的应用程序中,我有一段代码需要考虑 PHLivePhoto 类型的对象并将其转换为 UIImage。我相信它与 PHAssetPHAssetResourcePHImageManager 有关,但不清楚如何执行转换。关于如何从 PHLivePhoto -> UIImage 转换的好方法是什么?感谢您的帮助!

if let livePhoto = object as? PHLivePhoto {
    let livePhotoResources = PHAssetResource.assetResources(for: livePhoto)
    print("\(livePhotoResources)")
    
    // imageBucket is of type UIImage[]
    // livePhoto is of type PHLivePhoto but I don't know how to convert this to type PHAsset
    viewModel.imageBucket.append(convertImageAsset(asset: **WHAT_DO_I_INSERT_HERE**))
}

...

func convertImageAsset(asset: PHAsset) -> UIImage {
            let manager = PHImageManager.default()
            let option = PHImageRequestOptions()
            var tmpImage = UIImage()
            option.isSynchronous = true
            manager.requestImage(
                for: asset,
                   targetSize: CGSize(width: asset.pixelWidth, height: asset.pixelHeight),
                   contentMode: .aspectFit,
                   options: option,
                   resultHandler: {(result, info)->Void in
                       tmpImage = result!
                   })
            return tmpImage
        }

结果:

[<PHAssetResource: 0x28225cdc0> {
    type: photo
    uti: public.heic
    filename: IMG_5442.heic
    asset: (null)
    locallyAvailable: YES
    fileURL: file:///private/var/mobile/Containers/Data/Application/2FB56305-7600-4A8E-9C67-A71B4A4A9607/tmp/live-photo-bundle/75FD3D97-F13E-4F79-A6E9-F0743D443FDD.pvt/IMG_5442.HEIC
    width: 0
    height: 0
    fileSize: 0
    analysisType: unavailable
    cplResourceType: Unknown
    isCurrent: NO
    isInCloud: NO
}, <PHAssetResource: 0x28226bc00> {
    type: video_cmpl
    uti: com.apple.quicktime-movie
    filename: IMG_5442.mov
    asset: (null)
    locallyAvailable: YES
    fileURL: file:///private/var/mobile/Containers/Data/Application/2FB56305-7600-4A8E-9C67-A71B4A4A9607/tmp/live-photo-bundle/75FD3D97-F13E-4F79-A6E9-F0743D443FDD.pvt/IMG_5442.MOV
    width: 0
    height: 0
    fileSize: 0
    analysisType: unavailable
    cplResourceType: Unknown
    isCurrent: NO
    isInCloud: NO
}]

您需要使用PHAsset获取资产,然后从PHImageManager.default()

请求图像数据
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
    dismiss(animated: true)
    
    guard let assetIdentifier = results.first?.assetIdentifier  else {
        return
    }
    
    if let phAsset = PHAsset.fetchAssets(withLocalIdentifiers: [assetIdentifier], options: nil).firstObject {
        PHImageManager.default().requestImageDataAndOrientation(for: phAsset, options: nil) { [weak self] data, _, _, _ in
            if let data = data, let image = UIImage(data: data) {
                self?.viewModel.imageBucket.append(image)
            }
        }
    }
}

要获取 assetIdentifier,您需要使用共享照片库创建 PHPickerConfiguration 对象。在没有照片库的情况下创建配置仅提供资产数据,不包括资产标识符。

var configuration = PHPickerConfiguration(photoLibrary: .shared())
// Set the filter type according to the user’s selection. .images is a filter to display images, including Live Photos.
configuration.filter = .images
// Set the mode to avoid transcoding, if possible, if your app supports arbitrary image/video encodings.
configuration.preferredAssetRepresentationMode = .current
// Set the selection limit.
configuration.selectionLimit = 1
    
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self
present(picker, animated: true)