Из результатов UIImagePickerControlleHow, как я могу получить JPEG с метаданными, включенными в него? - PullRequest
5 голосов
/ 03 марта 2011

В iOS 4.2, когда я использую UIImagePickerController, чтобы позволить пользователю выбрать изображение из библиотеки фотографий, это ключи словаря, которые мне возвращаются:

2011-03-02 13:15:59.518 xxx[15098:307] didFinishPickingMediaWithInfo: 
  info dictionary: {
    UIImagePickerControllerMediaType = "public.image";
    UIImagePickerControllerOriginalImage = "<UIImage: 0x3405d0>";
    UIImagePickerControllerReferenceURL = 
      "assets-library://asset/asset.JPG?id=1000000050&ext=JPG";
}

Используя один или несколько из этих ключей, какМогу ли я получить представление в формате JPEG, которое будет включать метаданные изображения (например, информацию об экспозиции и данные о местоположении GPS), чтобы я мог выгрузить их куда-нибудь и включить метаданные (не вырезанные)?

Я вижу из очень красивого ответа Уоррена Бертона в Отображение изображения с URL-адреса, полученного из ALAsset в iPhone? как использовать метод UIImagePickerControllerReferenceURL и ALAssetsLibrary assetForURL, чтобы получить доступ к ALAsset и ALAssetRepresentation.Но что мне делать, чтобы добраться до JPEG, который включает в себя все метаданные?

Или есть ли механизм через UIImage?

Суть в том, что я хочу получитьJPEG с метаданными, включенными в него ...

1 Ответ

7 голосов
/ 04 марта 2011

С тех пор, как я задал вопрос, я провел еще несколько экспериментов и думаю, что теперь я знаю ответ.Все результаты были получены на iOS 4.2, и это все, что меня волнует ...

Прежде всего, мы использовали UIImageJPEGRepresentation ala:

NSData *imageData = UIImageJPEGRepresentation(self.selectedImage, 0.9);

, который, кажется, не дает вам (большая часть) метаданных (EXIF, GPS и т. д.), содержащихся в изображении.Достаточно справедливо, и я думаю, что это хорошо известно.

Мое тестирование показывает, что JPEG в «представлении по умолчанию» для актива изображения будет содержать все метаданные, включая информацию EXIF ​​и GPS (при условии, что она есть в первомместо).Вы можете получить это изображение, перейдя от URL ресурса к Активу к представлению актива по умолчанию (ALAssetRepresentation) и затем используя метод / сообщение getBytes, чтобы получить байты для изображения JPEG.Этот поток байтов содержит вышеупомянутые метаданные.

Вот пример кода, который я использую для этого.Он принимает URL-адрес актива, предположительно для изображения, и возвращает NSData с JPEG.Будьте бдительны в отношении вашего использования, обработки ошибок в коде и т. Д.

/*
 * Example invocation assuming that info is the dictionary returned by 
 * didFinishPickingMediaWithInfo (see original SO question where
 * UIImagePickerControllerReferenceURL = "assets-library://asset/asset.JPG?id=1000000050&ext=JPG").
 */
[self getJPEGFromAssetForURL:[info objectForKey:UIImagePickerControllerReferenceURL]];
// ...

/* 
 * Take Asset URL and set imageJPEG property to NSData containing the
 * associated JPEG, including the metadata we're after.
 */
-(void)getJPEGFromAssetForURL:(NSURL *)url {
    ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc] init];
    [assetslibrary assetForURL:url
        resultBlock: ^(ALAsset *myasset) {
            ALAssetRepresentation *rep = [myasset defaultRepresentation];
#if DEBUG
            NSLog(@"getJPEGFromAssetForURL: default asset representation for %@: uti: %@ size: %lld url: %@ orientation: %d scale: %f metadata: %@", 
            url, [rep UTI], [rep size], [rep url], [rep orientation], 
            [rep scale], [rep metadata]);
#endif

            Byte *buf = malloc([rep size]);  // will be freed automatically when associated NSData is deallocated
            NSError *err = nil;
            NSUInteger bytes = [rep getBytes:buf fromOffset:0LL 
                                length:[rep size] error:&err];
            if (err || bytes == 0) {
                // Are err and bytes == 0 redundant? Doc says 0 return means 
                // error occurred which presumably means NSError is returned.

                NSLog(@"error from getBytes: %@", err);
                self.imageJPEG = nil;
                return;
            } 
            self.imageJPEG = [NSData dataWithBytesNoCopy:buf length:[rep size] 
                                     freeWhenDone:YES];  // YES means free malloc'ed buf that backs this when deallocated
        }
        failureBlock: ^(NSError *err) {
            NSLog(@"can't get asset %@: %@", url, err);
        }];
    [assetslibrary release];
}
...