[iCloud中存储的图像中的CGImage看起来不正确

问题描述 投票:1回答:2

我正在使用CGImage中描述的代码从this answer中提取像素颜色。

但是,我刚刚意识到,如果加载在另一台设备上创建的图像,则像素值看起来不正确。第一个明显的问题是Alpha消失了。 CGImageAlphaInfo报告.noneSkipLast,但是我知道图像是RGBA。如果我从创建该设备的同一设备读取它,则看起来不错。第二个问题是有些颜色渗色,就好像图像已调整大小一样。也许是被压缩之类的东西。

这里是一个例子:

来源图片是这个西瓜,12x12Source image

它是在我的iPad上创建的。但是,如果我使用链接的代码通过iCloud将其加载到iPhone上,则会得到以下信息:

Bad sampling

alpha通道不见了,并且颜色出血。

[如果从同一部iPhone中,我使用Airdrop将小西瓜发送到我的Mac,然后再次使用Airdrop发送回(所以它应该是同一张图片!),然后立即加载,我会得到正确的图片:

Correct image(深褐色区域是alpha为0的地方)

[如果您有几个启用了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

访问原始图像
ios uiimage icloud cgimage
2个回答
1
投票

在“设置”应用中的“照片”下,有一个“优化iPhone存储空间”与“下载并保留原件”选项。后者应同步照片库,而不以任何方式更改图像。

不过,似乎Airdrop可以访问原始图像。

空投不依赖照片库iCloud同步来发送图像。这就是为什么资产可以不加更改地进行分配。

我如何也可以让我的应用访问原始文件?

取决于您是否真的要使用照片库来同步资产。这似乎尤其正确,因为许多人可能根本不选择将其庞大的照片库同步到iCloud。我不确定您是否要依靠它。

[您可能只想自己使用CloudKit,而不要依赖Photos库。也许您应该在应用程序中具有一个选项,以便用户可以选择完全使用iCloud存储,如果是这样,请在应用程序中进行iCloud存储,而不是依赖于照片库。


0
投票

图像看起来模糊且没有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图像一起使用。

© www.soinside.com 2019 - 2024. All rights reserved.