文件访问相机胶卷上的图像文件(iOS 12.1.4,Swift 4.2,Xcode 10.1)

时间:2019-03-05 07:35:14

标签: swift xcode url camera

我试图用内置相机拍照后为JPEG个文件(例如MD5)计算文件哈希。我可以在图像数据上创建摘要,但这与实际的文件哈希不同。在查看Photo模块及其PHAsset类时,我没有找到一种方法来检索实际的文件路径(URL),然后可以将其馈送到MD5Digest。通过实现完成侦听器功能,也许可以在将图像保存到相机胶卷之后立即捕获文件URL。有人尝试过吗?

使用completionHandler更新了代码,但是我仍然需要查找URL。

 @IBOutlet weak var imageHash: UILabel!

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

    let orgPic = info[UIImagePickerController.InfoKey.originalImage] as? UIImage

    UIImageWriteToSavedPhotosAlbum(orgPic!, self, #selector(imageSaved(_:didFinishSavingWithError:contextInfo:)), nil)

}

@objc func imageSaved(_ img: UIImage, didFinishSavingWithError error: NSError?, contextInfo: UnsafeRawPointer) {
        if let error = error {
            // we got back an error!
            let ac = UIAlertController(title: "Save error", message: error.localizedDescription, preferredStyle: .alert)
            ac.addAction(UIAlertAction(title: "OK", style: .default))
            present(ac, animated: true)
        } else {
            let ac = UIAlertController(title: "Saved!", message: "\(img.ciImage?.url)", preferredStyle: .alert)
            ac.addAction(UIAlertAction(title: "OK", style: .default))
            present(ac, animated: true)
        }
 }

// the img.ciImage.url is "nil" unfortunately

2 个答案:

答案 0 :(得分:0)

因此,您的主要座右铭是比较2个Image文件的MD5。所以这是我尝试过的,也许会对您有所帮助

; TLDR-保存在“库”中的文件与实际文件对我不匹配

 public func saveImgToLocal(_ img: UIImage,
                           onComplete: @escaping () -> Void) {

    var blockPlaceholder: PHObjectPlaceholder?
    var changeRequest: PHAssetChangeRequest?

    PHPhotoLibrary.shared().performChanges({
        changeRequest =  PHAssetChangeRequest.creationRequestForAsset(from: img)
        blockPlaceholder = changeRequest?.placeholderForCreatedAsset
    }, completionHandler: { (saved, error) in
        //_saved_ is of type bool, you can use it to check whether image is saved
        //Here we would fetch the asset using our saved placeholder
        let fetchOptions = PHFetchOptions()
        let fetchResult:PHFetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [blockPlaceholder!.localIdentifier], options: fetchOptions)
        if let asset = fetchResult.firstObject {
            //Method to convert asset to Actual image
            self.getAsset(asset: asset)
        }
        onComplete()

    })
}

这就是我将图像保存到本地的方式

这就是我从本地获取图片的方式

func getAsset(asset: PHAsset)  {
    let manager = PHImageManager.default()
    let option = PHImageRequestOptions()
    var resultImage = UIImage()
    option.isSynchronous = true
    manager.requestImage(for: asset, targetSize: PHImageManagerMaximumSize, contentMode: .aspectFit, options: option, resultHandler: {(result, info)->Void in
        resultImage = result!
        let url = info!["PHImageFileURLKey"] as! NSURL
        //Image created using the file URL.
        let image = UIImage.init(contentsOfFile: url.path!)
//I even compared the resultImage instead of the image from the file
        if UIImagePNGRepresentation(image!) == UIImagePNGRepresentation(self.image!) {
            print("Same image")
        }
    })

}

因此,如果您只想找回保存的图像,可以这样做,但是我不确定图像是否按原样保存在照片库中。 HTH:-)

答案 1 :(得分:0)

尽管Ajinkya Sharma发布的代码可行,但我注意到与UIImageWriteToSavedPhotosAlbum相比,使用creationRequestForAsset将图像保存到相机胶卷的性能明显降低。因此,我选择了一种混合解决方案。我使用旧函数进行保存,然后使用PHAsset框架获取最新的图像文件并检索其URL。问题解决了。

public func saveImgToLocal(_ img: UIImage) {
    // significantly faster than creationRequestForAsset
    UIImageWriteToSavedPhotosAlbum(img, self, #selector(imageSaved(_:didFinishSavingWithError:contextInfo:)), nil)
}

@objc func imageSaved(_ img: UIImage, didFinishSavingWithError error: NSError?, contextInfo: UnsafeRawPointer) {
    if let error = error {
        // we got back an error!
        let ac = UIAlertController(title: "Save error", message: error.localizedDescription, preferredStyle: .alert)
        ac.addAction(UIAlertAction(title: "OK", style: .default))
        present(ac, animated: true)
    } else {
        let fetchOptions = PHFetchOptions()
        fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
        fetchOptions.fetchLimit = 1
        let fetchResult = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: fetchOptions)
        if let asset = fetchResult.firstObject
        {
            self.imageHash.text = getAsset(asset: asset)
        }
    }
}

func getAsset(asset: PHAsset) -> String {
    let manager = PHImageManager.default()
    let option = PHImageRequestOptions()
    var hashString = "" as String
    option.isSynchronous = true
    manager.requestImage(for: asset, targetSize: PHImageManagerMaximumSize, contentMode: .aspectFit, options: option, resultHandler: {(result, info) -> Void in
        let url = info!["PHImageFileURLKey"] as! NSURL
        do {
            let data = try Data(contentsOf: url as URL)
            hashString = data.md5.rawValue
        }
        catch {
            hashString = "Error computing hash"
        }
    })
    return hashString
}