Какой самый эффективный способ получить индекс итератора std :: vector?

Вы посмотрели эту библиотеку exif iPhone?

http://code.google.com/p/iphone-exif/

Собираюсь попробовать это на моей стороне. Я хотел бы получить координаты GPS (геотаг) от изображения, которое было сделано с помощью UIImagePickerController: /

. После более глубокого просмотра эта библиотека, как представляется, принимает информацию NSData как входную информацию и возвращает UIImagePickerController UIImage после моментального снимка. Теоретически, если мы используем выбранную из категории UIkit для UIImage

NSData * UIImageJPEGRepresentation (
   UIImage *image,
   CGFloat compressionQuality
);

Затем мы можем преобразовать UIImage в экземпляр NSData, а затем использовать его с библиотекой exif iPhone.

ОБНОВЛЕНИЕ: Я дал тест в упомянутой выше библиотеке и, похоже, работает. Однако из-за моего ограниченного knwoledge о формате EXIF ​​и отсутствии API высокого уровня в библиотеке мне не удается получить значения для тегов EXIF. Вот мой код, если любой из вас может пойти дальше:


#import "EXFJpeg.h"

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo {
    NSLog(@"image picked %@ with info %@", image, editingInfo);
    NSData* jpegData = UIImageJPEGRepresentation (image,0.5);
    EXFJpeg* jpegScanner = [[EXFJpeg alloc] init];
    [jpegScanner scanImageData: jpegData];
    EXFMetaData* exifData = jpegScanner.exifMetaData;
    EXFJFIF* jfif = jpegScanner.jfif;
    EXFTag* tagDefinition = [exifData tagDefinition: [NSNumber numberWithInt:EXIF_DateTime]];
    //EXFTag* latitudeDef = [exifData tagDefinition: [NSNumber numberWithInt:EXIF_GPSLatitude]];
    //EXFTag* longitudeDef = [exifData tagDefinition: [NSNumber numberWithInt:EXIF_GPSLongitude]];
    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]];
....
....

Определение определения тегов в порядке, но все значения тегов возвращают nil: (

В случае, если вы хотите попробовать в библиотеку, вам нужно определить глобальную переменную, чтобы запустить ее (как описано в документе, но hum ..: /)

BOOL gLogging = FALSE;

UPDATE 2 Ответ здесь: iPhone - информация о местоположении доступа с фото UIImage не инкапсулирует метаинформацию , поэтому мы застряли: точно, никакая информация EXIF ​​не будет

FINAL UPDATE Хорошо, мне удалось заставить его работать, по крайней мере, для правильного отображения снимков, возвращенных сборщиком. Перед запуском UIImagePickerController, это вверх вам, чтобы использовать CLLocationManager для извлечения текущего CLocation . После этого вы можете использовать этот метод, который использует библиотеку exif-iPhone для геотегирования UIImage из CLLocation:


-(NSData*) geotagImage:(UIImage*)image withLocation:(CLLocation*)imageLocation {
    NSData* jpegData =  UIImageJPEGRepresentation(image, 0.8);
    EXFJpeg* jpegScanner = [[EXFJpeg alloc] init];
    [jpegScanner scanImageData: jpegData];
    EXFMetaData* exifMetaData = jpegScanner.exifMetaData;
    // end of helper methods 
    // adding GPS data to the Exif object 
    NSMutableArray* locArray = [self createLocArray:imageLocation.coordinate.latitude]; 
    EXFGPSLoc* gpsLoc = [[EXFGPSLoc alloc] init]; 
    [self populateGPS: gpsLoc :locArray]; 
    [exifMetaData addTagValue:gpsLoc forKey:[NSNumber numberWithInt:EXIF_GPSLatitude] ]; 
    [gpsLoc release]; 
    [locArray release]; 
    locArray = [self createLocArray:imageLocation.coordinate.longitude]; 
    gpsLoc = [[EXFGPSLoc alloc] init]; 
    [self populateGPS: gpsLoc :locArray]; 
    [exifMetaData addTagValue:gpsLoc forKey:[NSNumber numberWithInt:EXIF_GPSLongitude] ]; 
    [gpsLoc release]; 
    [locArray release];
    NSString* ref;
    if (imageLocation.coordinate.latitude <0.0)
        ref = @"S"; 
    else
        ref =@"N"; 
    [exifMetaData addTagValue: ref forKey:[NSNumber numberWithInt:EXIF_GPSLatitudeRef] ]; 
    if (imageLocation.coordinate.longitude <0.0)
        ref = @"W"; 
    else
        ref =@"E"; 
    [exifMetaData addTagValue: ref forKey:[NSNumber numberWithInt:EXIF_GPSLongitudeRef] ]; 
    NSMutableData* taggedJpegData = [[NSMutableData alloc] init];
    [jpegScanner populateImageData:taggedJpegData];
    [jpegScanner release];
    return [taggedJpegData autorelease];
}

// Helper methods for location conversion -(NSMutableArray*) createLocArray:(double) val{ val = fabs(val); NSMutableArray* array = [[NSMutableArray alloc] init]; double deg = (int)val; [array addObject:[NSNumber numberWithDouble:deg]]; val = val - deg; val = val*60; double minutes = (int) val; [array addObject:[NSNumber numberWithDouble:minutes]]; val = val - minutes; val = val*60; double seconds = val; [array addObject:[NSNumber numberWithDouble:seconds]]; return array; } -(void) populateGPS:(EXFGPSLoc* ) gpsLoc :(NSArray*) locArray{ long numDenumArray[2]; long* arrPtr = numDenumArray; [EXFUtils convertRationalToFraction:&arrPtr :[locArray objectAtIndex:0]]; EXFraction* fract = [[EXFraction alloc] initWith:numDenumArray[0]:numDenumArray[1]]; gpsLoc.degrees = fract; [fract release]; [EXFUtils convertRationalToFraction:&arrPtr :[locArray objectAtIndex:1]]; fract = [[EXFraction alloc] initWith:numDenumArray[0] :numDenumArray[1]]; gpsLoc.minutes = fract; [fract release]; [EXFUtils convertRationalToFraction:&arrPtr :[locArray objectAtIndex:2]]; fract = [[EXFraction alloc] initWith:numDenumArray[0] :numDenumArray[1]]; gpsLoc.seconds = fract; [fract release]; }

392
задан Ciro Santilli 新疆改造中心996ICU六四事件 15 January 2017 в 17:45
поделиться

7 ответов

я бы предпочел it - vec.begin() именно по той противоположной причине, которая была указана Naveen: поэтому не будет компилироваться, если изменить вектор в список. Если делать это во время каждой итерации, то можно легко превратить алгоритм O(n) в алгоритм O(n^2).

Другим вариантом, если не перепрыгивать через контейнер во время итерации, будет сохранение индекса в качестве второго счетчика цикла.

Примечание: it - общее имя для итератора контейнера,std::container_type::iterator it;.

521
ответ дан 22 November 2019 в 23:32
поделиться

Согласно http://www.cplusplus.com/reference/std/iterator/distance/ , с VEC.BEGIN () представляет собой произвольный доступ Итератор, метод расстояния использует оператор - .

Так что ответ, с точки зрения производительности, одинаково, но, возможно, с использованием расстояние () легче понять, если кто-нибудь должен будет читать и понять ваш код.

4
ответ дан 22 November 2019 в 23:32
поделиться

Я бы предпочел STD :: Расстояние (VEC.Begin (), он) , поскольку он позволит мне изменить контейнер без каких-либо изменений кода. Например, если вы решите использовать STD :: Список вместо STD :: VECTOR , который не содержит случайного итератора доступа Вашего кода все еще будет компилировать. Поскольку STD :: Расстояние поднимает оптимальный метод в зависимости от чертов итератора, у вас тоже нет никакой деградации производительности.

126
ответ дан 22 November 2019 в 23:32
поделиться

Поскольку UncleBens и Naveen показали, есть серьезные основания для обоих. То, какой «лучше», зависит, на каком поведении вы хотите: вы хотите гарантировать постоянно-разовое поведение, или вы хотите, чтобы оно отступило к линейному времени когда необходимый?

это - vec.begin () занимает время, но оператор - только определен на произвольном доступе iterators, таким образом, кодекс не соберет вообще со списком iterators, например.

std:: distance (vec.begin (), it) работает для всех типов итераторов, но будет только операцией постоянного времени, если используется на итераторах произвольного доступа.

Ни один из них не «лучше.» Используйте ту, которая делает то, что вам нужно.

72
ответ дан 22 November 2019 в 23:32
поделиться

Мне нравится этот: Это - VEC.Begin () , потому что мне это ясно говорит «расстояние от начала». С итераторами мы привыкли думать с точки зрения арифметики, поэтому значок - - это самый яркий индикатор.

11
ответ дан 22 November 2019 в 23:32
поделиться

- я бы использовал вариант - только для std::vector - понятно, что имеется в виду, а простота операции (которая не больше вычитания указателя) выражается синтаксисом (дистанция, с другой стороны, при первом чтении звучит как пифагор, не правда ли?). Как отмечает дядяBen, - также действует как статическое утверждение в случае, если вектор - случайно изменен на list.

Также я думаю, что это гораздо более распространенное утверждение - не иметь чисел, чтобы доказать это. Главный аргумент: it - vec.begin() короче в исходных текстах - меньше работы по набору, меньше места. Так как понятно, что правильный ответ на ваш вопрос сводится к делу, это может быть и аргументом, который будет действительным.

3
ответ дан 22 November 2019 в 23:32
поделиться

Если Ваш алгоритм уже ограничен/жестко закодирован только std::vector::iterator и std::vector::iterator, то не имеет значения, какой метод Вы в конечном итоге будете использовать. Ваш алгоритм уже конкретизирован за тем, что выбор одного из них может иметь какое-то значение. Они оба делают одно и то же. Это просто вопрос личных предпочтений. Я бы лично использовал явное вычитание.

Если, с другой стороны, Вы хотите сохранить в своем алгоритме более высокую степень обобщения, а именно допустить возможность того, что когда-нибудь в будущем он может быть применен к какому-нибудь другому типу итератора, то лучший метод зависит от Ваших намерений. Это зависит от того, насколько ограничительным вы хотите быть в отношении типа итератора, который может быть использован здесь.

  • Если вы используете явное вычитание, то ваш алгоритм будет ограничен довольно узким классом итераторов: итераторами случайного доступа. (Это то, что Вы получите теперь из std::vector)

  • Если Вы используете расстояние distance, то Ваш алгоритм будет поддерживать гораздо более широкий класс итераторов: ввод итераторов.

Конечно, вычисление расстояния для итераторов неслучайного доступа в общем случае является неэффективной операцией (в то время как для итераторов неслучайного доступа она также эффективна, как и вычитание). Решать, имеет ли алгоритм смысл для неслучайных итераторов, с точки зрения эффективности, Вы сами решаете. Это приводит к потере эффективности, что делает ваш алгоритм совершенно бесполезным, тогда лучше придерживаться вычитания, тем самым запрещая неэффективное использование и заставляя пользователя искать альтернативные решения для других типов итераторов. Если эффективность с итераторами неслучайного доступа все еще находится в полезном диапазоне, то следует использовать расстояние и задокументировать тот факт, что алгоритм лучше работает с итераторами неслучайного доступа.

8
ответ дан 22 November 2019 в 23:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: