iOS加载WebP格式图片时如何保留透明通道?
问题
从PHPickerViewController传入的NSItemProvider数组中导入图片时,PNG格式能正确保留透明通道,但WebP格式无法保留。已确认saveImage函数不会导致透明性丢失,问题出在item.loadDataRepresentation(forTypeIdentifier: UTType.webP.identifier)调用或Data实例化为UIImage的过程中。相关代码如下:
private func save(itemProviders: [NSItemProvider]) async throws -> Int { return try await withCheckedThrowingContinuation({ continuation in let group = DispatchGroup() var failureCount = 0 for item in itemProviders { // webp format image if item.hasItemConformingToTypeIdentifier(UTType.webP.identifier) { group.enter() item.loadDataRepresentation(forTypeIdentifier: UTType.webP.identifier) { data, error in defer { group.leave() } guard let data, let image = UIImage(data: data) else { return } self.saveImage(image) } } else if item.canLoadObject(ofClass: UIImage.self) { // other image formats, including PNG group.enter() item.loadObject(ofClass: UIImage.self) { (image, error) in defer { group.leave() } guard let image = image as? UIImage else { return } self.saveImage(image) } } else { failureCount += 1 } } group.notify(queue: .main) { continuation.resume(returning: failureCount) } }) }
解决方案
- 移除WebP单独处理分支,统一使用
loadObject(ofClass: UIImage.self)加载所有图片类型。iOS 14及以上系统的UIImage原生支持WebP解码,通过loadObject加载时会自动保留透明通道。 - 修改后的代码如下:
private func save(itemProviders: [NSItemProvider]) async throws -> Int { return try await withCheckedThrowingContinuation({ continuation in let group = DispatchGroup() var failureCount = 0 for item in itemProviders { if item.canLoadObject(ofClass: UIImage.self) { group.enter() item.loadObject(ofClass: UIImage.self) { (image, error) in defer { group.leave() } guard let image = image as? UIImage else { failureCount += 1 return } self.saveImage(image) } } else { failureCount += 1 } } group.notify(queue: .main) { continuation.resume(returning: failureCount) } }) }
- 问题根源:直接加载WebP的Data Representation再实例化UIImage时,系统未正确解析透明通道的元数据;而通过
loadObject(ofClass: UIImage.self)让系统完成解码流程,能完整保留图片的透明属性。
内容的提问来源于stack exchange,提问作者stackunderflow
相关产品推荐
相关产品推荐

