I'm having a problem while getting the latitude and longitude data from an image(which is having geo location details). I have imported the EXIF framework and I'm using the following code to achieve this:
NSData *jpegData = [UIImageJPEGRepresentation(image, 0.5) base64String];
EXFJpeg* jpegScanner = [[EXFJpeg alloc] init];
[jpegScanner scanImageData: jpegData];
EXFMetaData* exifData = jpegScanner.exifMetaData;
id latitudeValue = [exifData tagValue:[NSNumber numberWithInt:EXIF_GPSLatitude]];
id longitudeValue = [exifData tagValue:[NSNumber numberWithInt:EXIF_GPSLongitude]];
NSLog(#"Longitude: %# Longitude: %#", latitudeValue, longitudeValue);
But its returning the NULL value for both latitude and longitude, can anyone please tell me what I'm doing wrong in the above code? Please help me out. Thanks in Advance!!
You can do it with the alasset framework.
ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc]init];
[assetsLibrary assetForURL:photoUrl resultBlock:resultBlock failureBlock:nil];
ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset *photoAsset) {
CLLocation *location = [photoAsset valueForProperty:ALAssetPropertyLocation];
NSMutableDictionary *exifDataDict = [[NSMutableDictionary alloc] init];
if (location != nil) {
[exifDataDict setObject:[NSNumber numberWithDouble:location.coordinate.latitude] forKey:#"latitude"];
[exifDataDict setObject:[NSNumber numberWithDouble:location.coordinate.longitude] forKey:#"longitude"];
}
}
I had a similar issue once. While dealing with it I got the impression that UIImage sort of strips all or some of the EXIF data. EXIFJpeg worked fine for me when the image data was read from file, boundle or webservice etc. direclty but I did not manage to extract any reasonalbe EXIFs when I stored the image in memory as UIImage object and then used UIImageJPEGRepresentaiion to get the image data and the EXIF from that data.
I will not sign this in blood but that was my impression and using the "raw" data from file did actually work for me. So I received the file from some server, then extracted the EXIF including geo tags (if any) and after that created the UIImage.
Related
As the question says I am trying to add pins to my map based on the coordinates returned by my php file. Said file returns the following results
[{"dogid":"1","latitude":"15.435786","longitude":"-21.318447"},{"dogid":"1","latitude":"14.00000","longitude":"-18.536711"}]
What I am doing (well I believe i am) is taking the values from the link and saving them to a string. Secondly, save that string value to an array. Then, I go thru this array and save out the latitude and longitude and assign it to CLLocationCordinate 2dcoord. After whch I expect both pins to be dropped on whatever location they received.
However, what occurs is: Upon running the program, when it arrives on this lin
for (NSDictionary *row in locations) {
the loop is not run to assign the values, and it jumps to the end. Oddly, a single pin is dropped on the map (thou location doesnt appear to be the values that it waas passed).
Would appreciate a little incite into the matter.
Thanks
- (void)viewDidAppear:(BOOL)animated
{
NSMutableArray *annotations = [[NSMutableArray alloc] init];
NSURL *myURL =[NSURL URLWithString:#"link.php"];
NSError *error=nil;
NSString *str=[NSString stringWithContentsOfURL:myURL encoding:NSUTF8StringEncoding error:&error];
CLLocationCoordinate2D coord;
NSArray *locations=[NSArray arrayWithContentsOfFile:str];
for (NSDictionary *row in locations) {
NSNumber *latitude = [row objectForKey:#"latitude"];
NSNumber *longitude = [row objectForKey:#"longitude"];
// NSString *title = [row objectForKey:#"title"];
//Create coordinates from the latitude and longitude values
coord.latitude = latitude.doubleValue;
coord.longitude = longitude.doubleValue;
}
MKPointAnnotation *pin = [[MKPointAnnotation alloc] init];
pin.coordinate = coord;
[self.mapView addAnnotation:pin];
}
It looks like you are trying to save api response to and Array.
Api always returns json string which is NSString.
You need to convert decode json string.
In your case
NSString *str=[NSString stringWithContentsOfURL:myURL encoding:NSUTF8StringEncoding error:&error];
you need to decode str with [NSJSONSerialization JSONObjectWithData:<#(NSData )#> options:<#(NSJSONReadingOptions)#> error:<#(NSError *)#>] which give you proper array of dictionary.
Hope it will help you
I want to find the DPI for an image that has been captured from iPhone/iPad Camera
this is how i am trying to get the DPI
CFDictionaryRef exifDict = CMGetAttachment(imageDataSampleBuffer,
kCGImagePropertyExifDictionary ,
NULL);
originalExifDict = (__bridge NSMutableDictionary *)(exifDict);
[originalExifDict objectForKey:(NSString *)kCGImagePropertyDPIHeight]
[originalExifDict objectForKey:(NSString *)kCGImagePropertyDPIWidth]
However both the entries in the dictionary come to be 0.
What is the correct way to find the DPI ?
Thanks in advance for the help
CGSize size;
NSNumber *width = (NSNumber *)CFDictionaryGetValue(exifDict, kCGImagePropertyDPIWidth);
NSNumber *height = (NSNumber *)CFDictionaryGetValue(exifDict, kCGImagePropertyDPIHeight);
size.width = [width floatValue];
size.height = [height floatValue];
//Tell me its work or not.
The information isn't in the metadata that comes with your imageDataSampleBuffer. It is written (72 dpi) at the time the image is saved, unless you have, first, manually set it yourself when editing the metadata, before the save.
For most purposes, it is meaningless, However, some software uses it to calculate the "correct size" of an image when placing it in a document. A 3000 pixel square image at 300 dpi will thus appear 10 inches (c.25.4 cm) square; at 72 dpi it will be nearly 42 inches (c.105.8 cm) square. Also, some online image uploaders (especially those used by stock photo libraries and the like) insist on images having high-ish dpi.
If you are using imagePickerController use this below code
NSURL *assetURL = [info objectForKey:UIImagePickerControllerReferenceURL];
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library assetForURL:assetURL
resultBlock:^(ALAsset *asset) {
NSMutableDictionary *imageMetadata = nil;
NSDictionary *metadata = asset.defaultRepresentation.metadata;
imageMetadata = [[NSMutableDictionary alloc] initWithDictionary:metadata];
NSLog (#"imageMetaData from AssetLibrary %#",imageMetadata);
NSString *dpi = [imageMetadata objectForKey:#"DPIHeight"];
NSLog (#"Dpi: %#",dpi);
}
failureBlock:^(NSError *error) {
NSLog (#"error %#",error);
}];
I am exporting a Quicktime video using AVExporterSession and setting the metadata on it as follows:
AVMutableMetadataItem *newMetaDataCommentItem = [[AVMutableMetadataItem alloc] init];
[newMetaDataCommentItem setKeySpace:AVMetadataKeySpaceQuickTimeMetadata];
[newMetaDataCommentItem setKey:AVMetadataQuickTimeMetadataKeyComment];
[newMetaDataCommentItem setValue:#"Test metadata value"];
NSMutableArray *metaData = [NSMutableArray array];
[metaData addObject:newMetaDataCommentItem];
exporter = [[AVAssetExportSession alloc] initWithAsset:mutableComposition
presetName:AVAssetExportPresetHighestQuality];
exporter.outputURL=[[SNMovieManager instance] urlForFinalMovie];
exporter.metadata = metaData;
exporter.outputFileType = AVFileTypeQuickTimeMovie;
exporter.shouldOptimizeForNetworkUse = YES;
exporter.videoComposition = video;
I then import the file video to my Mac and run mdls on it and see the value has been set correctly: kMDItemComment = "Test metadata value"
The bit I can't do is read that value back. I am using the following to read the file. The asset is correct but the metadata property is always an empty dictionary.
[group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
if([[result valueForProperty:#"ALAssetPropertyType"] isEqualToString:#"ALAssetTypeVideo"])
{
ALAssetRepresentation *rep = result.defaultRepresentation;
NSDictionary *metadata = rep.metadata;
[images addObject:(id)rep.fullScreenImage];
}
Does anyone know if I am taking the correct approach here and if not let me know what the correct approach to read this comment back out is?
Thanks
Simon
I would be highly appreciated if you can provide more code base related to the PhotoLibrary save process.
Otherwise only one answer, Metadata will return nil if the representation is one that the system cannot interpret.
The returned dictionary holds the properties of the video at a specified location in an file source.
I'think your problem is on getting metadata script
You should get an AVURLAsset first and get metadata from it ALAssetRepresentation metadata is different
[group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
if([[result valueForProperty:#"ALAssetPropertyType"] isEqualToString:#"ALAssetTypeVideo"])
{
AVURLAsset *videoAset = [AVURLAsset assetWithURL:[[asset defaultRepresentation] url]];
if ([[videoAset metadataForFormat:AVMetadataFormatQuickTimeMetadata] count]) {
AVMutableMetadataItem *meta = [[videoAset metadataForFormat:AVMetadataFormatQuickTimeUserData] objectAtIndex:0];
NSLog(#"%#",meta);
NSLog(#"%lu",(unsigned long)[[videoAset metadataForFormat:AVMetadataFormatQuickTimeMetadata] count]);
}
}
I am updating my app to allow photo uploads to included GPS metadata when using UIImagePickerControllerSourceTypeSavedPhotosAlbum. The GPS data's accuracy is very important. I am running into an issue where the location data derived using ALAsset is different than the photo's actual exif data I can see when opening the same photo in Photoshop.
I have used two methods to read the GPS data in xcode:
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset) {
CLLocation *location = [myasset valueForProperty:ALAssetPropertyLocation];
latitudeString = [NSString stringWithFormat:#"%g",point.latitude];
longitudeString = [NSString stringWithFormat:#"%g",point.longitude];
}
AND
ALAssetRepresentation *representation = [myasset defaultRepresentation];
NSDictionary *metadata = [representation metadata];
NSDictionary *gpsDict = [metadata objectForKey:#"{GPS}"];
NSNumber *latitudeNumber = [gpsDict objectForKey:#"Latitude"];
NSNumber *longitudeNumber = [gpsDict objectForKey:#"Longitude"];
if ([[gpsDict valueForKey:#"LatitudeRef"] isEqualToString:#"S"])
{
//latitudeNumber = -latitudeNumber;
}
if ([[gpsDict valueForKey:#"LongitudeRef"] isEqualToString:#"W"])
{
//longitudeNumber = -longitudeNumber);
}
On a representative photo I am using as an example both sets of code above give me a latitude of 47.576333 which converts to 47,34,35N
If I look in Photoshop exif data - the latitude is 47,34,59N
These numbers are close - but they aren't the same. This happens without about 30% of my photos. Any idea why?
Edit - Photo shop does not give seconds - it give 34.59 minutes which is indeed accurate.
Your conversion is wrong, photoshop is more correct.
47.576333 (DEG) converts to 47* 34.5799' (DM). which can be rounded to 47* 34.58
which is the format photoshop obviously displays.
converted to DMS it gives your value: 47* 34' 35" N.
(Please replace all "*" with degrees symbol.)
So you exchanged DMS (Degress Minutes Seconds) with DM (Degrees Minutes) representation.
I'm trying to save an image with some custom metadata to a Photo Album. The custom metadata I would like to save should be in the form of a NSDictionary. Until now I have only succeeded in inserting an NSArray into the image metadata by using something like below:
NSMutableDictionary *metadata = [[NSMutableDictionary alloc] init];
[metadata setObject:#[#"ele1", #"ele2"] forKey:(NSString*)kCGImagePropertyIPTCKeywords];
NSMutableDictionary *meta = [[NSMutableDictionary alloc] init];
[meta setObject:metadata forKey:(NSString*)kCGImagePropertyIPTCDictionary];
// pass the meta dictionary into writeImageDataToSavedPhotosAlbum
But what I would like is to pass a dictionary into setObject.
Has anyone succeeded in inserting a custom metadata into an image where the metadata is an NSDIctionary?
Additional information
I'm using the code I found here Save CUSTOM metadata in an image taken from AVFoundation in iOS, to add a dictionary to the image metadata but still no luck. The original file is in the temporary directory and the final file is created via writeImageDataToSavedPhotosAlbum. Like in the link, the resulting image doesn't contain the dictionary. Any idea?
CGImageSourceRef source = CGImageSourceCreateWithData((CFMutableDataRef)data, NULL);
NSDictionary *metadata = [(NSDictionary *) CGImageSourceCopyPropertiesAtIndex(source,0,NULL)autorelease];
NSMutableDictionary *metadataAsMutable = [metadata mutableCopy];
NSMutableDictionary *RAWDictionary = [[metadataAsMutable objectForKey:(NSString *)kCGImagePropertyRawDictionary]mutableCopy];
if(!RAWDictionary) {
RAWDictionary = [NSMutableDictionary dictionary];
}
[RAWDictionary setValue:#"value1" forKey:#"key1"];
[RAWDictionary setValue:#"value2" forKey:#"key2"];
[metadataAsMutable setObject:RAWDictionary forKey:(NSString *)kCGImagePropertyRawDictionary];
NSMutableData *newData = [NSMutableData data];
CFStringRef UTI = CGImageSourceGetType(source);
CGImageDestinationRef destination = CGImageDestinationCreateWithData((CFMutableDataRef)newData, UTI, 1, NULL);
if(!destination) {
NSLog(#"***Could not create image destination ***");
}
CGImageDestinationAddImageFromSource(destination,source,0, (CFDictionaryRef)metadataAsMutable);
BOOL success = NO;
success = CGImageDestinationFinalize(destination);
if(!success) {
NSLog(#"***Could not create data from image destination ***");
}
Try this :
//covert image to nsdata format
NSData *imageData = [[NSData alloc]initWithContentsOfFile:#"your image path"];
NSMutableDictionary *metadata = [[NSMutableDictionary alloc] init];
[metadata setObject:imageData forKey:#"imageData"];