2016-06-23 30 views
5

IOS Uygulamamdaki görüntüleri seçmek için UIImagePickerController kullanıyorum ve exif bilgisinin info [UIImagePickerControllerMediaMetadata] tarafından alınabileceğini biliyorum. Ama görüntüyü UIImage tarafından sunucuma yüklediğimde, exif bilgisinin çoğu çizgili. Http isteğimde (resim bundan sonra jpg olarak yüklendi) resmime exif bilgisi ekleyip eklememeyi merak ediyorum. Eğer değilse, bu sorunu nasıl çözmeliyim? Ben değişiklik yapmak istiyorum, Model nitelikleriniSwift mobil kameradan çekilen resimlerdeki exif bilgilerini nasıl değiştiririm?

Aşağıda benim kod parçacıkları (diğer bir deyişle, hangi cihazı bu resim çekmek için kullanılmıştır):

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

Bu konuda herhangi bir güncelleme var mı? Bunu yapmak için basit bir yol bulamıyorum. – jonmecer

cevap

2

Evet! Sonunda EXIF ​​bilgisini değiştirmek için bir numara yaptım. İlk olarak, UIImageJPEGRepresentation tarafından seçilen UIImage'den EXIF ​​olmadan bilgi [UIImagePickerControllerMediaMetadata] ve NSData EXIF ​​bilgi alabilirsiniz. Daha sonra, değiştirilmiş EXIF ​​bilgisi içeren yeni bir NSDictionary oluşturabilirsiniz. Bundan sonra, aşağıdaki işlevimi çağırın, değiştirilmiş EXIF ​​ile görüntü NSData alabilirsiniz! durumda

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

Eğer EXIF ​​meta verileri güncelleştirmek için bir yol var bir video yakalama ve CMSampleBuffer alıyoruz. iOS10 içinde DataTimeOriginal zaten olsa iOS9 benim durumumda kullanarak. Böylece birkaç ek anahtar değerlerini koymak zorunda kaldı.,

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

Bu yöntemi denedim, ancak rawMetadata'm sıfırdır. Bu, AVCapturePhotoOutput'tan görüntü verileri üzerinde çalışır mı? –

+0

http://stackoverflow.com/questions/43489623/geotag-images-from-image-picker-swift-3 bunu da yapabilir misiniz? –

1

DateTimeOriginal alamadım ve diğer yayınlardan bazı bilgiler mergind, Swift dilinde Sözlük kullanarak problemle karşılaştım. Ben AVCapturePhoto için AVFounfation geri arama captureOutput kullanmış: yani "metadataAttachments" sonrasında

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 
    } 

} 

son görüntüyü (benim durumumda CGImageDestinationAddImage kullanarak) İşe görünüyor

oluşturmak için kullanılan (bir proje oluşturmaya çalıştı Swift ile 4.0)

Umut yardımcı olabilir!

İlgili konular