EXIF metadata is embedded in most of the images created by digital cameras, and the iPhone is no exception. This can include information about the camera that made the photo, the software used to process it, the data and time, geolocation information, and many other pieces of interesting information.

When I was developing Interlacer, one of my goals was to include information about how the photo was created. Since Interlacer creates a new photo from multiple sources, the EXIF metadata block in the final image is missing. I didn’t want to just copy metadata from the source images, since there is no guarantee that the metadata in the source images would be relevant to the final image. I decided that I wanted to save the name and version of the app, some information about the source images that were used to create the final image, and the date and time the final image was created.

There are a lot of examples of how to manipulate the existing EXIF data in an image on the iPhone, but I didn’t find much information about how to add EXIF data to an image that did not contain any. The solution turned out to be quite straightforward. When an image is saved using the ALAssetsLibrary class, a dictionary of metadata can be included. This dictionary includes some basic metadata and can also include dictionaries of other metadata, such as EXIF and TIFF metadata. The keys for all these metadata values are constants declared in ImageIO/CGImageProperties.h.

Depending on the information you want to save, you may need several dictionaries, each containing a specific type of metadata. In Interlacer, the date and time and image dimensions are saved as EXIF metadata, and information about Interlacer and the source images is saved as TIFF metadata.

Here is the code showing how to create EXIF and TIFF dictionaries and save the information along with an image:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
- (void)saveImageAndAddMetadata:(UIImage *)image
{
    // Format the current date and time
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyy:MM:dd HH:mm:ss"];
    NSString *now = [formatter stringFromDate:[NSDate date]];
    [formatter release];
   
    // Exif metadata dictionary
    // Includes date and time as well as image dimensions
    NSMutableDictionary *exifDictionary = [NSMutableDictionary dictionary];
    [exifDictionary setValue:now forKey:(NSString *)kCGImagePropertyExifDateTimeOriginal];
    [exifDictionary setValue:now forKey:(NSString *)kCGImagePropertyExifDateTimeDigitized];
    [exifDictionary setValue:[NSNumber numberWithFloat:image.size.width] forKey:(NSString *)kCGImagePropertyExifPixelXDimension];
    [exifDictionary setValue:[NSNumber numberWithFloat:image.size.height] forKey:(NSString *)kCGImagePropertyExifPixelYDimension];
   
    // Tiff metadata dictionary
    // Includes information about the application used to create the image
    // "Make" is the name of the app, "Model" is the version of the app
    NSMutableDictionary *tiffDictionary = [NSMutableDictionary dictionary];
    [tiffDictionary setValue:now forKey:(NSString *)kCGImagePropertyTIFFDateTime];
    [tiffDictionary setValue:@"Interlacer" forKey:(NSString *)kCGImagePropertyTIFFMake];
   
    NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
    NSString *build = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
    [tiffDictionary setValue:[NSString stringWithFormat:@"%@ (%@)", version, build] forKey:(NSString *)kCGImagePropertyTIFFModel];
   
    // Image metadata dictionary
    // Includes image dimensions, as well as the EXIF and TIFF metadata
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    [dict setValue:[NSNumber numberWithFloat:image.size.width] forKey:(NSString *)kCGImagePropertyPixelWidth];
    [dict setValue:[NSNumber numberWithFloat:image.size.height] forKey:(NSString *)kCGImagePropertyPixelHeight];
    [dict setValue:exifDictionary forKey:(NSString *)kCGImagePropertyExifDictionary];
    [dict setValue:tiffDictionary forKey:(NSString *)kCGImagePropertyTIFFDictionary];
   
    ALAssetsLibrary *al = [[ALAssetsLibrary alloc] init];
   
    [al writeImageToSavedPhotosAlbum:[image CGImage]
                            metadata:dict
                     completionBlock:^(NSURL *assetURL, NSError *error) {
                         if (error == nil) {
                             // notify user image was saved
                         } else {
                             // handle error
                         }
                     }];
   
    [al release];
}