Objective-C/ALAssetslibrary - 从图像 exif 信息中获取 gps 纬度

Posted

技术标签:

【中文标题】Objective-C/ALAssetslibrary - 从图像 exif 信息中获取 gps 纬度【英文标题】:Objective-C/ALAssetslibrary - Take gps latitude from image exif informations 【发布时间】:2013-08-30 11:29:16 【问题描述】:

我从一张图片中找到了一些关于使用 ALAssets 库的 gps 的 exif 信息。我可以正确显示整个退出信息,但是当我尝试仅采用纬度时,我总是收到空值。 这是关于GPS的exif信息:

"GPS" =     
    Altitude = 0;
    AltitudeRef = 1;
    DateStamp = "0111:06:09";
    Latitude = "45.84633333333333";
    LatitudeRef = N;
    Longitude = "12.58";
    LongitudeRef = E;
    TimeStamp = "10:39:04.00";
;

这是我用于获取信息的代码:

__block NSConditionLock * assetsReadLock = [[NSConditionLock alloc] initWithCondition:WDASSETURL_PENDINGREADS];
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^ 
__block ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
__block NSString *description = [[NSString alloc] init];
[library enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) 
    if (group) 
        [group setAssetsFilter:[ALAssetsFilter allPhotos]];
        [group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop)
            if (asset)
                NSDictionary *data = [[asset defaultRepresentation] metadata];
                NSLog(@"DATA: %@", data);

                NSNumber *width = [[[asset defaultRepresentation] metadata] objectForKey:@"PixelWidth"];
                NSString *widthString = [NSString stringWithFormat:@"%@", width];
                [widthList addObject:widthString];

                NSNumber *height = [[[asset defaultRepresentation] metadata] objectForKey:@"PixelHeight"];
                NSString *heightString = [NSString stringWithFormat:@"%@", height];
                [heightList addObject:heightString];

                NSString *latitude = [[[asset defaultRepresentation] metadata] objectForKey:@"Latitude"];
                NSLog(@"latitude %@", latitude);
                NSString *latitudeString = [NSString stringWithFormat:@"%@", latitude];
                if(latitude != NULL)
                    [latitudeList addObject:latitude];
                 else 
                    NSString *noLatitude = [[NSString alloc] init];
                    noLatitude = @"No latitude available";
                    [latitudeList addObject:noLatitude];
                
            
        ];
    

好吧,此时我可以轻松获取有关图像宽度和高度的信息,但是当我尝试获取纬度或经度时,我总是收到空值。我做错了什么?

感谢您的帮助!

【问题讨论】:

【参考方案1】:

有一个问题。从资产库返回的默认表示已从图像中删除了诸如 EXIF 数据之类的内容,这就是您找不到它的原因。

我发现如果我手动提取构成图像的字节,我可以重建图像,然后从中获取 EXIF 数据。

这是一个函数,它将获取字节并将它们作为 NSData 对象返回:

@implementation PhotoLibrary

...

#define MAX_IMAGE_SIZE_LIKELY (700 * 1024)

static uint8_t assetBytes[MAX_IMAGE_SIZE_LIKELY];

+ (NSData*) getDataFromAsset:(ALAsset*)asset 
ALAssetRepresentation* rep = [asset representationForUTI:(NSString*)kUTTypeJPEG];

    if (rep != nil) 
      [rep getBytes:assetBytes fromOffset:0 length:[rep size] error:NULL];
      return [NSData dataWithBytes:assetBytes length:[rep size]];
     else 
      // Return nil, indicating that the image was no good.
      //
      return nil;
    


...

@end

请注意,在我的情况下,我将图像的大小限制为 700K(我有其他与您的问题无关的检查代码)。

现在,调用它的一些代码(在同一个实用程序类中)是我在 uAlertMe 中的一个函数,它扫描资产库以查找符合各种条件的图像:

// Return an array of matching images.
//
+ (void) getImagesForDate:(NSDate *)forDate
         matchDateAndTime:(BOOL)matchDateAndTime
      andMatchUserComment:(NSString*)userComment
      withCompletionBlock:(PhotoLibraryRetrievalCompletetionBlock)completionBlock 
    NSMutableArray* result = [[NSMutableArray alloc] init];

    if ([PhotoLibrary isAssetsLibraryAvailable]) 
        ALAssetsGroupEnumerationResultsBlock assetEnumerator =
        ^(ALAsset *asset, NSUInteger index, BOOL *stop) 
            if(asset != NULL) 
                NSDictionary *dict = [asset valueForProperty:ALAssetPropertyURLs];

                if ([[asset valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypePhoto] == YES) 

                    // We've been asked to match the date and time, so that means
                    // that we need to get the image data itself so that we can
                    // get the EXIF metadata from within it.
                    //
                    NSData* repData = [PhotoLibrary getDataFromAsset:asset];

                    if (repData != nil) 
                        NSString* comment = [EXIFUtility userCommentForPhoto:repData];

                        if ((userComment != nil) && [comment isEqualToString:userComment]) 
                            // OK so the user comment matches.  Does the date match?
                            NSDate* date = [EXIFUtility dateDigitizedForPhoto:repData];

                            if (matchDateAndTime) 
                                // We want an exact match.
                                if ([date isEqualToDate:forDate]) 
                                    [result addObject:[UIImage imageWithData:repData]];
                                
                             else 
                                // We simply want a match on date, regardless of the time of day.
                                if ([date isSameDay:forDate]) 
                                    [result addObject:[UIImage imageWithData:repData]];
                                
                            
                        
                    
                
            
        ;

        ALAssetsLibraryGroupsEnumerationResultsBlock assetGroupEnumerator =
        ^(ALAssetsGroup *group, BOOL *stop) 
            @try 
                if(group != nil) 
                    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
                        [group enumerateAssetsUsingBlock:assetEnumerator];
                        completionBlock(result);
                        [result removeAllObjects];
                        [result release];
                    );
                
            
            @catch (NSException *exception) 
                DDLogError(@"Exception whilst enumerating group: %@", exception);
                *stop = true;
            
        ;

        ALAssetsLibrary *library = [PhotoLibrary defaultAssetsLibrary];

        [library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos
                               usingBlock:assetGroupEnumerator
                             failureBlock: ^(NSError *error) 
                                 DDLogError(@"getImagesForDate:forDate matchDateAndTime:  failed with error: %@", error);
                                 completionBlock(nil);
                                 [result removeAllObjects];
                                 [result release];
                             ];
     else 
        completionBlock(nil);
        [result removeAllObjects];
        [result release];
    

可以在以下位置找到 EXIFUtility 类的 Mac OS X 版本:

EXIFUtility.h EXIFUtility.m

这些与我在 uAlertMe 中的非常相似,应该为您提供足够的信息。

【讨论】:

以上是关于Objective-C/ALAssetslibrary - 从图像 exif 信息中获取 gps 纬度的主要内容,如果未能解决你的问题,请参考以下文章