如何使用 AVCapturePhoto 包含位置数据?

DJF*_*iar 3 xcode avfoundation cllocationmanager ios swift

我正在尝试用 Swift 编写一个 iOS 应用程序,让用户拍照,然后我将在图像上叠加一些额外的数据。我希望图像包含位置数据。我正在使用 AVCapturePhoto,我可以在文档中看到它有一些元数据变量,但我找不到有关如何使用它们的任何信息。当我现在用我的应用拍照时,它的 EXIF 信息中没有位置数据。

如何设置捕获会话以嵌入位置数据?

ada*_*oto 5

我还没有处理过新的 IOS 11 AVCapturePhoto 对象,所以这个答案必须对如何访问数据做出一些假设,但理论上所有这些都应该有效。

在添加位置数据之前,您需要询问用户是否可以使用他们的位置。将“隐私 - 使用时的位置”标签添加到您的 Info.plist。然后在初始化中的某处添加以下代码。

// Request authorization for location manager 
switch CLLocationManager.authorizationStatus() {
case .authorizedWhenInUse:
    break

case .notDetermined:
    locationManager.requestWhenInUseAuthorization()
    locationManagerStatus = CLLocationManager.authorizationStatus()

default:
    locationManagerStatus = .denied
}
Run Code Online (Sandbox Code Playgroud)

现在下面将创建一个包含位置信息的字典。

// create GPS metadata properties
func createLocationMetadata() -> NSMutableDictionary? {

    guard CLLocationManager.authorizationStatus() == .authorizedWhenInUse else {return nil}

    if let location = locationManager.location {
        let gpsDictionary = NSMutableDictionary()
        var latitude = location.coordinate.latitude
        var longitude = location.coordinate.longitude
        var altitude = location.altitude
        var latitudeRef = "N"
        var longitudeRef = "E"
        var altitudeRef = 0

        if latitude < 0.0 {
            latitude = -latitude
            latitudeRef = "S"
        }

        if longitude < 0.0 {
            longitude = -longitude
            longitudeRef = "W"
        }

        if altitude < 0.0 {
            altitude = -altitude
            altitudeRef = 1
        }

        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy:MM:dd"
        gpsDictionary[kCGImagePropertyGPSDateStamp] = formatter.string(from:location.timestamp)
        formatter.dateFormat = "HH:mm:ss"
        gpsDictionary[kCGImagePropertyGPSTimeStamp] = formatter.string(from:location.timestamp)
        gpsDictionary[kCGImagePropertyGPSLatitudeRef] = latitudeRef
        gpsDictionary[kCGImagePropertyGPSLatitude] = latitude
        gpsDictionary[kCGImagePropertyGPSLongitudeRef] = longitudeRef
        gpsDictionary[kCGImagePropertyGPSLongitude] = longitude
        gpsDictionary[kCGImagePropertyGPSDOP] = location.horizontalAccuracy
        gpsDictionary[kCGImagePropertyGPSAltitudeRef] = altitudeRef
        gpsDictionary[kCGImagePropertyGPSAltitude] = altitude

        if let heading = locationManager.heading {
            gpsDictionary[kCGImagePropertyGPSImgDirectionRef] = "T"
            gpsDictionary[kCGImagePropertyGPSImgDirection] = heading.trueHeading
        }

        return gpsDictionary;
    }
    return nil
}
Run Code Online (Sandbox Code Playgroud)

这是我必须做一些猜测的地方,因为我还没有处理过 IOS 11 AVPhotoCapture。您将需要图像数据的文件数据表示。我假设

AVCapturePhoto.fileDataRepresentation() 
Run Code Online (Sandbox Code Playgroud)

返回这个。您还需要原始文件元数据。我猜猜

AVCapturePhoto.metadata
Run Code Online (Sandbox Code Playgroud)

包含这个。有了这些假设,以下函数将为您提供带有附加位置数据的文件数据表示。可能会有更新的 IOS 11 方法以更简洁的方式执行此操作。

func getFileRepresentationWithLocationData(photo : AVCapturePhoto) -> Data {
    // get image metadata
    var properties = photo.metadata

    // add gps data to metadata
    if let gpsDictionary = createLocationMetadata() {
        properties[kCGImagePropertyGPSDictionary as String] = gpsDictionary
    }

    // create new file representation with edited metadata
    return photo.fileDataRepresentation(withReplacementMetadata:properties,
        replacementEmbeddedThumbnailPhotoFormat:photo.embeddedThumbnailPhotoFormat,
        replacementEmbeddedThumbnailPixelBuffer:photo.previewPixelBuffer,
        replacementDepthData:photo.depthData)
}
Run Code Online (Sandbox Code Playgroud)