iphone - UIImagePickerController और मौजूदा फ़ोटो से EXIF डेटा निकालने




cocoa-touch gps (12)

आईओएस 10 के लिए - स्विफ्ट 3

पिकर के कॉलबैक में एक info निर्देश है जहां metadata साथ एक कुंजी metadata : UIImagePickerControllerMediaMetadata

यह अच्छी तरह से जाना जाता है कि UIImagePickerController चयन के बाद फोटो के मेटाडेटा को वापस नहीं करता है। हालांकि, ऐप स्टोर (मोबाइल फ़ोटोज़, पिक्सेलपिप) में कुछ ऐप्स मूल फ़ाइलों और उनके भीतर संग्रहीत EXIF ​​डेटा को पढ़ने में सक्षम होते हैं, जिससे ऐप को चयनित फ़ोटो से जिओडाटा निकालने में सक्षम बनाता है।

वे मूल फ़ाइल को / निजी / var / मोबाइल / मीडिया / डीसीआईएम / 100APPLE / फ़ोल्डर से पढ़कर और EXIF ​​लाइब्रेरी के माध्यम से इसे चलाकर ऐसा करते हैं।

हालांकि, मैं UIImagePickerController से डिस्क पर एक फ़ाइल में लौटाई गई तस्वीर से मेल खाने का एक तरीका नहीं निकाल सकता। मैंने फ़ाइल आकारों की खोज की है, लेकिन मूल फ़ाइल एक जेपीईजी है, जबकि लौटाई गई छवि कच्ची यूआईएममेज है, जिससे छवि के फ़ाइल आकार को जानना असंभव हो गया है।

मैं हैश की एक टेबल बनाने और प्रत्येक छवि के पहले एक्स पिक्सेल के खिलाफ मिलान करने पर विचार कर रहा हूं। हालांकि यह शीर्ष पर थोड़ा सा लगता है, और शायद काफी धीमी है।

कोई सुझाव?


आईओएस 8 के लिए और बाद में आप फोटो फ्रेमवर्क का उपयोग कर सकते हैं

- (BOOL)writeCGImageToCameraRoll:(CGImageRef)cgImage withMetadata:(NSDictionary *)metadata
{

   NSDictionary *Exif = [metadata objectForKey:@"Exif"];   // Add this line

}

इस मेटाडेटा को प्राप्त करने के लिए आपको निचले स्तर के फ्रेमवर्क AVFoundation का उपयोग करना होगा।

ऐप्पल के स्क्वायरकैम उदाहरण पर एक नज़र डालें (http://developer.apple.com/library/ios/#samplecode/SquareCam/Introduction/Intro.html)

नीचे दी गई विधि पाएं और लाइन जोड़ें, मैंने कोड में जोड़ा है। मेटाडेटा डिक्शनरी में भी निदान एनएस डिक्शनरी ऑब्जेक्ट होता है।

-(CLLocation*)locationFromAsset:(ALAsset*)asset
{
    if (!asset)
        return nil;

    NSDictionary* pickedImageMetadata = [[asset defaultRepresentation] metadata];
    NSDictionary* gpsInfo = [pickedImageMetadata objectForKey:(__bridge NSString *)kCGImagePropertyGPSDictionary];
    if (gpsInfo){
        NSNumber* nLat = [gpsInfo objectForKey:(__bridge NSString *)kCGImagePropertyGPSLatitude];
        NSNumber* nLng = [gpsInfo objectForKey:(__bridge NSString *)kCGImagePropertyGPSLongitude];
        if (nLat && nLng)
            return [[CLLocation alloc]initWithLatitude:[nLat doubleValue] longitude:[nLng doubleValue]];
    }

    return nil;
}


-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    //UIImage *image =  [info objectForKey:UIImagePickerControllerOriginalImage];
    NSURL *assetURL = [info objectForKey:UIImagePickerControllerReferenceURL];

    // create the asset library in the init method of your custom object or view controller
    //self.library = [[ALAssetsLibrary alloc] init];
    //

    [self.library assetForURL:assetURL resultBlock:^(ALAsset *asset) {

        // try to retrieve gps metadata coordinates
        CLLocation* myLocation = [self locationFromAsset:asset];

        // Do your stuff....

    } failureBlock:^(NSError *error) {
        NSLog(@"Failed to get asset from library");
    }];
}

ऐप्पल ने आईओएस 4 में एक छवि I / O फ्रेमवर्क जोड़ा है जिसका उपयोग चित्रों से EXIF ​​डेटा पढ़ने के लिए किया जा सकता है। मुझे नहीं पता कि UIImagePickerController हालांकि एम्बेडेड EXIF ​​डेटा के साथ एक तस्वीर देता है।

संपादित करें: आईओएस 4 में आप UIImagePickerControllerMediaMetadata कुंजी के मूल्य को हथियाने के द्वारा EXII डेटा प्राप्त कर सकते हैं जो UIImagePickerControllerDelegate प्रतिनिधि को पास की जाने वाली जानकारी शब्दकोश में है।


ऐसा लगता है कि UIImagePickerControllerMediaURL द्वारा प्राप्त तस्वीर में एक्फिफ़ टैग बिल्कुल नहीं हैं


क्या आपने इस आईफोन लाइब्रेरी को देखा है?

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

मेरी तरफ से कोशिश करूँगा। मैं उस चित्र से जीपीएस (जियोटैग) निर्देशांक प्राप्त करना चाहता हूं जो UIImagePickerController के साथ लिया गया है: /

एक गहरी नजर के बाद, यह लाइब्रेरी एनएसडीटा जानकारी को इनपुट के रूप में लेती है और यूआईएममेज पिकर कंट्रोलर स्नैपशॉट लेने के बाद यूआईएममेज लौटाता है। सिद्धांत रूप में, यदि हम UIImage के लिए UIkit श्रेणी से चयनित का उपयोग करते हैं

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

फिर हम UIImage को NSData इंस्टेंस में परिवर्तित कर सकते हैं और फिर इसे आईफोन एक्सिफ़ लाइब्रेरी के साथ उपयोग कर सकते हैं।

अद्यतन करें:
मैंने ऊपर वर्णित पुस्तकालय को एक परीक्षण दिया और ऐसा लगता है कि यह काम करता है। हालांकि, EXIF ​​प्रारूप और लाइब्रेरी में उच्च स्तरीय एपीआई की कमी के बारे में मेरे सीमित knwoledge के कारण, मैं 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;

अद्यतन 2
यहां जवाब दें: आईफोन - एक फोटो से स्थान की जानकारी का उपयोग करें UIImage मेटा जानकारी को समाहित नहीं करता है , इसलिए हम अटक गए हैं: निश्चित रूप से, इस इंटरफ़ेस के माध्यम से कोई EXIF ​​जानकारी नहीं दी जाएगी।

अंतिम अद्यतन
ठीक है, मैं इसे पिकर द्वारा लौटाए गए चित्रों को कम से कम जियोटैग करने के लिए काम करने में कामयाब रहा।
UIImagePickerController को ट्रिगर करने से पहले, वर्तमान कॉलेशन पुनर्प्राप्त करने के लिए CLLocationManager का उपयोग करना आपके ऊपर निर्भर है
एक बार आपके पास हो जाने के बाद, आप इस विधि का उपयोग कर सकते हैं जो क्लाउलोकेशन से UIImage को geotag करने के लिए exif-iPhone लाइब्रेरी का उपयोग करता है:

-(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];
  }
}


फ़ाइल फ़ाइल को मूल फ़ाइल में प्राप्त करने के लिए UIImagePickerControllerMediaURL शब्दकोश कुंजी का उपयोग करें। दस्तावेज़ीकरण के बावजूद, आप फोटो के लिए फ़ाइल यूआरएल और न केवल फिल्में प्राप्त कर सकते हैं।

 func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
      let url = info[UIImagePickerControllerReferenceURL] as? URL
            if url != nil {

                let fetchResult = PHAsset.fetchAssets(withALAssetURLs: [url!], options: nil)
                let asset = fetchResult.firstObject
                print(asset?.location?.coordinate.latitude)
                print(asset?.creationDate)
            }
    }

बस एक विचार है, लेकिन क्या आपने GitHub पर थ्री 20 प्रोजेक्ट में TTPhotoViewController को आजमाया है?

यह एक छवि पिकर प्रदान करता है जो कई स्रोतों से पढ़ सकता है। आप इसे UIImagePickerController के विकल्प के रूप में उपयोग करने में सक्षम हो सकते हैं, या स्रोत आपको एक सुराग दे सकता है कि आपको आवश्यक जानकारी कैसे प्राप्त करें।


मैं इस पर काम करने के लिए थोड़ी देर बिताता हूं, जिसके लिए मुझे एक आवेदन के लिए अनुबंधित किया गया था। असल में एपीआई वर्तमान में खड़ा है क्योंकि यह संभव नहीं है। मूल समस्या UIImage क्लास अभिविन्यास को छोड़कर सभी EXIF ​​डेटा STRIPS है। कैमरा रोल में सहेजने के लिए यह फ़ंक्शन भी इस डेटा को स्ट्रिप्स करता है। तो मूल रूप से किसी भी अतिरिक्त EXIF ​​डेटा को पकड़ने और बनाए रखने का एकमात्र तरीका यह है कि इसे अपने एप्लिकेशन में एक निजी "कैमरा रोल" में सहेज लें। मैंने इस बग को सेब के साथ भी दायर किया है और ऐप समीक्षक प्रतिनिधि की आवश्यकता पर जोर दिया है जिसके साथ हम संपर्क में हैं। उम्मीद है कि किसी दिन वे इसे जोड़ देंगे .. अन्यथा यह जीईओ टैगिंग पूरी तरह से बेकार है क्योंकि यह केवल "स्टॉक" कैमरा एप्लिकेशन में काम करता है।

नोट ऐप स्टोर पर कुछ एप्लिकेशन इस के आसपास हैक । जीईओ डेटा को बचाने के लिए, जो मैंने पाया है, सीधे कैमरे रोल तक पहुंच रहा है और सीधे फोटो सहेज रहा है। हालांकि यह केवल कैमरा रोल / सहेजी गई तस्वीरों के साथ काम करता है और शेष फोटो लाइब्रेरी नहीं। आपके कंप्यूटर से आपके फोन पर "सिंक" की गई तस्वीरों में अभिविन्यास को छोड़कर सभी EXIF ​​डेटा हैं।

मैं अभी भी समझ नहीं पा रहा हूं कि उन अनुप्रयोगों को क्यों स्वीकृत किया गया था (वे कैमरे रोल से भी हटा दें) और हमारे आवेदन जो कि उनमें से कोई भी अभी भी वापस नहीं रखा जा रहा है।


मैं कैमरा रोल छवियों के लिए इसका उपयोग कर रहा हूँ

import AssetsLibrary

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {

    if picker.sourceType == UIImagePickerControllerSourceType.photoLibrary,
        let url = info[UIImagePickerControllerReferenceURL] as? URL {

        let assetLibrary = ALAssetsLibrary()
        assetLibrary.asset(for: url, resultBlock: { (asset) in
            if let asset = asset {
                let assetRep: ALAssetRepresentation = asset.defaultRepresentation()
                let metaData: NSDictionary = assetRep.metadata() as NSDictionary
                print(metaData)
            }
        }, failureBlock: { (error) in
            print(error!)
        })
    }

}

यह स्पष्ट रूप से काम करता है अगर छवि में जीपीएस मेटा सूचनाएं हैं

आशा करता हूँ की ये काम करेगा


यह ऐसा कुछ है जो सार्वजनिक एपीआई प्रदान नहीं करता है, लेकिन कई लोगों के लिए उपयोगी हो सकता है। आपका प्राथमिक सहारा ऐप्पल के साथ एक बग फाइल करना है जो आपको बताता है कि आपको क्या चाहिए (और यह समझाने में सहायक हो सकता है कि आपको इसकी आवश्यकता क्यों है)। उम्मीद है कि आपका अनुरोध इसे भविष्य में रिलीज में ला सकता है।

एक बग दर्ज करने के बाद, आप अपने आईफोन डेवलपर प्रोग्राम सदस्यता के साथ आए डेवलपर तकनीकी सहायता (डीटीएस) घटनाओं में से एक का भी उपयोग कर सकते हैं। यदि ऐसा करने का कोई सार्वजनिक तरीका है, तो एक ऐप्पल इंजीनियर को पता चलेगा। अन्यथा, कम से कम आपकी दुर्दशा मातृत्व के भीतर थोड़ा अधिक ध्यान देने में मदद कर सकती है। शुभकामनाएँ!


यह स्विफ्ट 3 में है यदि आप अभी भी आईओएस 8 के लिए समर्थन चाहते हैं:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {

  id thumbnailView = [[[[[[[[[[picker.view subviews] 
                  objectAtIndex:0] subviews]
                  objectAtIndex:0] subviews]
                objectAtIndex:0] subviews]
                objectAtIndex:0] subviews]
              objectAtIndex:0];

  NSString *fullSizePath = [[[thumbnailView selectedPhoto] fileGroup] pathForFullSizeImage];
  NSString *thumbnailPath = [[[thumbnailView selectedPhoto] fileGroup] pathForThumbnailFile];

  NSLog(@"%@ and %@", fullSizePath, thumbnailPath);

}




exif