EXIF creation date of ICCameraFile always nil?

I am using ImageCaptureCore to access and (sometimes) download media files from a digital camera connected via USB (either to a Mac oder to an iOS device with Apple lightning to USB3 camera adapter).

This works very well in general, but what puzzles me is that for the ICCameraFile's EXIF creation/modification date, it always returns nil. I can access the ICCameraItem's creation/modification date instead, which, as it says in the documentation "usually [is] the same as its EXIF creation date", but, well not always. Generally the EXIF tags are more reliable than the file dates, especially the modification date is easily messed up when copying files.

As for my cameras, they show the stable EXIF date on their display, so for consistency I would prefer to use the same in my app. Is there a way to get it without downloading the image from the camera and reading it from the file?

Does it possibly depend on the brand of camera (I mostly have Canon) whether ICCameraFile.exifCreationDate is ever populated or always nil?

For a thumb drive with DCIM folder, which is treated just like a camera, it is also nil.

Answered by DTS Engineer in 814147022

Thanks for asking. Are you able to verify that the EXIF creation/modification you are not able to receive from Core Image are present using the EXIF tab in the Preview app's Inspector? If so, this may be a bug.

If you can see these dates in Preview but not when calling the Core Image APIs, our engineering teams need to investigate this issue, as resolution may involve changes to Apple's software. Please open a bug report, include a small Xcode project that includes one of your images with its EXIF data, and post the FB number here once you do.

Bug Reporting: How and Why? has tips on creating your bug report.

In the interim, you may also wish to try the Image I/O APIs to check your EXIF data. Here is how you can use Image I/O to extract get the EXIF data from an image file:


guard let image_data_source: CGImageSource = CGImageSourceCreateWithURL(theURL as CFURL, nil) else {
	throw .errorCreatingImageSource(theURL) }
guard let sourceProps = CGImageSourceCopyPropertiesAtIndex(image_data_source, 0, [:] as CFDictionary) as? [AnyHashable: Any] else {
	throw .errorGettingImageProperties(theURL) }
if let exif_data: [AnyHashable : Any] = sourceProps[kCGImagePropertyExifDictionary] as? [AnyHashable : Any] {
	
	
	// using kCGImagePropertyExifDateTimeOriginal and kCGImagePropertyExifDateTimeDigitized keys...

}

Note, the EXIF standard seems to have two keys that appear to be relevant in this case.

  • kCGImagePropertyExifDateTimeDigitized ("DateTimeDigitized") is defined as the time when the image was stored as digital data
  • kCGImagePropertyExifDateTimeDigitized ("DateTimeOriginal") is defined as the time when the original image was generated.

I suggest doing a double check to verify your camera is providing the one you are using.

Thanks for asking. Are you able to verify that the EXIF creation/modification you are not able to receive from Core Image are present using the EXIF tab in the Preview app's Inspector? If so, this may be a bug.

If you can see these dates in Preview but not when calling the Core Image APIs, our engineering teams need to investigate this issue, as resolution may involve changes to Apple's software. Please open a bug report, include a small Xcode project that includes one of your images with its EXIF data, and post the FB number here once you do.

Bug Reporting: How and Why? has tips on creating your bug report.

In the interim, you may also wish to try the Image I/O APIs to check your EXIF data. Here is how you can use Image I/O to extract get the EXIF data from an image file:


guard let image_data_source: CGImageSource = CGImageSourceCreateWithURL(theURL as CFURL, nil) else {
	throw .errorCreatingImageSource(theURL) }
guard let sourceProps = CGImageSourceCopyPropertiesAtIndex(image_data_source, 0, [:] as CFDictionary) as? [AnyHashable: Any] else {
	throw .errorGettingImageProperties(theURL) }
if let exif_data: [AnyHashable : Any] = sourceProps[kCGImagePropertyExifDictionary] as? [AnyHashable : Any] {
	
	
	// using kCGImagePropertyExifDateTimeOriginal and kCGImagePropertyExifDateTimeDigitized keys...

}

Note, the EXIF standard seems to have two keys that appear to be relevant in this case.

  • kCGImagePropertyExifDateTimeDigitized ("DateTimeDigitized") is defined as the time when the image was stored as digital data
  • kCGImagePropertyExifDateTimeDigitized ("DateTimeOriginal") is defined as the time when the original image was generated.

I suggest doing a double check to verify your camera is providing the one you are using.

I am afraid that you misunderstood the issue: It is not about missing EXIF data after downloading the image from the camera. At that stage, EXIF data is present (e.g. in Preview) and there are ways to retrieve it via UIImage or CGImage.

The issue is about accessing the EXIF data before downloading the actual images from the camera. The goal is to compile a list of image thumbnails and image meta data, and to let the user decide which ones to actually download, or to automatically select only certain images based on names, dates, or possibly other criteria.

Access to this data on the camera itself should work via ICCameraFile, but for the EXIF dates, I always get nil. The (less reliable) file dates of ICCameraItem are available, though. The Image Capture app on MacOS displays this last date, and currently so do I in my own app. However I am wondering under what circumstances the actual EXIF date (which I would prefer) is accessible, considering that there already is a dedicated property for it.

I have just noticed that I can in fact access EXIF "DateTimeOriginal" (among others) via requestMetaData() and didReceiveMetadata(). This still does not populate the ICCameraFile.exifCreationDate, though. While I now have a workaround, I still wonder what the purpose of this empty field is.

EXIF creation date of ICCameraFile always nil?
 
 
Q