I am using ImageIO framework for updating metadata of UIImage then after I saved that image in my iphone photoLibrary my issue is that I am updating the Image TIFF data successfully in image but when I select that image for get TIFF data then it not displaying the TIFF dictionary data .online I can see updated TIFF data but in my code i can't see it.
Updated TIFF Data:
"{TIFF}" = {
Make = "test ";
Model = test;
Software = test;
};
Get updated Image metadata in iOS:
{
ColorModel = RGB;
Depth = 8;
PixelHeight = 2592;
PixelWidth = 1936;
"{PNG}" = {
InterlaceType = 0;
};
}
Code:
NSData *imageData = UIImagePNGRepresentation(image);
CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef )imageData, NULL);
if (imageSource == NULL) {
// Error loading image
return nil;
}
//Set the object in dictinary
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:NO], (NSString *)kCGImageSourceShouldCache,
nil];
CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, (__bridge CFDictionaryRef)options);
//Device name
CFDictionaryRef refDeviceInfo = CFDictionaryGetValue(imageProperties, kCGImagePropertyTIFFDictionary);
if (refDeviceInfo) {
NSString *strMake = (NSString *)CFDictionaryGetValue(refDeviceInfo, kCGImagePropertyTIFFMake);
NSLog(#"Make: %#", strMake);
NSString *strModel = (NSString *)CFDictionaryGetValue(refDeviceInfo, kCGImagePropertyTIFFModel);
NSLog(#"Model: %#", strModel);
}
Related
I have created a custom camera using AVFoundation, now after capturing images, I need to save them in the iPhone's gallery.
I tried saving images with UIImageWriteToSavedPhotosAlbum but found that this does not save EXIF information.
To Save EXIF information with an image refer below code.
- (void)saveImageDataToPhotoAlbum:(NSData *)originalData
{
NSDictionary *dataDic = [self getDataAndMetadata:originalData];
ALAssetsLibrary *assetsLib = [[ALAssetsLibrary alloc] init];
[assetsLib writeImageDataToSavedPhotosAlbum:dataDic[#"data"]
metadata:dataDic[#"metadata"]
completionBlock:^(NSURL *url, NSError *e) {
[self addToMyAlbum:url];
}];
}
- (NSDictionary *)getDataAndMetadata:(NSData *)originalData
{
CGImageSourceRef cimage = CGImageSourceCreateWithData((CFDataRef)originalData, nil);
NSDictionary *metadata = (NSDictionary *)CGImageSourceCopyPropertiesAtIndex(cimage, 0, nil);
NSMutableDictionary *metadataAsMutable = [NSMutableDictionary dictionaryWithDictionary:metadata];
metadataAsMutable[(NSString *)kCGImagePropertyGPSDictionary] = self.myGpsDic;
NSMutableData *dataForMetadataRemoval = [NSMutableData data];
CGImageDestinationRef dest =
CGImageDestinationCreateWithData((CFMutableDataRef)dataForMetadataRemoval, CGImageSourceGetType(cimage), 1, nil);
CGImageDestinationAddImageFromSource(dest, cimage, 0, (CFDictionaryRef)metadataAsMutable);
CGImageDestinationFinalize(dest);
CFRelease(dest);
[metadata release];
CFRelease(cimage);
return #{ #"data" : (dataForMetadataRemoval), #"metadata" : metadataAsMutable};
}
return metadataAsMutable;
}
I'm attempting to read the metadata produced by a UIImage when shot from the UIImagePicker, and I'm having some trouble.
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
image = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
// get the metadata
NSDictionary *imageMetadata = [info objectForKey:UIImagePickerControllerMediaMetadata];
NSLog (#"imageMetaData %#",imageMetadata);
This successfully prints the metadata dictionary to NSLog.
The issue I'm having is that I would like to access specific indices of the dictionary (such as FNumber, ISO, etc.) and print them to specific labels, but I can't figure out how to access the individual data.
Here is what I have tried so far to pull the data, but it doesn't seem to find the key (it returns as NULL):
NSLog(#"ISO: %#", imageMetadata[#"ISOSpeedRatings"]);
Based off of what NSLog prints for the dictionary, it seems as if there may be dictionaries within the dictionary, and that's what's throwing me off.
Here's what gets printed for the metadata:
imageMetaData {
DPIHeight = 72;
DPIWidth = 72;
Orientation = 6;
"{Exif}" = {
ApertureValue = "2.27500704749987";
BrightnessValue = "-0.6309286396300304";
ColorSpace = 1;
DateTimeDigitized = "2015:04:01 10:33:37";
DateTimeOriginal = "2015:04:01 10:33:37";
ExposureBiasValue = 0;
ExposureMode = 0;
ExposureProgram = 2;
ExposureTime = "0.06666666666666667";
FNumber = "2.2";
Flash = 24;
FocalLenIn35mmFilm = 29;
FocalLength = "4.15";
ISOSpeedRatings = (
320
);
LensMake = Apple;
LensModel = "iPhone 6 back camera 4.15mm f/2.2";
LensSpecification = (
"4.15",
"4.15",
"2.2",
"2.2"
);
MeteringMode = 5;
PixelXDimension = 3264;
PixelYDimension = 2448;
SceneType = 1;
SensingMethod = 2;
ShutterSpeedValue = "3.907056515078773";
SubjectArea = (
1631,
1223,
1795,
1077
);
SubsecTimeDigitized = 705;
SubsecTimeOriginal = 705;
WhiteBalance = 0;
};
"{MakerApple}" = {
1 = 2;
14 = 0;
2 = <0f000b00 06000900 04005000 a900b100 b700bb00 c400cd00 cd00a400 b100c700 14000b00 05000900 06000a00 8a00a800 b000b800 c300cb00 c900cd00 b300a600 2f000700 06000700 0a000400 3500a400 ab00b300 bc00c300 cf00d300 b4007f00 3f000700 09000700 0a000700 05007100 a100af00 b500c200 ce00cd00 a9006b00 1f000a00 0b000900 0a000c00 05001e00 9c00aa00 b400c200 cc00d000 d4005700 2b001900 0d001000 10000d00 08000600 5b00a700 b300bf00 cb00d500 e3008600 eb002800 1a001700 14000c00 0b000700 10009400 b100c000 ce00e000 f400bd00 cf013e00 2a001200 17000f00 0d000800 07004200 b100c000 d300e900 fd000401 ff011101 1d000700 16001400 09000700 07000900 8900bf00 d800ec00 07011f01 10021102 39000b00 10001900 0e000800 0a000700 2c00bf00 dd00f400 0b012401 1e023802 1f010d00 07001900 16000c00 0c000800 21007000 c500f400 0a012e01 10022202 01022500 08001000 18001100 0d001800 1601cc00 d100eb00 09012201 fb011002 26020401 0f000700 16001400 3200e801 6001b000 ce00f400 08011601 e1010602 1a020302 23001700 21002300 84009300 9f00ad00 bf00e800 02011401 ca01fc01 19024002 08013d00 3500ca00 7c009200 9e00ab00 c200d700 f8000a01 b401f101 1b024802 28023000 4a007f00 7f008e00 a000b100 bd00d000 ec00fe00>;
3 = {
epoch = 0;
flags = 1;
timescale = 1000000000;
value = 777291330499583;
};
4 = 1;
5 = 128;
6 = 123;
7 = 1;
8 = (
"0.2226092",
"-0.5721548",
"-0.7796207"
);
9 = 275;
};
"{TIFF}" = {
DateTime = "2015:04:01 10:33:37";
Make = Apple;
Model = "iPhone 6";
Software = "8.1.2";
XResolution = 72;
YResolution = 72;
};
}
Is the data I'm looking for within another NSDictionary named Exif? And if so, how do I access it?
#david strauss can you try this once
- (void) saveImage:(UIImage *)imageToSave withInfo:(NSDictionary *)info{
// Get the assets library
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
// Get the image metadata (EXIF & TIFF)
NSMutableDictionary * imageMetadata = [[info objectForKey:UIImagePickerControllerMediaMetadata] mutableCopy];
// add GPS data
CLLocation * loc = <•••>; // need a location here
if ( loc ) {
[imageMetadata setObject:[self gpsDictionaryForLocation:loc] forKey:(NSString*)kCGImagePropertyGPSDictionary];
}
ALAssetsLibraryWriteImageCompletionBlock imageWriteCompletionBlock =
^(NSURL *newURL, NSError *error) {
if (error) {
NSLog( #"Error writing image with metadata to Photo Library: %#", error );
} else {
NSLog( #"Wrote image %# with metadata %# to Photo Library",newURL,imageMetadata);
}
};
// Save the new image to the Camera Roll
[library writeImageToSavedPhotosAlbum:[imageToSave CGImage]
metadata:imageMetadata
completionBlock:imageWriteCompletionBlock];
[imageMetadata release];
[library release];
}
The metadata dictionary as you've noticed consists of several dictionaries.
So to answer your question - yes, if you're looking for specific values you can access the inner dictionaries. Also, you'd better use the proper keys from ImageIO constants; for example:
NSLog(#"%#", imageMetadata[(NSString*)kCGImagePropertyExifDictionary][(NSString*)kCGImagePropertyExifISOSpeedRatings]);
Or, you can use a key-path:
NSString *keyPath = [NSString stringWithFormat:#"%#.%#",
(NSString*)kCGImagePropertyExifDictionary, (NSString*)kCGImagePropertyExifISOSpeedRatings];
NSLog(#"%#", [imageMetadata valueForKeyPath:keyPath]);
your all required data is within this dictionary only.
you can use json formatter to see the exact location of your data.
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject: imageMetadata
options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string
error:&error];
if (! jsonData) {
NSLog(#"Got an error: %#", error);
} else {
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(#"jsonString: %#", jsonString);
}
after this get the exact location of your data from json
My application should be able to write custom metadata entries to PNG images for export to the UIPasteboard.
By piecing together various posts on the subject, I've been able to come up with the class given below as source.
Triggering the copyPressed method with a button, I'm able to set custom metadata with JPG images (EXIF):
Image[6101:907] found jpg exif dictionary
Image[6101:907] checking image metadata on clipboard
Image[6101:907] {
ColorModel = RGB;
Depth = 8;
Orientation = 1;
PixelHeight = 224;
PixelWidth = 240;
"{Exif}" = {
ColorSpace = 1;
PixelXDimension = 240;
PixelYDimension = 224;
UserComment = "Here is a comment";
};
"{JFIF}" = {
DensityUnit = 0;
JFIFVersion = (
1,
1
);
XDensity = 1;
YDensity = 1;
};
"{TIFF}" = {
Orientation = 1;
};
}
Although I'm able to read the PNG metadata just fine, I can't seem to write to it:
Image[6116:907] found png property dictionary
Image[6116:907] checking image metadata on clipboard
Image[6116:907] {
ColorModel = RGB;
Depth = 8;
PixelHeight = 224;
PixelWidth = 240;
"{PNG}" = {
InterlaceType = 0;
};
}
However, nothing in the documentation suggests this should fail and the presence of many PNG-specific metadata constants suggests it should succeed.
My application should use PNG to avoid JPG's lossy compression.
Why can I not set custom metadata on an in-memory PNG image in iOS?
Note: I've seen this SO question, but it doesn't address the problem here, which is how to write metadata to PNG images specifically.
IMViewController.m
#import "IMViewController.h"
#import <ImageIO/ImageIO.h>
#interface IMViewController ()
#end
#implementation IMViewController
- (IBAction)copyPressed:(id)sender
{
// [self copyJPG];
[self copyPNG];
}
-(void)copyPNG
{
NSData *pngData = UIImagePNGRepresentation([UIImage imageNamed:#"wow.png"]);
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)pngData, NULL);
NSDictionary *metadata = (__bridge NSDictionary *) CGImageSourceCopyPropertiesAtIndex(source, 0, NULL);
NSMutableDictionary *mutableMetadata = [metadata mutableCopy];
NSMutableDictionary *dict = [[mutableMetadata objectForKey:(NSString *) kCGImagePropertyPNGDictionary] mutableCopy];
if (dict) {
NSLog(#"found png property dictionary");
} else {
NSLog(#"creating png property dictionary");
dict = [NSMutableDictionary dictionary];
}
// set values on the root dictionary
[mutableMetadata setObject:#"Name of Software" forKey:(NSString *)kCGImagePropertyPNGDescription];
[mutableMetadata setObject:dict forKey:(NSString *)kCGImagePropertyPNGDictionary];
// set values on the internal dictionary
[dict setObject:#"works" forKey:(NSString *)kCGImagePropertyPNGDescription];
CFStringRef UTI = CGImageSourceGetType(source);
NSMutableData *data = [NSMutableData data];
CGImageDestinationRef destination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef) data, UTI, 1, NULL);
if (!destination) {
NSLog(#">>> Could not create image destination <<<");
return;
}
CGImageDestinationAddImageFromSource(destination, source, 0, (__bridge CFDictionaryRef) mutableMetadata);
BOOL success = CGImageDestinationFinalize(destination);
if (!success) {
NSLog(#">>> Error Writing Data <<<");
}
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
[pasteboard setData:data forPasteboardType:#"public.png"];
[self showPNGMetadata];
}
-(void)copyJPG
{
NSData *jpgData = UIImageJPEGRepresentation([UIImage imageNamed:#"wow.jpg"], 1);
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef) jpgData, NULL);
NSDictionary *metadata = (__bridge NSDictionary *) CGImageSourceCopyPropertiesAtIndex(source, 0, NULL);
NSMutableDictionary *mutableMetadata = [metadata mutableCopy];
NSMutableDictionary *exif = [[mutableMetadata objectForKey:(NSString *)kCGImagePropertyExifDictionary] mutableCopy];
if (exif) {
NSLog(#"found jpg exif dictionary");
} else {
NSLog(#"creating jpg exif dictionary");
}
// set values on the exif dictionary
[exif setObject:#"Here is a comment" forKey:(NSString *)kCGImagePropertyExifUserComment];
[mutableMetadata setObject:exif forKey:(NSString *)kCGImagePropertyExifDictionary];
CFStringRef UTI = CGImageSourceGetType(source);
NSMutableData *data = [NSMutableData data];
CGImageDestinationRef destination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef) data, UTI, 1, NULL);
if(!destination) {
NSLog(#">>> Could not create image destination <<<");
return;
}
CGImageDestinationAddImageFromSource(destination,source, 0, (__bridge CFDictionaryRef) mutableMetadata);
BOOL success = CGImageDestinationFinalize(destination);
if (!success) {
NSLog(#">>> Could not create data from image destination <<<");
}
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
[pasteboard setData:data forPasteboardType:#"public.jpeg"];
[self showJPGMetadata];
}
-(void)showJPGMetadata
{
NSLog(#"checking image metadata on clipboard");
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
NSData *data = [pasteboard dataForPasteboardType:#"public.jpeg"];
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
NSDictionary *metadata = (__bridge NSDictionary *) CGImageSourceCopyPropertiesAtIndex(source,0,NULL);
NSLog(#"%#", metadata);
}
-(void)showPNGMetadata
{
NSLog(#"checking image metadata on clipboard");
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
NSData *data = [pasteboard dataForPasteboardType:#"public.png"];
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
NSDictionary *metadata = (__bridge NSDictionary *) CGImageSourceCopyPropertiesAtIndex(source,0,NULL);
NSLog(#"%#", metadata);
}
#end
If you will try to save your image with modified metadata
[data writeToFile:[NSTemporaryDirectory() stringByAppendingPathComponent:#"test.png"]
atomically:YES];
And than view it properties in Finder. You will see that kCGImagePropertyPNGDescription field was setted up successfully.
But if you will try read metadata of this new file, kCGImagePropertyPNGDescription will be lost.
ColorModel = RGB;
Depth = 8;
PixelHeight = 1136;
PixelWidth = 640;
"{PNG}" = {
InterlaceType = 0;
};
After some research I found that PNG doesn't contain metadata. But it may contain XMP metadata. However seems like ImageIO didn't work with XMP.
Maybe you can try to use ImageMagic or libexif.
Useful links:
PNG Specification
Reading/Writing image XMP on iPhone / Objective-c
Does PNG support metadata fields like Author, Camera Model, etc?
Does PNG contain EXIF data like JPG?
libexif.sourceforge.net
When a user makes some changes (cropping, red-eye removal, ...) to photos in the built-in Photos.app on iOS, the changes are not applied to the fullResolutionImage returned by the corresponding ALAssetRepresentation.
However, the changes are applied to the thumbnail and the fullScreenImage returned by the ALAssetRepresentation.
Furthermore, information about the applied changes can be found in the ALAssetRepresentation's metadata dictionary via the key #"AdjustmentXMP".
I would like to apply these changes to the fullResolutionImage myself to preserve consistency. I've found out that on iOS6+ CIFilter's filterArrayFromSerializedXMP: inputImageExtent:error: can convert this XMP-metadata to an array of CIFilter's:
ALAssetRepresentation *rep;
NSString *xmpString = rep.metadata[#"AdjustmentXMP"];
NSData *xmpData = [xmpString dataUsingEncoding:NSUTF8StringEncoding];
CIImage *image = [CIImage imageWithCGImage:rep.fullResolutionImage];
NSError *error = nil;
NSArray *filterArray = [CIFilter filterArrayFromSerializedXMP:xmpData
inputImageExtent:image.extent
error:&error];
if (error) {
NSLog(#"Error during CIFilter creation: %#", [error localizedDescription]);
}
CIContext *context = [CIContext contextWithOptions:nil];
for (CIFilter *filter in filterArray) {
[filter setValue:image forKey:kCIInputImageKey];
image = [filter outputImage];
}
However, this works only for some filters (cropping, auto-enhance) but not for others like red-eye removal. In these cases, the CIFilters have no visible effect. Therefore, my questions:
Is anyone aware of a way to create red-eye removal CIFilter? (In a way consistent with the Photos.app. The filter with the key kCIImageAutoAdjustRedEye is not enough. E.g., it does not take parameters for the position of the eyes.)
Is there a possibility to generate and apply these filters under iOS 5?
ALAssetRepresentation* representation = [[self assetAtIndex:index] defaultRepresentation];
// Create a buffer to hold the data for the asset's image
uint8_t *buffer = (Byte*)malloc(representation.size); // Copy the data from the asset into the buffer
NSUInteger length = [representation getBytes:buffer fromOffset: 0.0 length:representation.size error:nil];
if (length==0)
return nil;
// Convert the buffer into a NSData object, and free the buffer after.
NSData *adata = [[NSData alloc] initWithBytesNoCopy:buffer length:representation.size freeWhenDone:YES];
// Set up a dictionary with a UTI hint. The UTI hint identifies the type
// of image we are dealing with (that is, a jpeg, png, or a possible
// RAW file).
// Specify the source hint.
NSDictionary* sourceOptionsDict = [NSDictionary dictionaryWithObjectsAndKeys:
(id)[representation UTI], kCGImageSourceTypeIdentifierHint, nil];
// Create a CGImageSource with the NSData. A image source can
// contain x number of thumbnails and full images.
CGImageSourceRef sourceRef = CGImageSourceCreateWithData((CFDataRef) adata, (CFDictionaryRef) sourceOptionsDict);
[adata release];
CFDictionaryRef imagePropertiesDictionary;
// Get a copy of the image properties from the CGImageSourceRef.
imagePropertiesDictionary = CGImageSourceCopyPropertiesAtIndex(sourceRef,0, NULL);
CFNumberRef imageWidth = (CFNumberRef)CFDictionaryGetValue(imagePropertiesDictionary, kCGImagePropertyPixelWidth);
CFNumberRef imageHeight = (CFNumberRef)CFDictionaryGetValue(imagePropertiesDictionary, kCGImagePropertyPixelHeight);
int w = 0;
int h = 0;
CFNumberGetValue(imageWidth, kCFNumberIntType, &w);
CFNumberGetValue(imageHeight, kCFNumberIntType, &h);
// Clean up memory
CFRelease(imagePropertiesDictionary);
I'm trying to create a custom image gallery within my iOS app. I would like to enable the user to be able to save certain meta data with the image so that it can be pulled up in the app later with the attached information.
First, when the user takes a picture, the app saves the image into a custom album for the app:
UITextField *nameField = [alertView textFieldAtIndex:0];
NSMutableDictionary *metaData = [[NSMutableDictionary alloc] init];
[metaData setObject:currentEvent forKey:kMetaDataEventKey];
[metaData setObject:[AppDelegate getActivePerson].name forKey:kMetaDataPersonKey];
[metaData setObject:nameField.text forKey:kMetaDataNameKey];
NSLog(#"Saving image with metadata: %#", metaData);
NSMutableDictionary *realMetaData = [[NSMutableDictionary alloc] init];
[realMetaData setObject:metaData forKey:kCGImagePropertyTIFFDictionary];
[library saveImage:imageToSave toAlbum:albumName metadata:realMetaData withCompletionBlock:^(NSError *error) {
if ( error != nil )
{
NSLog(#"Error saving picture? %#", error);
}
[self.tableView reloadData];
}];
Upon saving I get the following log message:
Saving image with metadata: {
Event = t;
Person = "George James";
PictureName = tt;
}
Then when I attempt to retrieve the images later, I use this function
-(void) loadAssets
{
self.assets = [NSMutableArray arrayWithCapacity:album.numberOfAssets];
[album enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
if ( result != nil )
{
NSDictionary *metaData = result.defaultRepresentation.metadata;
NSLog(#"Retrieved image metadata: %#", metaData);
}
else
{
[self.tableView reloadData];
}
}];
}
But the log indicates that it did not successfully save the meta data associated with the image:
Retrieved image metadata: {
ColorModel = RGB;
DPIHeight = 72;
DPIWidth = 72;
Depth = 8;
Orientation = 1;
PixelHeight = 720;
PixelWidth = 960;
"{Exif}" = {
ColorSpace = 1;
ComponentsConfiguration = (
1,
2,
3,
0
);
ExifVersion = (
2,
2,
1
);
FlashPixVersion = (
1,
0
);
PixelXDimension = 960;
PixelYDimension = 720;
SceneCaptureType = 0;
};
"{TIFF}" = {
Orientation = 1;
ResolutionUnit = 2;
XResolution = 72;
YResolution = 72;
"_YCbCrPositioning" = 1;
};
}
library is an ALAssetsLibrary instance, and the saveImage: toAlbum: method is from this blog post, only slightly modified so that I can save metadata as such:
-(void)saveImage:(UIImage *)image toAlbum:(NSString *)albumName metadata:(NSDictionary *)metadata withCompletionBlock:(SaveImageCompletion)completionBlock
{
//write the image data to the assets library (camera roll)
[self writeImageToSavedPhotosAlbum:image.CGImage
metadata:metadata
completionBlock:^(NSURL* assetURL, NSError* error) {
//error handling
if (error!=nil) {
completionBlock(error);
return;
}
//add the asset to the custom photo album
[self addAssetURL: assetURL
toAlbum:albumName
withCompletionBlock:completionBlock];
}
];
}
The image is coming from a UIImagePickerController that uses the camera. The picture is successfully being saved to the correct album, just missing the metadata.
Am I doing something wrong in the save/load process? Am I actually not allowed to save custom meta data to an image?
I did some testing, and from what I can tell, the short answer is 'you can't do that.' It looks like the metadata has to conform to specific EXIF Metadata keys. You could look up the available TIFF Metadata keys and see if there are any values you want to set/overwrite. You could try, for example, using kCGImagePropertyTIFFImageDescription to store your data.
NSMutableDictionary *tiffDictionary= [[NSMutableDictionary alloc] init];
NSMutableDictionary *myMetadata = [[NSMutableDictionary alloc] init];
[tiffDictionary setObject:#"My Metadata" forKey:(NSString*)kCGImagePropertyTIFFImageDescription];
[myMetadata setObject:tiffDictionary forKey:(NSString*)kCGImagePropertyTIFFDictionary];
... and save myMetadata with the image.
For other keys, see this:
http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Reference/CGImageProperties_Reference/Reference/reference.html
Otherwise, what I would do is create an NSDictionary that uses an image's unique identifier as a key, and store the metadata object as the value. Save/Load this NSDictionary whenever you save/load an image.