1

我从一张图片中发现了一些关于使用 ALAssetslibrary 的 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];
                }
            }
        }];
    }

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

感谢您的帮助!

4

1 回答 1

0

有一个问题。从资产库返回的默认表示已从图像中删除了诸如 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 中的非常相似,应该为您提供足够的信息。

于 2013-08-31T14:51:13.260 回答