PHImageManager 中的图像数据与保存为资产的图像数据不同

Posted

技术标签:

【中文标题】PHImageManager 中的图像数据与保存为资产的图像数据不同【英文标题】:Image data from PHImageManager differs from image data saved as asset 【发布时间】:2016-02-16 15:43:29 【问题描述】:

您好,提前感谢您花时间查看我的问题。

我正在创建一个位图,然后从该位图构建一个 PNG。然后我将该PNG保存到相册。在通过其本地标识符取回该资产,然后使用 PHImageManager 检索与该资产关联的 UIImage 后,我注意到图像的字节已更改。我不确定保存为 PHAsset 时是否添加了标头或什么,但我并没有真正看到插入和检索图像之间的任何公共字节。但是,当我将检索到的图像本身放入视图时,它看起来很正确,所以我很难过。

以下是一些演示问题的示例代码。

// image is a UIImage

// This is to show what the bytes are prior to saving
let imageRef = image.CGImage!
let cgData = CGDataProviderCopyData(CGImageGetDataProvider(imageRef))
let data = NSData(data: cgData)
let bytes = UnsafeMutablePointer<UInt8>(data.bytes)

print(data.length)
for i in 0..<16 
    print(bytes[i])


var assetIdentifier: String!

// collectionIdentifier is a valid local identifier for an existing collection
let collectionFetchRequest = PHAssetCollection.fetAssetCollectionsWithLocalIdentifiers([collectionIdentifier], options: nil)
let collection = collectionFetchRequest.firstObject as! PHAssetCollection

phphotoLibrary.sharedPhotoLibrary().performChanges(

    let assetCreationRequest = PHAssetChangeRequest.creationRequestForAssetFromImage(image)
    let collectionChangeRequest = PHAssetCollectionChangeRequest(forAssetCollection: collection)!
    let assetPlaceholder = assetCreationRequest.placeholderForCreatedAsset!
    collectionChangeRequest.addAssets([assetPlaceholder])
    assetIdentifier = assetPlaceholder.localIdentifier

)  (_, _) in

    let assetFetchRequest = PHAsset.fetchAssetsWithLocalIdentifiers([assetIdentifier], options: nil)
    let asset = assetFetchRequest.firstObject as! PHAsset

    let options = PHImageRequestOptions()
    options.synchronous = true
    options.version = .Current
    options.resizeMode = .None

    // The image is actually 64 x 64, but the targetSize doesn't seem to affect the bytes I'm getting out, I assume because the options aren't saying not to resize or crop anything
    // This was the not working code.
    // PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: CGSizeMake(256, 256), contentMode: .Default, options: options)  (retrievedImage, _) in

    // This is the working code.
    PHImageManager.defaultManager().requestImageDataForAsset(asset, options: options)  (data, _, _, _) in

        let retrievedImage = UIImage(data: data!)!

        // This is to show what the bytes are after retrieving
        let retrievedCGImage = retrievedImage!.CGImage!
        let retrievedCFData = CGDataProviderCopyData(CGImageGetDataProvider(retrievedCGImage))!
        let retrievedData = NSData(data: retrievedCFData)
        let retrievedBytes = UnsafeMutablePointer<UInt8>(retrievedData.bytes)

        // Length is the same but the bytes are not even close to right
        print(retrievedData.length)
        for i in 0..<16 
            print(retrievedBytes[i])
        

    

请随时更正此代码的任何不正确或低效的部分。此代码应该运行,因此如果您看到任何语法错误或输入错误的变量,这些仅在 *** 上而不在 XCode 中,因此它们不是导致此字节问题的原因。同样就图像中的字节而言,我不关心第 4 个字节,它是 alpha 分量,因为从我的测试到目前为止,它始终是 255。如果有人知道我如何使用第 4 个字节,而无需在保存图像时将其设置为 255,或者只是没有 alpha 组件,那也会有所帮助。

再次感谢您的时间和考虑!

编辑:

这是对回答者的完整回复:

感谢您的提醒。事实证明你对 requestImageDataForAsset 的工作是正确的。我将编辑原始代码块以反映工作代码。您知道它在文档中的哪个位置描述了 requestImageForAsset 返回的图像吗?

此外,您是否知道任何描述 requestImageDataForAsset 返回的数据的文档?图片存储机制我不是太熟悉,但是requestImageData返回的数据也和图片不完全匹配,直到变成UIImage。

再次感谢!

*** 的可爱界面使输入键提交评论,然后最多 5 分钟进行编辑。那太好了。

【问题讨论】:

【参考方案1】:

requestImageForAsset 方法不保证你得到字节完美的输出。我建议您尝试 requestImageDataForAsset 方法,它应该会给出您期望的结果。

【讨论】:

感谢您的提醒。事实证明你对 requestImageDataForAsset 的工作是正确的。我将编辑原始代码块以反映工作代码。您知道它在文档中的哪个位置描述了 requestImageForAsset 返回的图像吗?此外,您是否知道任何描述 requestImageDataForAsset 返回的数据的文档?我对图片存储机制不太熟悉,

以上是关于PHImageManager 中的图像数据与保存为资产的图像数据不同的主要内容,如果未能解决你的问题,请参考以下文章

PHImageManager 在许多图像请求后崩溃

在 iOS 8.3 中向 PHImageManager 请求图像会导致错误的图像

使用 PHImageManager 时,PHAsset 返回 UIImage 的 nil 值

PHImageManager.default().requestAVAsset 用于视频

如何在应用程序中保存图像

HighQualityFormat 的 PHImageManager.requestImageForAsset 从不调用 resultHandler