复制使用UiimagePicker选择的照片和元数据,并带有修改的Exif Metadata的新照片

发布于 2025-01-20 07:02:26 字数 221 浏览 3 评论 0原文

我希望能够使用 UIImagePicker 从照片库中选择一张照片,并将所有图像(带有修改后的 Exif 元数据)复制到我保存在“照片”中的新照片中。如果我使用 UIActivityViewController 选择保存选项(从复制/保存/分配到联系人/打印/添加到共享相册/保存到文件),则当我从加载的图像数据创建新的 UIimage 时,不会传输输入图像元数据修改后的元数据。如何获取附加到已保存照片的修改过的元数据的图像?

I would like to be able to select a photo from the Photos library using UIImagePicker and copy all the image (with modified Exif metadata) to a new photo which I save in Photos. If I use UIActivityViewController to choose the save option (from copy/save/assign to contact/print/add to shared album/save to file), the input image metadata is not transferred when I create a new UIimage from the loaded image data with the modified metadata. How can get the image with modified metadata attached to the saved photo?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

忆梦 2025-01-27 07:02:26

最终找到了如何做到这一点。图像选择器之后执行的代码如下。重要的是创建从 URL 提取元数据的源,而不是从 image.jpegData 的数据中提取元数据。 jpegData 选项仅包含 JPEG 操作必需的元数据

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

     let info = convertFromUIImagePickerControllerInfoKeyDictionary(info)

    if let image = info[convertFromUIImagePickerControllerInfoKey(UIImagePickerController.InfoKey.originalImage)] as? UIImage {

        let url  = info[UIImagePickerController.InfoKey.imageURL.rawValue]
       
        let source = CGImageSourceCreateWithURL(url as! CFURL, nil)
      
        let metadata = CGImageSourceCopyPropertiesAtIndex(source!,0,nil) as? [AnyHashable: Any]
        var metadataAsMutable = metadata
        //let ImagePropertyExifDictionary = kCGImagePropertyExifDictionary
        
        guard var exif = metadataAsMutable![kCGImagePropertyExifDictionary] as? [String:Any] else {return}
        if((exif[kCGImagePropertyExifUserComment as String] == nil))
        {
        exif[kCGImagePropertyExifUserComment as String] = "Test User Comment"
        }
        metadataAsMutable![kCGImagePropertyExifDictionary] = exif as CFDictionary
        
       ImagePickerView.contentMode = .scaleAspectFit

        let image2 = image.imageWithInsets(insets: UIEdgeInsets.init(top: 0,left: 0,bottom: 300,right: 0))
        let data1 = image2!.jpegData(compressionQuality: 1.0)
        newData = addImageProperties(imageData: data1!, properties: metadataAsMutable! as CFDictionary)
        image3 = UIImage(data:newData)!
        
        ImagePickerView.image = image3

        captionButton.isEnabled = true; saveButton.isEnabled = true;
        
    }else {
        print("Error")
    }
    self.dismiss(animated: true, completion: nil)

}

func addImageProperties(imageData: Data, properties: NSMutableDictionary) -> Data? {
  
 if let source = CGImageSourceCreateWithData(imageData as CFData, nil) {
  if let uti = CGImageSourceGetType(source) {
      let destinationData = NSMutableData()
      if let destination = CGImageDestinationCreateWithData(destinationData, uti, 1, nil) {
      CGImageDestinationAddImageFromSource(destination, source, 0, properties)
      if CGImageDestinationFinalize(destination) == false {
      return nil
    }                    
    return destinationData as Data
  }
}

}
返回零
获取newData

后,保存按钮IBAction为,

@IBAction func shareAction(_ sender: Any) {
        self.saveImageDataAsImage(newData)
 }

将图片保存到与所选图片同一个相册的函数为

 func saveImageDataAsImage(_ data: Data) {
    var newImageIdentifier: String!

    PHPhotoLibrary.shared().performChanges{
        //if #available(iOS 9.0, *) {
            let assetRequest = PHAssetCreationRequest.forAsset()
            assetRequest.addResource(with: .photo, data: data, options: nil)
            newImageIdentifier = assetRequest.placeholderForCreatedAsset!.localIdentifier
//            } else {
//                // Fallback on earlier versions
//            }
    } completionHandler: { (success, error) in
        DispatchQueue.main.async(execute: {
            if success, let newAsset = PHAsset.fetchAssets(withLocalIdentifiers: [newImageIdentifier], options: nil).firstObject {
                // ...
            } else {
                // ...
            }
        })

    }
}

Eventually found out how to do this. The code executed after the image picker is below. The important thing is to create the source from which the metadata is extracted from a URL, not from data from image.jpegData. The jpegData option only includes metadata essential to JPEG operation

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

     let info = convertFromUIImagePickerControllerInfoKeyDictionary(info)

    if let image = info[convertFromUIImagePickerControllerInfoKey(UIImagePickerController.InfoKey.originalImage)] as? UIImage {

        let url  = info[UIImagePickerController.InfoKey.imageURL.rawValue]
       
        let source = CGImageSourceCreateWithURL(url as! CFURL, nil)
      
        let metadata = CGImageSourceCopyPropertiesAtIndex(source!,0,nil) as? [AnyHashable: Any]
        var metadataAsMutable = metadata
        //let ImagePropertyExifDictionary = kCGImagePropertyExifDictionary
        
        guard var exif = metadataAsMutable![kCGImagePropertyExifDictionary] as? [String:Any] else {return}
        if((exif[kCGImagePropertyExifUserComment as String] == nil))
        {
        exif[kCGImagePropertyExifUserComment as String] = "Test User Comment"
        }
        metadataAsMutable![kCGImagePropertyExifDictionary] = exif as CFDictionary
        
       ImagePickerView.contentMode = .scaleAspectFit

        let image2 = image.imageWithInsets(insets: UIEdgeInsets.init(top: 0,left: 0,bottom: 300,right: 0))
        let data1 = image2!.jpegData(compressionQuality: 1.0)
        newData = addImageProperties(imageData: data1!, properties: metadataAsMutable! as CFDictionary)
        image3 = UIImage(data:newData)!
        
        ImagePickerView.image = image3

        captionButton.isEnabled = true; saveButton.isEnabled = true;
        
    }else {
        print("Error")
    }
    self.dismiss(animated: true, completion: nil)

}

func addImageProperties(imageData: Data, properties: NSMutableDictionary) -> Data? {
  
 if let source = CGImageSourceCreateWithData(imageData as CFData, nil) {
  if let uti = CGImageSourceGetType(source) {
      let destinationData = NSMutableData()
      if let destination = CGImageDestinationCreateWithData(destinationData, uti, 1, nil) {
      CGImageDestinationAddImageFromSource(destination, source, 0, properties)
      if CGImageDestinationFinalize(destination) == false {
      return nil
    }                    
    return destinationData as Data
  }
}

}
return nil
}

After obtaining newData, the save button IBAction is

@IBAction func shareAction(_ sender: Any) {
        self.saveImageDataAsImage(newData)
 }

and the function to save the image in the same album as the selected image is

 func saveImageDataAsImage(_ data: Data) {
    var newImageIdentifier: String!

    PHPhotoLibrary.shared().performChanges{
        //if #available(iOS 9.0, *) {
            let assetRequest = PHAssetCreationRequest.forAsset()
            assetRequest.addResource(with: .photo, data: data, options: nil)
            newImageIdentifier = assetRequest.placeholderForCreatedAsset!.localIdentifier
//            } else {
//                // Fallback on earlier versions
//            }
    } completionHandler: { (success, error) in
        DispatchQueue.main.async(execute: {
            if success, let newAsset = PHAsset.fetchAssets(withLocalIdentifiers: [newImageIdentifier], options: nil).firstObject {
                // ...
            } else {
                // ...
            }
        })

    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文