Всем известно, что приложение «Фото», установленное на всех 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 за ответы на мои бесконечные вопросы и всем кто дочитал до конца.