Всем известно, что приложение «Фото», установленное на всех iOS-девайсах, позволяет просматривать не только фотографии пользователей, но и отметки на карте, где были сделаны эти фотографии. Если вы делаете фотографию с помощью стандартной камеры, то информация о вашем текущем местоположении автоматически заносится в EXIF-тег, находящийся внутри изображения и вы увидите новую отметку на карте. Это изображение можно отправить друзьям или разместить в интернете. А с помощью записанных координат все смогут увидеть, где был сделан столь замечательный кадр. Все красиво и удобно.
Этот небольшой топик-подсказка поможет вам, когда необходимо сделать собственное приложение с камерой, которое будет повторять данный функционал и (скорее всего) выполнять какие-то действия с полученным изображением (в моем случае свежую фотографии необходимо было загружать на веб-сайт, где пользователи могут просматривать фотографии и места на карте).
Выделим три маленьких этапа, реализовав которые, можно получить желаемый результат:
Надеюсь, что вам не составит труда справиться с первыми двумя пунктами самостоятельно и мы остановимся более подробно на самом интересном — как записать координаты.
Получаем изображение (у меня из UIImagePickerController)
Далее у нас уже должен быть объект location (класса CLLocation)
Сделаем конвертацию наших координат в строки, которые будет записаны в EXIF-тег
Создаем словарик с нашими данными и названием ключей:
kCGImagePropertyGPSTimeStamp
kCGImagePropertyGPSLatitude
kCGImagePropertyGPSLongitude
kCGImagePropertyGPSLatitudeRef
kCGImagePropertyGPSLongitudeRef
Создаем еще один словарик и включаем в него созданный строчкой выше locDict. Здесь используется ключ kCGImagePropertyGPSDictionary
Создаем объект класса NSData и наполняем его байтами из нашего изображения
Следующие волшебные строчки кода создают объект класса ALAssetsLibrary, который предоставляет доступ к вашим фото- и видеоальбомам (и не только, более подробно можно ознакомиться в документации). Далее сохраняем фотографию в фотоальбом на девайсе с использованием созданного нами словаря metadata. Метод writeImageDataToSavedPhotosAlbum поможет нам в этом и заодно запишет необходимые нам EXIF-теги.
На этом можно было бы остановиться, если фотография нужна вам только в фотоальбоме. Но мы пойдем дальше. Создаем объект dest_data, который нам понадобится для хранения фотографии
Создаем референс для фотографии
Указываем тип
Указываем куда нужно записать полученные данные (в dest_data)
Записываем данные с использованием словаря metadata (да, все тот же).
Делаем проверку
Не забываем почистить память
Теперь у нас есть объект dest_data, который хранит изображение с нужными тегами. Его можно использовать на ваше усмотрение.
Добавьте следующие строчки в ваш заголовочный файл
И не забудьте подключить нужные фреймворки.
Спасибо stackoverflow за ответы на мои бесконечные вопросы и всем кто дочитал до конца.
Этот небольшой топик-подсказка поможет вам, когда необходимо сделать собственное приложение с камерой, которое будет повторять данный функционал и (скорее всего) выполнять какие-то действия с полученным изображением (в моем случае свежую фотографии необходимо было загружать на веб-сайт, где пользователи могут просматривать фотографии и места на карте).
Выделим три маленьких этапа, реализовав которые, можно получить желаемый результат:
- Получение изображения с камеры девайса
- Определение координат пользователя
- Запись коодринат в изображение
Надеюсь, что вам не составит труда справиться с первыми двумя пунктами самостоятельно и мы остановимся более подробно на самом интересном — как записать координаты.
Получаем изображение (у меня из UIImagePickerController)
UIImage *pickedImage = [[info objectForKey:UIImagePickerControllerOriginalImage] retain];
Далее у нас уже должен быть объект location (класса CLLocation)
CLLocationDegrees exifLatitude = location.coordinate.latitude; CLLocationDegrees exifLongitude = location.coordinate.longitude;
Сделаем конвертацию наших координат в строки, которые будет записаны в EXIF-тег
NSString *latRef; NSString *lngRef; if (exifLatitude < 0.0) { exifLatitude = exifLatitude * -1.0f; latRef = @"S"; } else { latRef = @"N"; } if (exifLongitude < 0.0) { exifLongitude = exifLongitude * -1.0f; lngRef = @"W"; } else { lngRef = @"E"; }
Создаем словарик с нашими данными и названием ключей:
kCGImagePropertyGPSTimeStamp
kCGImagePropertyGPSLatitude
kCGImagePropertyGPSLongitude
kCGImagePropertyGPSLatitudeRef
kCGImagePropertyGPSLongitudeRef
NSDictionary* locDict = [[NSDictionary alloc] initWithObjectsAndKeys: location.timestamp, (NSString*)kCGImagePropertyGPSTimeStamp, latRef, (NSString*)kCGImagePropertyGPSLatitudeRef, [NSNumber numberWithFloat:exifLatitude], (NSString*)kCGImagePropertyGPSLatitude, lngRef, (NSString*)kCGImagePropertyGPSLongitudeRef, [NSNumber numberWithFloat:exifLongitude], (NSString*)kCGImagePropertyGPSLongitude, nil];
Создаем еще один словарик и включаем в него созданный строчкой выше locDict. Здесь используется ключ kCGImagePropertyGPSDictionary
NSMutableDictionary *metadata = [[NSMutableDictionary alloc] init]; [metadata setObject:locDict forKey:(NSString*)kCGImagePropertyGPSDictionary]; [locDict release];
Создаем объект класса NSData и наполняем его байтами из нашего изображения
NSData *image = UIImageJPEGRepresentation(pickedImage, 90);
Следующие волшебные строчки кода создают объект класса ALAssetsLibrary, который предоставляет доступ к вашим фото- и видеоальбомам (и не только, более подробно можно ознакомиться в документации). Далее сохраняем фотографию в фотоальбом на девайсе с использованием созданного нами словаря metadata. Метод writeImageDataToSavedPhotosAlbum поможет нам в этом и заодно запишет необходимые нам EXIF-теги.
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; [library writeImageDataToSavedPhotosAlbum:image metadata:metadata completionBlock:^(NSURL *assetURL, NSError *error){ if (error) { // TODO: error handling } else { // TODO: success handling } }]; [library release];
На этом можно было бы остановиться, если фотография нужна вам только в фотоальбоме. Но мы пойдем дальше. Создаем объект dest_data, который нам понадобится для хранения фотографии
NSMutableData *dest_data = [NSMutableData data];
Создаем референс для фотографии
CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)image, NULL); if (!source) { NSLog(@"***Could not create image source ***"); }
Указываем тип
CFStringRef UTI = CGImageSourceGetType(source);
Указываем куда нужно записать полученные данные (в dest_data)
CGImageDestinationRef destination = CGImageDestinationCreateWithData((CFMutableDataRef)dest_data,UTI,1,NULL); if(!destination) { NSLog(@"***Could not create image destination ***"); }
Записываем данные с использованием словаря metadata (да, все тот же).
CGImageDestinationAddImageFromSource(destination,source,0, (CFDictionaryRef) metadata); [metadata release];
Делаем проверку
BOOL success = NO; success = CGImageDestinationFinalize(destination); if(!success) { NSLog(@"***Could not create data from image destination ***"); }
Не забываем почистить память
CFRelease(destination); CFRelease(source);
Теперь у нас есть объект dest_data, который хранит изображение с нужными тегами. Его можно использовать на ваше усмотрение.
Добавьте следующие строчки в ваш заголовочный файл
#import <CoreFoundation/CoreFoundation.h> #import <AssetsLibrary/ALAssetsLibrary.h> #import <ImageIO/ImageIO.h>
И не забудьте подключить нужные фреймворки.
Спасибо stackoverflow за ответы на мои бесконечные вопросы и всем кто дочитал до конца.