我当然希望我错过了一些东西,因为我不明白为什么这样做会有所作为。我有一个PNG图像,它具有完全透明的背景,因为我想将它叠加在UIImageView
内的其他图像上。
XCode项目中包含的PNG图像都可以正常工作。问题是当我使用UIImagePickerController
动态选择这些相同的PNG图像然后将其分配给UIImageView
时,出于某些非常奇怪的原因,它不会将其视为具有透明度的PNG图像而是它添加了白色背景。
之前有人见过这个,我该如何解决这个问题?
*更新#1:我决定尝试一些似乎证实我理论的东西。我决定给自己发送电子邮件给我保存到我设备上的原始PNG图像,然后看到这些图像以JPG的形式传给我。在我看来,当你将图像保存到iPhone上的照片时它将它转换为JPG,这对我来说相当震撼。希望有人能解决这个问题。原始图片testImage1.png
和testImage2.png
已保存到照片中,然后通过电子邮件发回给自己,并以IMG_XXXX.jpg
和IMG_XXXX.jpg
*更新#2:我一直在玩这个,我发现了一些事情,并在此过程中能够回答我自己的问题。 (1)我在UPDATE#1中的理论是部分正确的,但保存Photo时转换不会发生,看起来就像是在飞行中。内部照片存储了原始图片扩展名(2)当我在UIImagePickerControllerDelegate
中意识到我正在使用时,我能够验证这一点
let imageData = UIImageJPEGRepresentation(image, 1.0)
而不是
let imageData = UIImagePNGRepresentation(image)
当我使用第二行代码时,它识别出图像的原始透明属性。
答案 0 :(得分:8)
是的,对UIImageJPEGRepresentation
的调用会将生成的图像转换为JPEG,但不支持透明度。
顺便说一下,如果您的目的是出于其他原因(例如上传到服务器,发送电子邮件等)获取图片的NSData
,我建议针对UIImageJPEGRepresentation
和{{1} }。它们会丢失元数据,可以使资产变大,如果使用质量因子小于1则会出现图像质量下降等情况。
相反,我建议回去并从Photos框架中获取原始资产。因此,在Swift 3中:
UIImagePNGRepresentation
如果你也必须支持iOS 7,你也可以使用等效的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)
}
API,但想法是一样的:获取原始资产而不是通过ALAssetsLibrary
对其进行四舍五入。
(对于Swift 2的演绎,请参阅previous revision of this answer。)
答案 1 :(得分:0)
@Rob
的Swift 3版本答案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)
}
答案 2 :(得分:0)
另一种解决方案使用PHAssetResourceManager而不是PHImageManager。使用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)
}
})
}
}
}
像这样使用它:
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)
}
}
}