56 votes

UIImagePickerController et extraction de données EXIF à partir de photos existantes

Il est bien connu que UIImagePickerController ne pas renvoyer les métadonnées de la photo après la sélection. Cependant, un couple d'applications dans l'app store (Mobile Fotos, PixelPipe) semblent être en mesure de lire les fichiers d'origine et les données EXIF stockées au sein de eux, ce qui permet à l'application d'extraire les données à partir de la photo sélectionnée.

Ils semblent le faire par la lecture du fichier d'origine de l' /private/var/mobile/Media/DCIM/100APPLE/ dossier et en l'exécutant à travers une EXIF de la bibliothèque.

Cependant, je ne peux pas travailler un moyen d'associer une photo retourné à partir de la UIImagePickerController à un fichier sur le disque. J'ai exploré les tailles de fichier, mais le fichier d'origine est un JPEG, tandis que l'image renvoyée est un raw UIImage, rendant impossible de connaître la taille du fichier de l'image qui a été choisie.

J'envisage de faire un tableau de hachages et le rapprochement avec la première de x pixels de chaque image. Cela semble un peu plus haut, cependant, et probablement assez lent.

Toutes les suggestions?

29voto

yonel Points 6648

Avez-vous pris un coup d'oeil à ce exif iPhone bibliothèque?

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

Va l'essayer sur mon côté. Je voudrais avoir le GPS (géolocalisation) des coordonnées de l'image qui a été prise avec la UIImagePickerController :/

Après un regard plus profond, cette bibliothèque semble prendre NSData info comme une entrée et le UIImagePickerController renvoie une UIImage après la prise d'un instantané. En théorie, si nous utilisons l'sélectionnés à partir de la UIkit catégorie pour UIImage NSData * UIImageJPEGRepresentation ( UIImage *image, CGFloat compressionQuality ); Alors nous pouvons convertir les UIImage dans un NSData de l'instance et ensuite l'utiliser avec l'iPhone exif de la bibliothèque.

Mise à JOUR:
J'ai fait un test à la bibliothèque mentionné ci-dessus et il semble fonctionner. Toutefois, en raison de mon peu de knwoledge sur le format EXIF et le manque de haut niveau de l'API de la bibliothèque, je n'arrive pas à obtenir les valeurs pour les données EXIF. Voici mon code au cas où l'un de vous peut aller plus loin :


#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]];
....
....

La recherche des balises de définition est OK, mais toutes les valeurs de balise renvoie nil :(

Dans le cas où vous souhaitez donner un essai à la bibliothèque, vous devez définir une variable globale pour le remettre en marche (comme expliqué dans la doc, mais hum.. :/)

BOOL gLogging = FALSE;

Mise à JOUR 2
Réponse ici : iPhone - accéder aux informations de localisation à partir d'une photo Une UIImage ne pas encapsuler les méta-informations, de sorte que nous sommes coincés : pour sûr, pas EXIF info sera donnée par l'intermédiaire de cette interface.

DERNIÈRE MISE À JOUR
Ok j'ai réussi à le faire fonctionner, au moins pour géolocaliser correctement les images renvoyées par le sélecteur.
Avant le déclenchement de la UIImagePickerController, c'est à vous d'utiliser le CLLocationManager pour récupérer le courant CLocation
Une fois que vous avez cela, vous pouvez utiliser cette méthode qui utilise exif-iPhone bibliothèque de géolocaliser les UIImage de la 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];
}


23voto

RonC Points 475

Cela fonctionne avec iOS5 (beta 4) et la pellicule (vous avez besoin de définir le type pour les blocs dans le fichier .h):

 -(void) imagePickerController:(UIImagePickerController *)picker 
           didFinishPickingMediaWithInfo:(NSDictionary *)info
{
  NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
  if ([mediaType isEqualToString:(NSString*)kUTTypeImage]) {
    NSURL *url = [info objectForKey:UIImagePickerControllerReferenceURL];
    if (url) {
      ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset) {
      CLLocation *location = [myasset valueForProperty:ALAssetPropertyLocation];
      // location contains lat/long, timestamp, etc
      // extracting the image is more tricky and 5.x beta ALAssetRepresentation has bugs!
    };
    ALAssetsLibraryAccessFailureBlock failureblock = ^(NSError *myerror) {
      NSLog(@"cant get image - %@", [myerror localizedDescription]);
    };
    ALAssetsLibrary *assetsLib = [[ALAssetsLibrary alloc] init];
    [assetsLib assetForURL:url resultBlock:resultblock failureBlock:failureblock];
  }
}
 

5voto

Yannick Compernol Points 2875

Apple a ajouté un cadre I / O Image dans iOS4 qui peut être utilisé pour lire des données EXIF à partir d'images. Je ne sais pas si UIImagePickerController renvoie une image avec les données EXIF intégrées.

Éditer: Dans iOS4, vous pouvez récupérer les données EXIF en récupérant la valeur de la clé UIImagePickerControllerMediaMetadata dans le dictionnaire d’informations qui est transmise au délégué UIImagePickerControllerDelegate .

2voto

Urkle Points 443

Je passe un certain temps à travailler sur ce point aussi, pour une application j'ai été conclu le contrat de construction. Fondamentalement, comme l'API actuelle, il n'est pas possible. Le problème de base est le UIImage classe des BANDES de toutes les données EXIF, sauf pour l'orientation. Aussi la fonction pour enregistrer dans la pellicule des bandes de ces données. Donc, fondamentalement, la seule façon de saisir et de maintenir supplémentaire des données EXIF qui est de l'enregistrer dans un cadre " privé "camera roll" dans votre application. J'ai déposé ce bug avec apple ainsi et a souligné la nécessité de l'application de l'examinateur de répétitions, nous avons été en contact avec. J'espère qu'un jour ils vont l'ajouter dans.. Sinon il fait d'avoir la GÉO-tagging complètement inutile car il ne fonctionne que dans le "stock" de l'application appareil photo.

REMARQUE Certaines applications sur l'app store hack autour de ce. Par ce que j'ai trouvé, en accédant directement à la bobine de caméra et ENREGISTREMENT de photos directement à enregistrer les données GEO. Toutefois, cela ne fonctionne qu'avec la camera roll/sauvegarder des photos et PAS le reste de la bibliothèque de photos. Les photos "synchronisés" de votre téléphone à partir de votre ordinateur toutes les données EXIF, sauf pour l'orientation dépouillé.

Je n'arrive toujours pas à comprendre pourquoi ces demandes ont été approuvées (heck ils même de les SUPPRIMER à partir de la pellicule) et notre application qui ne fait rien de cela n'est encore freinée.

1voto

natevw Points 3543

C'est quelque chose que l'API publique ne prévoit pas, mais pourrait être utile à beaucoup de gens. Votre principal recours est de remplir un rapport de bogue avec Apple qui décrit ce qu'il vous faut (et il peut être utile d'expliquer pourquoi vous avez besoin en tant que bien). Nous espérons que votre demande pourrait le faire dans une version future.

Après le dépôt d'un bug, vous pouvez également utiliser l'un des Développeurs de l'assistance Technique (DTS) les incidents qui sont venus avec votre iPhone Developer Program adhésion. Si il y a un public pour ce faire, une Pomme ingénieur savoir. Sinon, il peut au moins aider à obtenir votre sort un peu plus d'attention dans le vaisseau-mère. Bonne chance!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X