我正在使用CGImage
中描述的代码从this answer中提取像素颜色。
但是,我刚刚意识到,如果加载在另一台设备上创建的图像,则像素值看起来不正确。第一个明显的问题是Alpha消失了。 CGImageAlphaInfo
报告.noneSkipLast
,但是我知道图像是RGBA。如果我从创建该设备的同一设备读取它,则看起来不错。第二个问题是有些颜色渗色,就好像图像已调整大小一样。也许是被压缩之类的东西。
这里是一个例子:
它是在我的iPad上创建的。但是,如果我使用链接的代码通过iCloud将其加载到iPhone上,则会得到以下信息:
alpha通道不见了,并且颜色出血。
[如果从同一部iPhone中,我使用Airdrop将小西瓜发送到我的Mac,然后再次使用Airdrop发送回(所以它应该是同一张图片!),然后立即加载,我会得到正确的图片:
[如果您有几个启用了iCloud的iOS设备,则可以在此应用中重现此行为:http://swiftpixels.endavid.com我在哪里使用该代码读取像素颜色。
这些图像之间有什么区别?如何从iCloud读取正确的图像?我应该在UIImage
中寻找提示,而不是CGImage
吗?
任何线索?谢谢!
更新
供参考,我正在使用UIImagePickerController
并使用以下代码读取图像:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
loadImageInMemory(image)
}
picker.dismiss(animated: true, completion: nil)
self.presentingViewController?.dismiss(animated: true, completion: nil)
}
fileprivate func loadImageInMemory(_ image: UIImage) {
/// skipping some preparation
guard let cgImage = image.cgImage else {
return
}
/// getImageData is a function like getPixelColor linked above,
/// but for a Rect
self.imageData = cgImage.getImageData(rect, width, height)
}
我也发现了可能与以下问题有关的问题:UIImagePickerController and iCloud photos
如Rob在下面的评论中所建议,我将手机中的“照片”设置更改为“下载并保留原件”(而不是“优化iPhone存储空间”),从而解决了该问题。所以我想问题是为什么iCloud尝试压缩只有1,355字节的PNG图像,以及是否有可能从UIImagePickerController
在“设置”应用中的“照片”下,有一个“优化iPhone存储空间”与“下载并保留原件”选项。后者应同步照片库,而不以任何方式更改图像。
不过,似乎Airdrop可以访问原始图像。
空投不依赖照片库iCloud同步来发送图像。这就是为什么资产可以不加更改地进行分配。
我如何也可以让我的应用访问原始文件?
取决于您是否真的要使用照片库来同步资产。这似乎尤其正确,因为许多人可能根本不选择将其庞大的照片库同步到iCloud。我不确定您是否要依靠它。
[您可能只想自己使用CloudKit,而不要依赖Photos库。也许您应该在应用程序中具有一个选项,以便用户可以选择完全使用iCloud存储,如果是这样,请在应用程序中进行iCloud存储,而不是依赖于照片库。
图像看起来模糊且没有Alpha的原因似乎是,默认情况下,Photos从iCloud传输Jpeg压缩图像。即使您的原始图像在不压缩的情况下也会变小,例如在此像素图示例中。
如Rob所指出的,一种验证情况的方法是更改“照片”设置。在“设置”应用中:
Settings -> Photos -> Download and Keep Originals
这可以解决问题,但当然不是可取的。如果您想继续使用照片,而不是实施自己的iCloud解决方案,而保持Optimize iPhone Storage
设置,则可以使用PhotoKit来检索原始图像。
替换此代码,
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
loadImageInMemory(image)
}
picker.dismiss(animated: true, completion: nil)
self.presentingViewController?.dismiss(animated: true, completion: nil)
}
通过此其他代码:
import Photos
// ...
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
// it will be loaded asynchronously
loadImageFromPicker(info: info)
picker.dismiss(animated: true, completion: nil)
self.presentingViewController?.dismiss(animated: true, completion: nil)
}
private func loadImageFromPicker(info: [UIImagePickerController.InfoKey : Any]) {
guard let referenceURL = info[UIImagePickerController.InfoKey.referenceURL] as? URL else {
return
}
let fetchResult = PHAsset.fetchAssets(withALAssetURLs: [referenceURL], options: nil)
guard let phAsset = fetchResult.firstObject else {
return
}
// size doesn't matter, because resizeMode = .none
let size = CGSize(width: 32, height: 32)
let options = PHImageRequestOptions()
options.version = .original
options.deliveryMode = .highQualityFormat
options.resizeMode = .none
options.isNetworkAccessAllowed = true
PHImageManager.default().requestImage(for: phAsset, targetSize: size, contentMode: .aspectFit, options: options) { [weak self] (image, info) in
if let s = self, let image = image {
s.loadImageInMemory(image)
}
}
}
此代码将与本地图像和iCloud图像一起使用。