Papillon
Papillon

Reputation: 327

iOS: How to extract thumbnail and metadata from photo file on disk

Apple doc here https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/capturing_still_and_live_photos/capturing_thumbnail_and_preview_images explains how to capture thubnails.

At the bottom, it says

If you requested an embedded thumbnail image, that image isn't directly accessible from the AVCapturePhoto object—it's embedded in the image file data that you get by calling the photo object's fileDataRepresentation() method.

Seems impossible to separate the embedded thumbnail from the main photo. So what is the meaning of embedded thumbnail?

I want to save the AVCapturePhoto in JPG and raw DNG (requested embedded thumbnails for both) to App's Documents directory (I do not use PhotoKit) and then load it back to a UIImageView.

I save a photo like this:

if let data = capturePhoto.fileDataRepresentation() {
    data.write(to: documentsPath, options: [])
}

And load it back to a UIImage like this:

if let data = FileManager.default.contents(at: path) {
    let image = UIImage(data: data)
}

But it will be better to load the embedded thubmail first. If a user clicks to see the large image, load the full imgage file then.

I also want to show the metadata, e.g., GPS location, flash status, ISO, shutter speed etc. I wonder how to do that.

Upvotes: 5

Views: 1124

Answers (1)

Gordon Childs
Gordon Childs

Reputation: 36169

AVFoundation's AVAsset wraps some metadata types, but apparently not EXIF data. If you want the thumbnail you have to use the CoreGraphics framework. This function fetches the thumbnail if present, limiting the maximum side length to 512 pixels.

public func getImageThumbnail(url: URL) -> CGImage? {
    guard let imageSource = CGImageSourceCreateWithURL(url as CFURL, nil) else { return nil }
    
    let thumbnailOptions: [String: Any] = [
        kCGImageSourceCreateThumbnailWithTransform as String: true,
        kCGImageSourceCreateThumbnailFromImageIfAbsent as String: false, // true will create if thumbnail not present
        kCGImageSourceThumbnailMaxPixelSize as String: 512
    ]
    return CGImageSourceCreateThumbnailAtIndex(imageSource, 0, thumbnailOptions as CFDictionary);
}

For all the rest of the metadata, you can use CGImageSourceCopyPropertiesAtIndex or CGImageSourceCopyMetadataAtIndex.

Upvotes: 4

Related Questions