2

I'm creating a photo app that can open photos, edit them, and save them. I'm using GPUImage to process my photos and the EXIF data is lost in the process. Because of this, I'm reading the EXIF data when opening the file this way:

NSImage *img = [[NSImage alloc] initWithContentsOfURL:url];
NSImageRep *rep = [[img representations] objectAtIndex:0];
NSMutableDictionary *exif = [((NSDictionary*)[(id)rep valueForProperty:NSImageEXIFData]) mutableCopy];

It contains almost all the EXIF data, but it doesn't include Camera Maker and Camera Model for some reason. I need to preserve all the data including those fields when saving. How can I read the whole EXIF data when opening an image file? I've tried the CF methods from this:

Working with images (CGImage), exif data, and file icons

But I can't read any data with that method except file size. Are there any methods to read the EXIF data fully?

Community
  • 1
  • 1
Can Poyrazoğlu
  • 33,241
  • 48
  • 191
  • 389

1 Answers1

3

I've ripped the following code out of a sample project called ImageApp by Apple, Inc. So you need that project to take a close look at the code below. The key values are bound to mTree.

// AppDelegate.h
@interface AppDelegate : NSObject {
IBOutlet NSTreeController *mTree;
NSURL *mUrl;
}

// AppDelegate.m
- (void)setPictureInfo:(NSString *)filepath {
NSURL *url = [[NSURL alloc] init];
url = [self convertpathURL:filepath:NO]; // Converting a file path to a url
[self getImageInfo:url];
}

- (void)getImageInfo:(NSURL *)url {
if (nil == url) {
    return;
}

if ([url isEqual:mUrl])
    return;

mUrl = url;   
CGImageSourceRef source = NULL;

if (url) source = CGImageSourceCreateWithURL((__bridge CFURLRef)url, NULL);

// CGImageSourceRef source = CGImageSourceCreateWithURL((__bridge CFURLRef)url, NULL);
if (source) {
    // get image properties (height, width, depth, metadata etc.) for display
    NSDictionary *props = (__bridge_transfer NSDictionary *) CGImageSourceCopyPropertiesAtIndex(source, 0, NULL);
    [mTree setContent:[self propTree:props]];
}
else { // couldn't make image source for image, so display nothing
    [mTree setContent:nil];
}
}

static NSString *ImageIOLocalizedString (NSString *key) {
static NSBundle *b = nil;

if (b == nil)
    b = [NSBundle bundleWithIdentifier:@"com.apple.ImageIO.framework"];

// Returns a localized version of the string designated by 'key' in table 'CGImageSource'. 
return [b localizedStringForKey:key value:key table: @"CGImageSource"];
}

- (NSArray *)propTree:(NSDictionary *)branch {
NSMutableArray *tree = [[NSMutableArray alloc] init];   
for (NSInteger i3 = 0; i3 < [branch count]; i3++) {
    NSArray *keys = [[branch allKeys] sortedArrayUsingSelector:@selector(compare:)];
    NSString *key = [keys objectAtIndex:i3];
    NSString *locKey = ImageIOLocalizedString(key);
    id obj = [branch objectForKey:key];
    NSDictionary* leaf = nil;

    if ([obj isKindOfClass:[NSDictionary class]])
        leaf = [NSDictionary dictionaryWithObjectsAndKeys:
                locKey,@"key",  @"",@"val",  [self propTree:obj],@"children",  nil];
    else
        leaf = [NSDictionary dictionaryWithObjectsAndKeys:
                locKey,@"key",  obj,@"val",  nil];

    [tree addObject:leaf];
}
return tree;
}
El Tomato
  • 6,479
  • 6
  • 46
  • 75
  • that worked. for some reason, this code didn't work before. perhaps I was doing something wrong. I can get TIFF/EXIF/IPTC metadata seperately in a full dictionary, which is even better than what I expected. – Can Poyrazoğlu Oct 30 '13 at 17:43
  • by the way, now (because I've changed the reading method) I'm struggling with writing the data to an image file. if you have any idea about that, you can help here: http://stackoverflow.com/questions/19692455/writing-image-metadata-exif-tiff-iptc-to-image-file-in-os-x – Can Poyrazoğlu Oct 30 '13 at 19:46
  • I have a problem with ImageIOLocalizedString and iOS14 - bundle ImageIO can't be found – Viktor Goltvyanitsa Oct 06 '20 at 12:44
  • @Viktor Goltvyanitsa See the tags of the original topic. This topic is about an macOS application. – El Tomato Oct 06 '20 at 13:23
  • @El Tomato And what? The code itself worked for my iOS app during of some years until now. If you wish, then okay, it is not working for macOS under maccatalyst. – Viktor Goltvyanitsa Oct 07 '20 at 15:39