UIImageView not showing transparency of PNG Images from UIImagePickerController

后端 未结 3 857
忘掉有多难
忘掉有多难 2020-12-07 02:21

I surely hope I am missing something because I do not understand why this is working the way it does. I have a PNG Image, which has a fully transparent background because I

相关标签:
3条回答
  • 2020-12-07 02:31

    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.)

    0 讨论(0)
  • 2020-12-07 02:34

    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)
    
    }
    
    0 讨论(0)
  • 2020-12-07 02:55

    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)
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题