2016-06-23 3 views
5

UIImagePickerController를 사용하여 내 iOS 앱에서 이미지를 선택하고 exif 정보가 정보 [UIImagePickerControllerMediaMetadata]를 통해 얻을 수 있음을 알고 있습니다. 그러나 UIImage에서 내 이미지를 내 서버에 업로드하면 대부분의 exif 정보가 스트라이프됩니다. HTTP 요청 (이미지는 jpg로 업로드 한 후)에서 내 이미지에 exif 정보를 추가 할 수 있는지 궁금합니다. 그렇지 않다면이 문제를 어떻게 해결해야합니까? 내가 변경 만들기 싶어, 모델 속성휴대 전화에서 가져온 이미지에서 exif 정보를 수정하는 방법

아래는 내 코드 조각을 (즉, 어떤 장치는이 사진을 촬영 하였다) :

func Tapped() { 
    let myPickerController = UIImagePickerController() 

    myPickerController.delegate = self 
    myPickerController.sourceType = UIImagePickerControllerSourceType.Camera 
    myPickerController.allowsEditing = false 
    self.presentViewController(myPickerController, animated: true, completion: nil) 
} 
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) { 
    let image = info[UIImagePickerControllerOriginalImage] as? UIImage 
    myImageView.image = image 
    UIImageWriteToSavedPhotosAlbum(image!, self, #selector(ViewController.image(_:didFinishSavingWithError:contextInfo:)), nil) 
    self.dismissViewControllerAnimated(true, completion: nil) 
} 

func myImageUploadRequest() 
{ 

    let myUrl = NSURL(string: "http://XXXXXX/Uploadfile") 

    let request = NSMutableURLRequest(URL:myUrl!) 
    request.HTTPMethod = "POST" 

    let param = [ 
     "userId" : "7" 
    ] 

    let boundary = generateBoundaryString() 

    request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type") 


    let imageData = UIImageJPEGRepresentation(myImageView.image!, 1) 

    if(imageData == nil) { return; } 

    request.HTTPBody = createBodyWithParameters(param, filePathKey: "file", imageDataKey: imageData!, boundary: boundary) 



    myActivityIndicator.startAnimating() 

    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { 
     data, response, error in 

     if error != nil { 
      print("error=\(error)") 
      return 
     } 

     // You can print out response object 
     print("******* response = \(response)") 

     // Print out response body 
     let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding) 
     print("****** response data = \(responseString!)") 

     do{ 
      let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSDictionary 

     }catch{ 
      print(error) 
     } 


     dispatch_async(dispatch_get_main_queue(),{ 
      self.myActivityIndicator.stopAnimating() 
      self.myImageView.image = nil 
     }) 

    } 

    task.resume() 
} 

func createBodyWithParameters(parameters: [String: String]?, filePathKey: String?, imageDataKey: NSData, boundary: String) -> NSData { 
    let body = NSMutableData(); 

    if parameters != nil { 
     for (key, value) in parameters! { 
      body.appendString("--\(boundary)\r\n") 
      body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n") 
      body.appendString("\(value)\r\n") 
     } 
    } 

    let filename = "test.jpg" 

    let mimetype = "image/jpg" 

    body.appendString("--\(boundary)\r\n") 
    body.appendString("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n") 
    body.appendString("Content-Type: \(mimetype)\r\n\r\n") 
    body.appendData(imageDataKey) 
    body.appendString("\r\n") 



    body.appendString("--\(boundary)--\r\n") 

    return body 
} 

func generateBoundaryString() -> String { 
    return "Boundary-\(NSUUID().UUIDString)" 
} 

extension NSMutableData { 

func appendString(string: String) { 
    let data = string.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true) 
    appendData(data!) 
} 
} 
+0

이 항목에 대한 최신 정보가 있습니까? 나는 또한 이것을하는 간단한 방법을 찾을 수 없다. – jonmecer

답변

2

예! 마지막으로 EXIF ​​정보를 수정하는 트릭을 만들었습니다. 처음에는 UIImageJPEGRepresentation에 의해 선택된 UIImage에서 EXIF ​​정보없이 info [UIImagePickerControllerMediaMetadata] 및 NSData에서 EXIF ​​정보를 얻을 수 있습니다. 그런 다음 수정 된 EXIF ​​정보로 새 NSDictionary를 만들 수 있습니다. 그 후, 다음에서 내 함수를 호출하면 수정 된 EXIF로 이미지 NSData를 얻을 수 있습니다! 경우

func saveImageWithImageData(data: NSData, properties: NSDictionary, completion: (data: NSData, path: NSURL) -> Void) { 

    let imageRef: CGImageSourceRef = CGImageSourceCreateWithData((data as CFDataRef), nil)! 
    let uti: CFString = CGImageSourceGetType(imageRef)! 
    let dataWithEXIF: NSMutableData = NSMutableData(data: data) 
    let destination: CGImageDestinationRef = CGImageDestinationCreateWithData((dataWithEXIF as CFMutableDataRef), uti, 1, nil)! 

    CGImageDestinationAddImageFromSource(destination, imageRef, 0, (properties as CFDictionaryRef)) 
    CGImageDestinationFinalize(destination) 

    var paths: [AnyObject] = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) 
    let savePath: String = paths[0].stringByAppendingPathComponent("exif.jpg") 

    let manager: NSFileManager = NSFileManager.defaultManager() 
    manager.createFileAtPath(savePath, contents: dataWithEXIF, attributes: nil) 

    completion(data: dataWithEXIF,path: NSURL(string: savePath)!) 

    print("image with EXIF info converting to NSData: Done! Ready to upload! ") 

} 
0

SWIFT 3

당신은 EXIF ​​메타 데이터를 업데이트하는 방법이 비디오를 캡처하고 CMSampleBuffer을 받고 있습니다. iOS10에 DataTimeOriginal가 이미 있었지만 iOS9에서 내 경우에는 내가 사용. 따라서 나는에 몇 가지 추가 키 - 값을 넣어했다.,

self.stillCameraOutput.captureStillImageAsynchronously(from: connectionVideo) { (sampleBuffer, err) in 
     if let err = err { 
      blockCompletion(nil, err as NSError?) 
     } 
     else { 
      if let sampleBuffer = sampleBuffer { 
       let rawMetadata = CMCopyDictionaryOfAttachments(nil, sampleBuffer, CMAttachmentMode(kCMAttachmentMode_ShouldPropagate)) 
       let metadata = CFDictionaryCreateMutableCopy(nil, 0, rawMetadata) as NSMutableDictionary 

       let exifData = metadata.value(forKey: "{Exif}") as? NSMutableDictionary 

       print("EXIF DATA: \(exifData)") 

       if let dateTime = exifData?["DateTimeOriginal"] as? String { 
        print("DateTime exists \(dateTime)") 
       } 
       else { 
        exifData?.setValue(Date().exifDate(), forKey: "DateTimeOriginal") 
       } 

       if let dateTime = exifData?["DateTimeDigitized"] as? String { 
        print("DateTime exists \(dateTime)") 
       } 
       else { 
        exifData?.setValue(Date().exifDate(), forKey: "DateTimeDigitized") 
       } 

       metadata.setValue(exifData, forKey: "{Exif}") 

       CMSetAttachments(sampleBuffer, metadata as CFDictionary, CMAttachmentMode(kCMAttachmentMode_ShouldPropagate)) 

       let rawMetadata2 = CMCopyDictionaryOfAttachments(nil, sampleBuffer, CMAttachmentMode(kCMAttachmentMode_ShouldPropagate)) 
       let metadata2 = CFDictionaryCreateMutableCopy(nil, 0, rawMetadata2) as NSMutableDictionary 

       let exifData2 = metadata2.value(forKey: "{Exif}") as? NSMutableDictionary 

       print("EXIF DATA: \(exifData2)") 

       if let dataImage = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer) { 
        blockCompletion(dataImage, nil) 
       } 
       else { 
        blockCompletion(nil, nil) 
       } 
      } 
      else { 
       blockCompletion(nil, nil) 
      } 
     } 
    } 
+0

이 방법을 시도했지만 rawMetadata는 0입니다. 이것은 AVCapturePhotoOutput의 이미지 데이터에서 작동합니까? –

+0

http://stackoverflow.com/questions/43489623/geotag-images-from-image-picker-swift-3 당신도이 문제를 해결할 수 있습니까? –

1

을시 날짜를 못해서 다른 게시물에서 약간의 정보를 mergind, 스위프트에서 사전을 사용하여 문제에 접근했습니다. 내가 AVCapturePhoto에 대한 AVFounfation 콜백의 captureOutput에서 사용 : 그 "metadataAttachments"후

func photoOutput(_ output: AVCapturePhotoOutput, 
       didFinishProcessingPhoto photo: AVCapturePhoto, 
       error: Error?) { 

    //retrieve exif information 
    var photoFormatDescription: CMFormatDescription? 
    CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, photoPixelBuffer, &photoFormatDescription) 

    var metadataAttachments: Dictionary = photo.metadata as Dictionary 

    if var exifData = metadataAttachments["{Exif}"] as? [String: Any] { 
     exifData[kCGImagePropertyExifUserComment as String] = "<whatever you want to write>" 

    metadataAttachments[kCGImagePropertyExifDictionary as String] = exifData 
    } 

} 

최종 이미지 (내 경우 CGImageDestinationAddImage를 사용하여) 작동하는 것 같다

을 구축하는 데 사용됩니다 (프로젝트 빌드 시도 Swift 4.0)

희망이 있습니다.

관련 문제