iosxcodeuicollectionviewphassetdng

iOS: PHAsset & Detecting DNG RAW Format


I got Apple's sample code for 'SamplePhotosApp' and in the photo album grid photo layout, trying to detect DNG RAW files (put up a badge if it's DNG).

Default 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 Format

With DNG files, there could be a preview or thumbnail (with iOS11) embedded in it, and of course a completely separate JPEG attached to it.

With above code, requestImage still displays DNG files by pulling out its embedded JPEG. However, it doesn't know that the PHAsset is actually a DNG file.

How can I find out if the PHAsset is a DNG?


Things I Tried

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

Above works only if the DNG file has just the preview JPEG embedded. If it has a regular full-size JPEG embedded, it recognize the PHAsset as a JPEG.

I've been told to try this:

let res = PHAssetResource.assetResources(for: asset)

But a certain asset could have several number of resources (adjustment data, etc). How would I be able to make this work?


Solution

  • Some conceptual background: there are sort of three levels to work at in PhotoKit...

    So, if you're looking to find out whether an asset contains RAW or DNG data, you'll need to look at its resources.

    1. Use PHAssetResource.assetResources(for:) to get the set of resources corresponding to an asset.

    2. Narrow down the list of resources by checking the type property for each — an asset backed by a RAW or DNG file should store it in a resource of the alternatePhoto type. (Though there's at least some possibility that third-party apps could write DNG files using the fullSizePhoto type, so you might check there, too.)

    3. Check the 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.