Чтение данных GPS с изображения, возвращаемого камерой в iOS iphone

Мне нужно получить координаты GPS изображения, снятого с камерой устройства iOS. Меня не интересуют изображения Camera Roll, только изображение, сделанное с UIImagePickerControllerSourceTypeCamera.

Я прочитал много ответов stackoverflow, таких как Get Exif data из UIImage – UIImagePickerController , который предполагает, что вы используете среду AssetsLibrary, которая, похоже, не работает на изображениях с камеры, или используйте CoreLocaiton для получения широты / долготы из приложения а не из образа.

Использование CoreLocation не является вариантом . Это не даст мне координаты при нажатии кнопки спуска затвора. (С решениями, основанными на CoreLocation, вам нужно либо записать координаты, прежде чем вы откроете представление камеры или после, и, конечно, если устройство движется, координаты будут неправильными. Этот метод должен работать со стационарным устройством.)

Я только iOS5, поэтому мне не нужно поддерживать старые устройства. Это также для коммерческого продукта, поэтому я не могу использовать http://code.google.com/p/iphone-exif/ .

Итак, каковы мои возможности для чтения данных GPS с изображения, возвращаемого камерой в iOS5? Все, о чем я могу сейчас думать, это сохранить изображение в Camera Roll, а затем использовать AssetsLibrary, но это кажется hokey.

Благодаря!


Вот код, который я написал на основе ответа Калеба.

UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage]; NSData *jpeg = UIImageJPEGRepresentation(image,1.0); CGImageSourceRef source ; source = CGImageSourceCreateWithData((__bridge CFDataRef)jpeg, NULL); NSDictionary *metadataNew = (__bridge NSDictionary *) CGImageSourceCopyPropertiesAtIndex(source,0,NULL); NSLog(@"%@",metadataNew); 

и моя консоль показывает:

  2012-04-26 14:15:37:137 ferret[2060:1799] { ColorModel = RGB; Depth = 8; Orientation = 6; PixelHeight = 1936; PixelWidth = 2592; "{Exif}" = { ColorSpace = 1; PixelXDimension = 2592; PixelYDimension = 1936; }; "{JFIF}" = { DensityUnit = 0; JFIFVersion = ( 1, 1 ); XDensity = 1; YDensity = 1; }; "{TIFF}" = { Orientation = 6; }; } 

Нет широты / долготы.

9 Solutions collect form web for “Чтение данных GPS с изображения, возвращаемого камерой в iOS iphone”

Проблема в том, что с iOS 4 UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage]; удаляет геолокацию. Чтобы решить эту проблему, вы должны использовать исходный путь фотографии, чтобы получить доступ к метаданным полного изображения. Что-то вроде этого:

 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { NSURL *referenceURL = [info objectForKey:UIImagePickerControllerReferenceURL]; ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; [library assetForURL:referenceURL resultBlock:^(ALAsset *asset) { ALAssetRepresentation *rep = [asset defaultRepresentation]; NSDictionary *metadata = rep.metadata; NSLog(@"%@", metadata); CGImageRef iref = [rep fullScreenImage] ; if (iref) { self.imageView.image = [UIImage imageWithCGImage:iref]; } } failureBlock:^(NSError *error) { // error handling }]; 

Результат должен выглядеть примерно так:

 { ColorModel = RGB; DPIHeight = 72; DPIWidth = 72; Depth = 8; Orientation = 6; PixelHeight = 1936; PixelWidth = 2592; "{Exif}" = { ApertureValue = "2.970854"; BrightnessValue = "1.115874"; ColorSpace = 1; ComponentsConfiguration = ( 0, 0, 0, 1 ); DateTimeDigitized = "2012:07:14 21:55:05"; DateTimeOriginal = "2012:07:14 21:55:05"; ExifVersion = ( 2, 2, 1 ); ExposureMode = 0; ExposureProgram = 2; ExposureTime = "0.06666667"; FNumber = "2.8"; Flash = 24; FlashPixVersion = ( 1, 0 ); FocalLength = "3.85"; ISOSpeedRatings = ( 200 ); MeteringMode = 5; PixelXDimension = 2592; PixelYDimension = 1936; SceneCaptureType = 0; SensingMethod = 2; Sharpness = 2; ShutterSpeedValue = "3.9112"; SubjectArea = ( 1295, 967, 699, 696 ); WhiteBalance = 0; }; "{GPS}" = { Altitude = "1167.528"; AltitudeRef = 0; ImgDirection = "278.8303"; ImgDirectionRef = T; Latitude = "15.8235"; LatitudeRef = S; Longitude = "47.99416666666666"; LongitudeRef = W; TimeStamp = "00:55:04.59"; }; "{TIFF}" = { DateTime = "2012:07:14 21:55:05"; Make = Apple; Model = "iPhone 4"; Orientation = 6; ResolutionUnit = 2; Software = "5.1.1"; XResolution = 72; YResolution = 72; "_YCbCrPositioning" = 1; }; } 

Мы много работали с камерой и UIImagePickerController и, по крайней мере, вплоть до iOS 5.1.1, она не возвращает данные о местоположении в метаданных для фотографий или видео, снятых с UIImagePickerController .

Не имеет значения, включена ли служба определения местоположения для приложения «Камера» или нет; это контролирует использование приложениями местоположения камеры, а не функцию камеры в UIImagePickerController .

Вашему приложению нужно будет использовать класс CLLocation чтобы получить местоположение, а затем добавить его к изображению или видео, возвращенному с камеры. Может ли ваше приложение получить местоположение, зависит от того, разрешает ли пользователь доступ к службам местоположения для вашего приложения. Обратите внимание, что пользователь может отключить службы определения местоположения для вашего приложения (или полностью для устройства) в любое время через « Settings > Location Службы Settings > Location .

Одна из возможностей – оставить CoreLocation запущенным, когда камера видна. Запишите каждый CCLocation в массив вместе со временем выборки. Когда фото возвращается, найдите свое время, а затем сопоставьте ближайший CClocation из массива.

Звучит kludgy, но он будет работать.

Вы не используете данные изображения из камеры в коде, который вы опубликовали, вы создали его JPEG-представление, которое по существу отменило бы все метаданные. Используйте изображение. image.CGImage как предположил Калеб.

Также:

Это также для коммерческого продукта, поэтому я не могу использовать http://code.google.com/p/iphone-exif/ .

Автор совершенно четко заявляет, что коммерческое лицензирование доступно.

Не могу сказать, что мне нужно было сделать именно это в моих собственных материалах, но из документов это выглядит довольно ясно, что если вы используете UIImagePickerController вы можете получить изображение, которое пользователь только что взял с -imagePicker:didFinishPickingMediaWithInfo: delegate метод. Для получения изображения используйте ключ UIImagePickerControllerOriginalImage .

После того, как вы получили изображение, вы сможете получить доступ к его свойствам, включая данные EXIF, как описано в QA1654. Доступ к свойствам изображения с помощью ImageIO . Чтобы создать CGImageSource, я бы посмотрел CGImageSourceCreateWithData() и использовал данные, полученные из метода CGImage CGImage . Когда у вас есть источник изображения, вы можете получить доступ к различным атрибутам через CGImageSourceCopyProperties() .

Как указывает Крис Маркл , Apple действительно снимает данные GPS из EXIF. Но вы можете открыть RAW-данные изображения и самостоятельно проанализировать данные или использовать стороннюю библиотеку для этого, например .

Вот пример кода:

 - (void) imagePickerController: (UIImagePickerController *) picker didFinishPickingMediaWithInfo: (NSDictionary *) info { ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; [library assetForURL:[info objectForKey:UIImagePickerControllerReferenceURL] resultBlock:^(ALAsset *asset) { ALAssetRepresentation *image_representation = [asset defaultRepresentation]; NSUInteger size = (NSUInteger)image_representation.size; // create a buffer to hold image data uint8_t *buffer = (Byte*)malloc(size); NSUInteger length = [image_representation getBytes:buffer fromOffset: 0.0 length:size error:nil]; if (length != 0) { // buffer -> NSData object; free buffer afterwards NSData *adata = [[NSData alloc] initWithBytesNoCopy:buffer length:size freeWhenDone:YES]; EXFJpeg* jpegScanner = [[EXFJpeg alloc] init]; [jpegScanner scanImageData: adata]; EXFMetaData* exifData = jpegScanner.exifMetaData; id latitudeValue = [exifData tagValue:[NSNumber numberWithInt:EXIF_GPSLatitude]]; id longitudeValue = [exifData tagValue:[NSNumber numberWithInt:EXIF_GPSLongitude]]; id datetime = [exifData tagValue:[NSNumber numberWithInt:EXIF_DateTime]]; id t = [exifData tagValue:[NSNumber numberWithInt:EXIF_Model]]; self.locationLabel.text = [NSString stringWithFormat:@"Local: %@ - %@",latitudeValue,longitudeValue]; self.dateLavel.text = [NSString stringWithFormat:@"Data: %@", datetime]; } else { NSLog(@"image_representation buffer length == 0"); } } failureBlock:^(NSError *error) { NSLog(@"couldn't get asset: %@", error); } ]; } 

В своем делете UIImagePickerController выполните следующие действия:

 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { NSDictionary *metadata = [info valueForKey:UIImagePickerControllerMediaMetadata]; // metadata now contains all the image metadata. Extract GPS data from here. } 

Это проверено на iOS 8 и работает для видео, поэтому оно должно работать аналогично для фотографий с несколькими настройками.

 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { NSURL *videoUrl = (NSURL *)[info objectForKey:UIImagePickerControllerMediaURL]; NSString *moviePath = [videoUrl path]; if ( UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(moviePath) ) { ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc] init]; [assetLibrary assetForURL:[info objectForKey:UIImagePickerControllerReferenceURL] resultBlock:^(ALAsset *asset) { CLLocation *location = [asset valueForProperty:ALAssetPropertyLocation]; NSLog(@"Location Meta: %@", location); } failureBlock:^(NSError *error) { NSLog(@"Video Date Error: %@", error); }]; } } 

Быстрый ответ:

 import AssetsLibrary import CoreLocation // MARK: - UIImagePickerControllerDelegate extension ViewController: UIImagePickerControllerDelegate { func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) { defer { dismiss(animated: true, completion: nil) } guard picker.sourceType == .photoLibrary else { return } guard let url = info[UIImagePickerControllerReferenceURL] as? URL else { return } let library = ALAssetsLibrary() library.asset(for: url, resultBlock: { (asset) in guard let coordinate = asset?.value(forProperty: ALAssetPropertyLocation) as? CLLocation else { return } print("\(coordinate)") // Getting human-readable address. let geocoder = CLGeocoder() geocoder.reverseGeocodeLocation(coordinate, completionHandler: { (placemarks, error) in guard let placemark = placemarks?.first else { return } print("\(placemark.addressDictionary)") }) }, failureBlock: { (error: Error?) in print("Unable to read metadata: \(error)") }) } } 
  • Уменьшение использования фона в фоновом режиме iOS
  • Что мы можем использовать вместо nstimer?
  • Поиск уровня сигнала GPS
  • Ограничить обратную геолокацию - kCLErrorDomain Code = 2
  • Phonegap geolocation.watchPosition не обновляет местоположение на iPhone
  • Точность основного местоположения
  • Отладка приложения CoreLocation в реальном устройстве IO
  • как конвертировать gps на север и gps на запад до lat / long в объективе c
  • Детальное использование аккумулятора - iOS
  • API Geofence для iOS 5
  • Рассчитать расстояние между двумя местами, используя широту-долготу в gmap для iPhone
  • iOS: Можно ли запросить базовую структуру расположения для определения местоположения, используя только ячеистую башню или только Wi-Fi или используя GPS-антенны?
  • Interesting Posts

    Верните обернутую словом NSString из более длинного файла NSString

    CNContactPickerViewController на контроллере панели вкладок

    Сохранить EVObjects с помощью CoreData

    Должен ли я платить, чтобы получить пользовательский поиск Google в моем приложении?

    Ядро рисования прямоугольника с рамкой в ​​одной строке

    UIImageView для показа хода загрузки приложения

    Кнопка триггера для изменения текста в UITextView в swift3 xcode 8 ios 10

    Как свести к минимуму приложение ios

    Утечка памяти на быстрой игровой площадке / deinit {} не называется последовательно

    Как перейти «без контроллера панели навигации» в «с контроллером просмотра навигационной панели» в Swift

    Автоматический поиск бизнеса Swift Mapkit

    Отключить предложения ярлыков клавиатуры UITextField

    Подтверждение от пользователя перед обновлением новой версии приложения в ios

    Верхняя панель не отображается для текущегоModalViewController

    Программировать триггерное событие iOS

    PhoneC: Разработка iOS проста с помощью XCode, Swift3, UITableView, cocatouch, давайте создадим приложения для iPhone, iPad и Macbook.