Saving Geotag info with photo on iOS4.1

后端 未结 6 1330
旧时难觅i
旧时难觅i 2020-12-01 03:21

I am having major issues trying to save a photo to camera roll with geotag info on iOS4.1. I am using following ALAssetsLibrary API:

- (void)writeImageDataTo         


        
相关标签:
6条回答
  • 2020-12-01 03:40

    Here is code to copy all available information from a CLLocation object into the proper format for a GPS metadata dictionary:

    - (NSDictionary *)getGPSDictionaryForLocation:(CLLocation *)location {
        NSMutableDictionary *gps = [NSMutableDictionary dictionary];
    
        // GPS tag version
        [gps setObject:@"2.2.0.0" forKey:(NSString *)kCGImagePropertyGPSVersion];
    
        // Time and date must be provided as strings, not as an NSDate object
        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
        [formatter setDateFormat:@"HH:mm:ss.SSSSSS"];
        [formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
        [gps setObject:[formatter stringFromDate:location.timestamp] forKey:(NSString *)kCGImagePropertyGPSTimeStamp];
        [formatter setDateFormat:@"yyyy:MM:dd"];
        [gps setObject:[formatter stringFromDate:location.timestamp] forKey:(NSString *)kCGImagePropertyGPSDateStamp];
        [formatter release];
    
        // Latitude
        CGFloat latitude = location.coordinate.latitude;
        if (latitude < 0) {
            latitude = -latitude;
            [gps setObject:@"S" forKey:(NSString *)kCGImagePropertyGPSLatitudeRef];
        } else {
            [gps setObject:@"N" forKey:(NSString *)kCGImagePropertyGPSLatitudeRef];
        }
        [gps setObject:[NSNumber numberWithFloat:latitude] forKey:(NSString *)kCGImagePropertyGPSLatitude];
    
        // Longitude
        CGFloat longitude = location.coordinate.longitude;
        if (longitude < 0) {
            longitude = -longitude;
            [gps setObject:@"W" forKey:(NSString *)kCGImagePropertyGPSLongitudeRef];
        } else {
            [gps setObject:@"E" forKey:(NSString *)kCGImagePropertyGPSLongitudeRef];
        }
        [gps setObject:[NSNumber numberWithFloat:longitude] forKey:(NSString *)kCGImagePropertyGPSLongitude];
    
        // Altitude
        CGFloat altitude = location.altitude;
        if (!isnan(altitude)){
            if (altitude < 0) {
                altitude = -altitude;
                [gps setObject:@"1" forKey:(NSString *)kCGImagePropertyGPSAltitudeRef];
            } else {
                [gps setObject:@"0" forKey:(NSString *)kCGImagePropertyGPSAltitudeRef];
            }
            [gps setObject:[NSNumber numberWithFloat:altitude] forKey:(NSString *)kCGImagePropertyGPSAltitude];
        }
    
        // Speed, must be converted from m/s to km/h
        if (location.speed >= 0){
            [gps setObject:@"K" forKey:(NSString *)kCGImagePropertyGPSSpeedRef];
            [gps setObject:[NSNumber numberWithFloat:location.speed*3.6] forKey:(NSString *)kCGImagePropertyGPSSpeed];
        }
    
        // Heading
        if (location.course >= 0){
            [gps setObject:@"T" forKey:(NSString *)kCGImagePropertyGPSTrackRef];
            [gps setObject:[NSNumber numberWithFloat:location.course] forKey:(NSString *)kCGImagePropertyGPSTrack];
        }
    
        return gps;
    }
    

    Assign the dictionary returned by this method as the value for the kCGImagePropertyGPSDictionary key in the metadata dictionary you pass to writeImageDataToSavedPhotosAlbum:metadata:completionBlock: or CGImageDestinationAddImage().

    0 讨论(0)
  • 2020-12-01 03:41

    Anomie's response in Swift 4.0:

    func getGPSDictionaryForLocation(location:CLLocation) -> [String:AnyObject] {
    
        var gps = [String:AnyObject]()
    
        var latitude = location.coordinate.latitude
    
        if(latitude < 0){
            latitude = -latitude
            gps[kCGImagePropertyGPSLatitudeRef as String] = "S" as AnyObject
    
        }else{
            gps[kCGImagePropertyGPSLatitudeRef as String] = "N" as AnyObject
        }
    
        gps[kCGImagePropertyGPSLatitude as String] = latitude as AnyObject
    
    
        var longitude = location.coordinate.longitude
    
        if(longitude < 0){
            longitude = -longitude
            gps[kCGImagePropertyGPSLongitudeRef as String] = "W" as AnyObject
        }else{
            gps[kCGImagePropertyGPSLongitudeRef as String] = "E" as AnyObject
        }
    
        gps[kCGImagePropertyGPSLongitude as String] = longitude as AnyObject
    
        gps[kCGImagePropertyGPSAltitude as String] = location.altitude as AnyObject
    
        return gps
    }
    
    0 讨论(0)
  • 2020-12-01 03:42

    I used this code and created a NSMutableDictionary to help save geotag and other metadata to an image. Check out my blog post here:

    http://blog.codecropper.com/2011/05/adding-metadata-to-ios-images-the-easy-way/

    0 讨论(0)
  • 2020-12-01 03:42

    After much searching I found and adapted this

    This turns cclocation data into a suitable NSDictionary

     #import <ImageIO/ImageIO.h>
    
    +(NSMutableDictionary *)updateExif:(CLLocation *)currentLocation{
    
    
        NSMutableDictionary* locDict = [[NSMutableDictionary alloc] init];
    
    
        CLLocationDegrees exifLatitude = currentLocation.coordinate.latitude;
        CLLocationDegrees exifLongitude = currentLocation.coordinate.longitude;
    
        [locDict setObject:currentLocation.timestamp forKey:(NSString*)kCGImagePropertyGPSTimeStamp];
    
        if (exifLatitude <0.0){
            exifLatitude = exifLatitude*(-1);
            [locDict setObject:@"S" forKey:(NSString*)kCGImagePropertyGPSLatitudeRef];
        }else{
            [locDict setObject:@"N" forKey:(NSString*)kCGImagePropertyGPSLatitudeRef];
        }
        [locDict setObject:[NSNumber numberWithFloat:exifLatitude] forKey:(NSString*)kCGImagePropertyGPSLatitude];
    
        if (exifLongitude <0.0){
            exifLongitude=exifLongitude*(-1);
            [locDict setObject:@"W" forKey:(NSString*)kCGImagePropertyGPSLongitudeRef];
        }else{
            [locDict setObject:@"E" forKey:(NSString*)kCGImagePropertyGPSLongitudeRef];
        }
        [locDict setObject:[NSNumber numberWithFloat:exifLongitude] forKey:(NSString*) kCGImagePropertyGPSLongitude];
    
    
        return [locDict autorelease];
    
    }
    

    Then I add it to the existing metadata that you get through the camera (which doesn't by default have the gps data)

    I get the original metadata like this

    -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{  
        [imageMetaData setDictionary:[[info objectForKey:UIImagePickerControllerMediaMetadata] copy]];
    }
    

    then I add the gps dictionary the previous method produces.

    [imageMetaData setObject:currentLocation forKey:(NSString*)kCGImagePropertyGPSDictionary];          
    
        [library writeImageToSavedPhotosAlbum:[viewImage CGImage] metadata:imageMetaData completionBlock:photoCompblock];   
    
    0 讨论(0)
  • 2020-12-01 03:47

    Class to Write GPS Data to Meta-Data.

    class GeoTagImage {
    
      /// Writes GPS data into the meta data.
      /// - Parameters:
      ///   - data: Coordinate meta data will be written to the copy of this data.
      ///   - coordinate: Cooordinates to write to meta data.
      static func mark(_ data: Data, with coordinate: Coordinate) -> Data {
        var source: CGImageSource? = nil
        source = CGImageSourceCreateWithData((data as CFData?)!, nil)
        // Get all the metadata in the image
        let metadata = CGImageSourceCopyPropertiesAtIndex(source!, 0, nil) as? [AnyHashable: Any]
        // Make the metadata dictionary mutable so we can add properties to it
        var metadataAsMutable = metadata
        var EXIFDictionary = (metadataAsMutable?[(kCGImagePropertyExifDictionary as String)]) as? [AnyHashable: Any]
        var GPSDictionary = (metadataAsMutable?[(kCGImagePropertyGPSDictionary as String)]) as? [AnyHashable: Any]
    
        if !(EXIFDictionary != nil) {
          // If the image does not have an EXIF dictionary (not all images do), then create one.
          EXIFDictionary = [:]
        }
        if !(GPSDictionary != nil) {
          GPSDictionary = [:]
        }
    
        // add coordinates in the GPS Dictionary
        GPSDictionary![(kCGImagePropertyGPSLatitude as String)] = coordinate.latitude
        GPSDictionary![(kCGImagePropertyGPSLongitude as String)] = coordinate.longitude
        EXIFDictionary![(kCGImagePropertyExifUserComment as String)] = "Raw Image"
    
        // Add our modified EXIF data back into the image’s metadata
        metadataAsMutable!.updateValue(GPSDictionary!, forKey: kCGImagePropertyGPSDictionary)
        metadataAsMutable!.updateValue(EXIFDictionary!, forKey: kCGImagePropertyExifDictionary)
    
        // This is the type of image (e.g., public.jpeg)
        let UTI: CFString = CGImageSourceGetType(source!)!
    
        // This will be the data CGImageDestinationRef will write into
        let dest_data = NSMutableData()
        let destination: CGImageDestination = CGImageDestinationCreateWithData(dest_data as CFMutableData, UTI, 1, nil)!
        // Add the image contained in the image source to the destination, overidding the old metadata with our modified metadata
        CGImageDestinationAddImageFromSource(destination, source!, 0, (metadataAsMutable as CFDictionary?))
    
        // Tells the destination to write the image data and metadata into our data object.
        // It will return false if something goes wrong
        _ = CGImageDestinationFinalize(destination)
    
        return (dest_data as Data)
      }
    
      /// Prints the Meta Data from the Data.
      /// - Parameter data: Meta data will be printed of this object.
      static func logMetaData(from data: Data) {
        if let imageSource = CGImageSourceCreateWithData(data as CFData, nil) {
          let imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil)
          if let dict = imageProperties as? [String: Any] {
            print(dict)
          }
        }
      }
    }
    
    0 讨论(0)
  • 2020-12-01 04:03

    Here's a handy CLLocation category on gist to do all this for you:

    https://gist.github.com/phildow/6043486

    0 讨论(0)
提交回复
热议问题