Permalink
Browse files

Added some init methods and the ability to read the geolocation form …

…the dictionary in a nice CLLocation package. Also added a way to set the digital zoom
  • Loading branch information...
1 parent 2574e38 commit a9ad3a230aef8dea5640ee7866fb528d74c36959 @gpambrozio committed May 24, 2011
Showing with 116 additions and 8 deletions.
  1. +27 −1 GusUtils/NSMutableDictionary+ImageMetadata.h
  2. +89 −7 GusUtils/NSMutableDictionary+ImageMetadata.m
@@ -13,13 +13,39 @@
- (id)initWithImageSampleBuffer:(CMSampleBufferRef) imageDataSampleBuffer;
-- (void)setLocation:(CLLocation *)currentLocation;
+/*
+ Be careful with this method: because it uses blocks, there's no guarantee that your
+ imageMetadata dictionary will be populated when this code runs. In some testing I've
+ done it sometimes runs the code inside the block even before the [library autorelease]
+ is executed. But the first time you run this, the code inside the block will only run
+ on another cycle of the apps main loop. So, if you need to use this info right away,
+ it's better to schedule a method on the run queue for later with:
+
+ [self performSelectorOnMainThread: withObject: waitUntilDone:NO];
+ */
+- (id)initWithInfoFromImagePicker:(NSDictionary *)info;
+
+/*
+ Be careful with this method: because it uses blocks, there's no guarantee that your
+ imageMetadata dictionary will be populated when this code runs. In some testing I've
+ done it sometimes runs the code inside the block even before the [library autorelease]
+ is executed. But the first time you run this, the code inside the block will only run
+ on another cycle of the apps main loop. So, if you need to use this info right away,
+ it's better to schedule a method on the run queue for later with:
+
+ [self performSelectorOnMainThread: withObject: waitUntilDone:NO];
+ */
+- (id)initFromAssetURL:(NSURL*)assetURL;
+
- (void)setUserComment:(NSString*)comment;
- (void)setDateOriginal:(NSDate *)date;
- (void)setDateDigitized:(NSDate *)date;
- (void)setMake:(NSString*)make model:(NSString*)model software:(NSString*)software;
- (void)setDescription:(NSString*)description;
- (void)setKeywords:(NSString*)keywords;
- (void)setImageOrientarion:(UIImageOrientation)orientation;
+- (void)setDigitalZoom:(CGFloat)zoom;
+
+@property (nonatomic, assign) CLLocation *location;
@end
@@ -6,6 +6,7 @@
#import "NSMutableDictionary+ImageMetadata.h"
#import <ImageIO/ImageIO.h>
+#import <AssetsLibrary/AssetsLibrary.h>
/* Add this before each category implementation, so we don't have to use -all_load or -force_load
* to load object files from static libraries that only contain categories and no classes.
@@ -20,38 +21,93 @@ @implementation FIX_CATEGORY_BUG_ImageMetadataCategory @end
@implementation NSMutableDictionary (ImageMetadataCategory)
- (id)initWithImageSampleBuffer:(CMSampleBufferRef) imageDataSampleBuffer {
+
+ // Dictionary of metadata is here
CFDictionaryRef metadataDict = CMCopyDictionaryOfAttachments(NULL, imageDataSampleBuffer, kCMAttachmentMode_ShouldPropagate);
+
+ // Just init with it....
self = [self initWithDictionary:(NSDictionary*)metadataDict];
+
+ // Release it
CFRelease(metadataDict);
return self;
}
+- (id)initWithInfoFromImagePicker:(NSDictionary *)info {
+
+ if ((self = [self init])) {
+
+ // Key UIImagePickerControllerReferenceURL only exists in iOS 4.1
+ if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 4.1f) {
+
+ NSURL* assetURL = nil;
+ if ((assetURL = [info objectForKey:UIImagePickerControllerReferenceURL])) {
+
+ ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
+ [library assetForURL:assetURL
+ resultBlock:^(ALAsset *asset) {
+ NSDictionary *metadata = asset.defaultRepresentation.metadata;
+ [self addEntriesFromDictionary:metadata];
+ }
+ failureBlock:^(NSError *error) {
+ }];
+ [library autorelease];
+ }
+ else {
+ NSDictionary *metadata = [info objectForKey:UIImagePickerControllerMediaMetadata];
+ if (metadata)
+ [self addEntriesFromDictionary:metadata];
+ }
+ }
+ }
+
+ return self;
+}
+
+- (id)initFromAssetURL:(NSURL*)assetURL {
+
+ if ((self = [self init])) {
+ NSURL* assetURL = nil;
+ ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
+ [library assetForURL:assetURL
+ resultBlock:^(ALAsset *asset) {
+ NSDictionary *metadata = asset.defaultRepresentation.metadata;
+ [self addEntriesFromDictionary:metadata];
+ }
+ failureBlock:^(NSError *error) {
+ }];
+ [library autorelease];
+ }
+
+ return self;
+}
+
// Mostly from here: http://stackoverflow.com/questions/3884060/need-help-in-saving-geotag-info-with-photo-on-ios4-1
-- (void)setLocation:(CLLocation *)currentLocation {
+- (void)setLocation:(CLLocation *)location {
- if (currentLocation) {
+ if (location) {
- CLLocationDegrees exifLatitude = currentLocation.coordinate.latitude;
- CLLocationDegrees exifLongitude = currentLocation.coordinate.longitude;
+ CLLocationDegrees exifLatitude = location.coordinate.latitude;
+ CLLocationDegrees exifLongitude = location.coordinate.longitude;
NSString *latRef;
NSString *lngRef;
if (exifLatitude < 0.0) {
- exifLatitude = exifLatitude * -1;
+ exifLatitude = exifLatitude * -1.0f;
latRef = @"S";
} else {
latRef = @"N";
}
if (exifLongitude < 0.0) {
- exifLongitude = exifLongitude * -1;
+ exifLongitude = exifLongitude * -1.0f;
lngRef = @"W";
} else {
lngRef = @"E";
}
NSDictionary* locDict = [[NSDictionary alloc] initWithObjectsAndKeys:
- currentLocation.timestamp, (NSString*)kCGImagePropertyGPSTimeStamp,
+ location.timestamp, (NSString*)kCGImagePropertyGPSTimeStamp,
latRef, (NSString*)kCGImagePropertyGPSLatitudeRef,
[NSNumber numberWithFloat:exifLatitude], (NSString*)kCGImagePropertyGPSLatitude,
lngRef, (NSString*)kCGImagePropertyGPSLongitudeRef,
@@ -63,6 +119,27 @@ - (void)setLocation:(CLLocation *)currentLocation {
}
}
+- (CLLocation*)location {
+ NSDictionary *locDict = [self objectForKey:(NSString*)kCGImagePropertyGPSDictionary];
+ if (locDict) {
+
+ CLLocationDegrees lat = [[locDict objectForKey:(NSString*)kCGImagePropertyGPSLatitude] floatValue];
+ CLLocationDegrees lng = [[locDict objectForKey:(NSString*)kCGImagePropertyGPSLongitude] floatValue];
+ NSString *latRef = [locDict objectForKey:(NSString*)kCGImagePropertyGPSLatitudeRef];
+ NSString *lngRef = [locDict objectForKey:(NSString*)kCGImagePropertyGPSLongitudeRef];
+
+ if ([@"S" isEqualToString:latRef])
+ lat *= -1.0f;
+ if ([@"W" isEqualToString:lngRef])
+ lng *= -1.0f;
+
+ CLLocation *location = [[[CLLocation alloc] initWithLatitude:lat longitude:lng] autorelease];
+ return location;
+ }
+
+ return nil;
+}
+
- (NSMutableDictionary *)dictionaryForKey:(CFStringRef)key {
NSDictionary *dict = [self objectForKey:(NSString*)key];
NSMutableDictionary *mutableDict;
@@ -117,6 +194,11 @@ - (void)setKeywords:(NSString*)keywords {
[IPTC_DICT setObject:keywords forKey:(NSString*)kCGImagePropertyIPTCKeywords];
}
+- (void)setDigitalZoom:(CGFloat)zoom {
+ [EXIF_DICT setObject:[NSNumber numberWithFloat:zoom] forKey:(NSString*)kCGImagePropertyExifDigitalZoomRatio];
+}
+
+
/* The intended display orientation of the image. If present, the value
* of this key is a CFNumberRef with the same value as defined by the
* TIFF and Exif specifications. That is:

0 comments on commit a9ad3a2

Please sign in to comment.