Adding EXIF Metadata To Images On The iPhone

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];
}

Announcing Interlacer

My new iOS application, Interlacer, is now available in the App Store.

Interlacer is a photo application that combines multiple photos and/or colors into a new image. It does this by using alternating lines from each image and color. It is probably easier to illustrate with a picture:

You can take photos from within the application, select photos from your album, or select a color from the color picker. You can control the size of the lines and shift alternating lines to get a video interlace effect.

Two Is Spookier Than One

If you make any photos with Interlacer, feel free to add them to the Interlacer App Group on Flickr.

Jinx Updated

Jinx, a Java library to access the Flickr API, has been updated. The latest version supports these API entry points:
* activity
* auth
* blogs
* collections
* commons
* contacts
* favorites
* galleries
* groups
* groups.members
* photos
* photosets

You can get it on github.

Happy coding!