UIImageView not showing transparency of PNG Images from UIImagePickerController

非 Y 不嫁゛ 提交于 2019-11-28 01:59:32
Rob

Yes, the call to UIImageJPEGRepresentation will convert the resulting image into a JPEG, which doesn't support transparency.

BTW, if your intent is to get the NSData for the image for other reasons (e.g. uploading to server, emailing, etc.), I would recommend against both UIImageJPEGRepresentation and UIImagePNGRepresentation. They lose meta data, can make the asset larger, if suffer some image degradation if you use quality factor of less than 1, etc.

Instead, I'd recommend going back and get the original asset from the Photos framework. Thus, in Swift 3:

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    if let url = info[UIImagePickerControllerReferenceURL] as? URL {
        let result = PHAsset.fetchAssets(withALAssetURLs: [url], options: nil)
        if let asset = result.firstObject {
            let manager = PHImageManager.default()
            manager.requestImageData(for: asset, options: nil) { imageData, dataUTI, orientation, info in
                if let fileURL = info!["PHImageFileURLKey"] as? URL {
                    let filename = fileURL.lastPathComponent
                    // use filename here
                }

                // use imageData here
            }
        }
    }

    picker.dismiss(animated: true)
}

If you have to support iOS 7, too, you'd use the equivalent ALAssetsLibrary API, but the idea is the same: Get the original asset rather than round-tripping it through a UIImage.

(For Swift 2 rendition, see previous revision of this answer.)

Swift 3 version of answer by @Rob

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    if let URL = info[UIImagePickerControllerReferenceURL] as? NSURL {
        let result = PHAsset.fetchAssets(withALAssetURLs: [URL as URL], options: nil)
        if let asset:PHAsset = result.firstObject! as PHAsset {
            let manager = PHImageManager.default()
            manager.requestImageData(for: asset, options: nil) { imageData, dataUTI, orientation, info in
                let fileURL = info!["PHImageFileURLKey"] as? NSURL
                let filename = fileURL?.lastPathComponent;

                // use imageData here
            }
        }
    }

    picker.dismiss(animated: true, completion: nil)

}

An alternative solution uses the PHAssetResourceManager rather than PHImageManager. Using Xcode 10, Swift 4.2.

func imageFromResourceData(phAsset:PHAsset) {

    let assetResources = PHAssetResource.assetResources(for: phAsset)

    for resource in assetResources {

        if resource.type == PHAssetResourceType.photo {

            var imageData = Data()

            let options = PHAssetResourceRequestOptions()
            options.isNetworkAccessAllowed = true

            let _ = PHAssetResourceManager.default().requestData(for: resource, options: options, dataReceivedHandler: { (data:Data) in
                imageData.append(data)
            }, completionHandler: { (error:Error?) in
                if error == nil, let picked = UIImage(data: imageData) {
                    self.handlePickedImage(picked: picked)
                }
            })
        }

    }
}

Use it like this:

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {

    dismiss(animated: true)

    let mediaType = info[UIImagePickerController.InfoKey.mediaType] as! NSString

    if mediaType == kUTTypeImage || mediaType == kUTTypeLivePhoto {

        if #available(iOS 11.0, *) {

            if let phAsset = info[UIImagePickerController.InfoKey.phAsset] as? PHAsset {
                self.imageFromResourceData(phAsset: phAsset)
            }
            else {
                if let picked = (info[UIImagePickerController.InfoKey.originalImage] as? UIImage) {
                    self.handlePickedImage(picked: picked)
                }
            }

        }
        else if let picked = (info[UIImagePickerController.InfoKey.originalImage] as? UIImage) {
            self.handlePickedImage(picked: picked)
        }
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!