iOS: PHAsset & 检测 DNG RAW 格式

iOS: PHAsset & Detecting DNG RAW Format

我得到了 Apple 的“SamplePhotosApp”示例代码,并在相册网格照片布局中尝试检测 DNG RAW 文件(如果是 DNG,请贴上徽章)。

默认 cellForItemAt:

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let asset = fetchResult.object(at: indexPath.item)

        // Dequeue a GridViewCell.
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: GridViewCell.self), for: indexPath) as? GridViewCell
            else { fatalError("unexpected cell in collection view") }

        // Add a badge to the cell if the PHAsset represents a Live Photo.
        if asset.mediaSubtypes.contains(.photoLive) {
            cell.livePhotoBadgeImage = PHLivePhotoView.livePhotoBadgeImage(options: .overContent)
        }

        // Request an image for the asset from the PHCachingImageManager.
        cell.representedAssetIdentifier = asset.localIdentifier
        imageManager.requestImage(for: asset, targetSize: thumbnailSize, contentMode: .aspectFill, options: nil, resultHandler: { image, _ in
            // The cell may have been recycled by the time this handler gets called;
            // set the cell's thumbnail image only if it's still showing the same asset.
            if cell.representedAssetIdentifier == asset.localIdentifier {
                cell.thumbnailImage = image
            }
        })

        return cell

    }

DNG/RAW格式

对于 DNG 文件,可以在其中嵌入预览或缩略图(iOS11),当然还可以附加一个完全独立的 JPEG。

使用上面的代码,requestImage 仍然通过提取其嵌入的 JPEG 来显示 DNG 文件。但是,它不知道 PHAsset 实际上是一个 DNG 文件。

如何确定 PHAsset 是否为 DNG?


我尝试过的事情

let fileExtension = ((asset.value(forKey: "uniformTypeIdentifier") as! NSString).pathExtension as NSString).uppercased
if fileExtension == "DNG" || fileExtension == "RAW-IMAGE" {
     //Show RAW Badge
}

以上仅在 DNG 文件仅嵌入了预览 JPEG 时才有效。如果它嵌入了常规的全尺寸 JPEG,它会将 PHAsset 识别为 JPEG。

有人告诉我试试这个:

let res = PHAssetResource.assetResources(for: asset)

但某个资产可能有多个资源(调整数据等)。我怎样才能完成这项工作?

一些概念背景:在 PhotoKit 中可以在三个层次上工作...

  • 当您与 PHAsset 和朋友一起工作时,您处于抽象模型级别。每个资产都是照片数据库中的一个条目——单个 "thing" 在照片应用程序中显示为缩略图。在这一层,它只是一个 "thing"(不是像素缓冲区或视频数据流)。

  • 当您使用 PHImageManager 时,您仍然在抽象地工作。你告诉 PhotoKit,"give me an image (or video) that's an appropriate way to display this asset to the user in these circumstances." 什么样的文件包含资产的原始数据仍然在这个级别被抽象掉。

  • 每个摘要 "things" 可能有一个或多个原始文件提供其图像或视频数据、内在元数据等。要处理此类问题(包括文件格式),您需要使用 PHAssetResource(可能还有 PHAssetResourceManager)。

因此,如果您要查找资产是否包含 RAW 或 DNG 数据,则需要查看其资源。

  1. 使用PHAssetResource.assetResources(for:)获取资产对应的资源集合。

  2. 通过检查每个资源的 type 属性 来缩小资源列表 — 由 RAW 或 DNG 文件支持的资产应将其存储在 alternatePhoto类型。 (虽然第三方应用程序至少有可能使用 fullSizePhoto 类型写入 DNG 文件,因此您也可以在那里检查。)

  3. 检查uniformTypeIdentifier property for each resource in your narrowed list. The UTI for DNG files is "com.adobe.raw-image" (in Xcode 9 there's a string constant for this, AVFileTypeDNG). That's probably fine if you want just DNG files, but to more broadly check for RAW files it's probably better test whether the resource's UTI conforms to "public.camera-raw-image" aka kUTTypeRawImage