After i took a photo with the camera i save the image with the following code:
UIImageWriteToSavedPhotosAlbum(image, self,"image:didFinishSavingWithError:contextInfo:", nil)
This saves the image in the camera roll. Additionally i want to save the URL to this saved image in Core Data. Is it possible to retrieve the URL (or the Path) to so that i only need to save this URL and not the full image in Core Data?
After reading a lot of answers written in ObjectivC i finally figured out how to write this in Swift with Xcode 6.2:
ALAssetsLibrary().writeImageToSavedPhotosAlbum(image.CGImage, orientation: ALAssetOrientation(rawValue: image.imageOrientation.rawValue)!,
completionBlock:{ (path:NSURL!, error:NSError!) -> Void in
println("\(path)")
})
Here is my combination..
Saving Image :
let imageData = NSData(data:UIImagePNGRepresentation(pickedimage))
let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
var docs: String = paths[0] as! String
let fullPath = docs.stringByAppendingPathComponent("yourNameImg.png")
let result = imageData.writeToFile(fullPath, atomically: true)
print(fullPath)
Get Image:
let nsDocumentDirectory = NSSearchPathDirectory.DocumentDirectory
let nsUserDomainMask = NSSearchPathDomainMask.UserDomainMask
if let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
{
if paths.count > 0
{
if let dirPath = paths[0] as? String
{
let readPath = dirPath.stringByAppendingPathComponent("yourNameImg.png")
let image = UIImage(contentsOfFile: readPath)
UploadImagePreview.image = image
}
}
}
We can try with Photos Framework to fetch the last saved image.
var fetchOptions: PHFetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
var fetchResult = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: fetchOptions)
if (fetchResult.firstObject != nil) {
var lastAsset: PHAsset = fetchResult.lastObject as! PHAsset
PHImageManager.defaultManager().requestImageForAsset(lastAsset, targetSize: self.UploadImagePreview.bounds.size, contentMode: PHImageContentMode.AspectFill, options: PHImageRequestOptions(), resultHandler: { (result, info) -> Void in
self.UploadImagePreview.image = result
})
}
Related
I am working on UICollectionView fetching gallery images and shown in UICollectionViewCell but i need to shown all images within one single folder.
Is there any solution for this?
You can try this way.Below code is fetch the "Repost" folder from gallery and fetch all the photos of it.
func getImages() {
image = []
let albumName = "Repost" //album name
let fetchOptions = PHFetchOptions()
var assetCollection = PHAssetCollection()
fetchOptions.predicate = NSPredicate(format: "title = %#", albumName)
let collection:PHFetchResult = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
if let _:AnyObject = collection.firstObject{
//found the album
assetCollection = collection.firstObject!
albumFound = true
}
else { albumFound = false
print("album not found")
}
let assets = PHAsset.fetchAssets(in: assetCollection, options: nil) as! PHFetchResult<AnyObject>
assets.enumerateObjects({ (object, count, stop) in
// self.cameraAssets.add(object)
if object.mediaType == .image
{
self.image.append(object as! PHAsset) // for image
}
})
self.image.reverse()
self.imgcollection.reloadData()
}
Don't forgot to import photos framework.
Thanks.
In case you are still struggling to figure out here is the code snippet, good luck
func saveImageToDocumentDirectory(image: UIImage ) {
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileName = "image001.png" // name of the image to be saved
let fileURL = documentsDirectory.appendingPathComponent(fileName)
if let data = UIImageJPEGRepresentation(image, 1.0),!FileManager.default.fileExists(atPath: fileURL.path) {
do {
try data.write(to: fileURL)
print("file saved")
} catch {
print("error saving file:", error)
}
}
}
func loadImageFromDocumentDirectory(nameOfImage : String) -> UIImage {
let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
if let dirPath = paths.first {
let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(nameOfImage)
let image = UIImage(contentsOfFile: imageURL.path)
return image!
}
return UIImage.init(named: "default.png")!
}
I tried to fetch all images from album. It fetches all images with their URL's and image data, but it does not fetch images directly from given URL path, So I need to download images in Document Directory and then get path. So it's taking too much time. I use below code. I want fetch images like iPhone photos library fetches.
Please find error.
func fatchImagesfromAlbum() {
DispatchQueue.global(qos: .background).async {
self.photoAssets = self.fetchResult as! PHFetchResult<AnyObject>
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.image.rawValue)
self.photoAssets = PHAsset.fetchAssets(in: self.assetCollection, options: fetchOptions) as! PHFetchResult<AnyObject>
for i in 0..<self.photoAssets.count{
autoreleasepool {
let asset = self.photoAssets.object(at: i)
let imageSize = CGSize(width: asset.pixelWidth,
height: asset.pixelHeight)
let options = PHImageRequestOptions()
options.deliveryMode = .fastFormat
options.isSynchronous = true
options.isNetworkAccessAllowed = true
self.imageManager.requestImage(for: asset as! PHAsset, targetSize: imageSize, contentMode: .aspectFill, options: options, resultHandler: { (image, info) -> Void in
if image != nil {
let image1 = image as! UIImage
let imageUrl = info!["PHImageFileURLKey"] as? NSURL
let imageName = imageUrl?.lastPathComponent
let urlString: String = imageUrl!.path!
let theFileName = (urlString as NSString).lastPathComponent
self.imageName.append("\(theFileName)")
self.imagePath.append("\(urlString)")
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let photoURL = NSURL(fileURLWithPath: documentDirectory)
let localPath = photoURL.appendingPathComponent(imageName!)
DispatchQueue.global(qos: .background).async {
if !FileManager.default.fileExists(atPath: localPath!.path) {
do {
try UIImageJPEGRepresentation(image1, 0.1)?.write(to: localPath!)
print("file saved")
}catch {
print("error saving file")
}
}
else {
print("file already exists")
}
}
}
})
DispatchQueue.main.async
{
self.collectionView.reloadData()
}
}
}
self.hudHide()
}
PHPhotoLibrary.shared().register(self)
if fetchResult == nil {
let allPhotosOptions = PHFetchOptions()
allPhotosOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
fetchResult = PHAsset.fetchAssets(with: allPhotosOptions)
}
}
I recommend simply using UIImagePickerController or if your app requires multiple image selection functionality, a third-party library like DKImagePickerController. As another user already mentioned in the comments, these will only copy the image(s) the user selected into your app's directory and save on processing time.
Am creating an application for image share related things. Here my requirement is I have to store some custom information(Name, PhoneNumber, Price) into the Image Metadata and retrieve it back.
I use UIImagePickerController to capture the image and set my information into the image metadata in UIImagePickerControllerDelegate like below mentioned:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
picker.dismiss(animated: true, completion: nil)
let profileImage = info[UIImagePickerControllerOriginalImage] as? UIImage
let imageData: Data = UIImageJPEGRepresentation(profileImage!, 1)!
let cgImgSource: CGImageSource = CGImageSourceCreateWithData(imageData as CFData, nil)!
let uti: CFString = CGImageSourceGetType(cgImgSource)!
let dataWithExif: NSMutableData = NSMutableData(data: imageData)
let destination: CGImageDestination = CGImageDestinationCreateWithData((dataWithExif as CFMutableData), uti, 1, nil)!
let imageProoperties = CGImageSourceCopyPropertiesAtIndex(cgImgSource, 0, nil)! as NSDictionary
let mutable: NSMutableDictionary = imageProoperties.mutableCopy() as! NSMutableDictionary
let EXIFDictionary: NSMutableDictionary = (mutable[kCGImagePropertyExifDictionary as String] as? NSMutableDictionary)!
print("Before Modification: \(EXIFDictionary)")
EXIFDictionary[kCGImagePropertyExifUserComment as String] = "\(self.m_NameTxtFd.text!):\(self.m_PhoneNumberTxtFd.text!):\(self.m_PriceTxtFd.text!)"
mutable[kCGImagePropertyExifDictionary as String] = EXIFDictionary
CGImageDestinationAddImageFromSource(destination, cgImgSource, 0, (mutable as CFDictionary))
CGImageDestinationFinalize(destination)
let testImage: CIImage = CIImage(data: dataWithExif as Data, options: nil)!
let newProperties: NSDictionary = testImage.properties as NSDictionary
print("After Modification : \(newProperties)") //Here I Got My Information is Stored Successfully
self.m_ImgView.image = self.convert(cmage: testImage)
self.saveImageDocumentDirectory()
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
Now am going to save the image in NSDocumentDirectory like below mentioned:
func saveImageDocumentDirectory(){
let fileManager = FileManager.default
let paths = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("apple.jpg")
let image = self.m_ImgView.image
print(paths)
let imageData = UIImageJPEGRepresentation(image!, 0.5)
fileManager.createFile(atPath: paths as String, contents: imageData, attributes: nil)
}
Now am going to fetch the stored image in another view controller like below mentioned:
func getImage(){
let fileManager = FileManager.default
let imagePAth = (self.getDirectoryPath() as NSString).appendingPathComponent("apple.jpg")
print(imagePAth)
if fileManager.fileExists(atPath: imagePAth){
self.m_ImgView.image = UIImage(contentsOfFile: imagePAth)
self.fetchImageDetails()
}else{
print("No Image")
}
}
I successfully got the image and now I have to fetch the information from image metadata like below mentioned:
func fetchImageDetails() {
let profileImage = self.m_ImgView.image!
let ciImage: CIImage = CIImage(cgImage: profileImage.cgImage!)
let newProperties: NSDictionary = ciImage.properties as NSDictionary
}
But issue is the information is null in image property.
Please guide me to retrieve the custom information from stored Image.
First create NSMutableDictionary and set value to NSMutableDictionary when you set value to then you don't need to set again to metadata you directly assign to NSMutableDictionary to Metada.
let metadata = info[UIImagePickerControllerMediaMetadata] as? NSMutableDictionary
let exifData = NSMutableDictionary()
let metaStr = "\(self.m_NameTxtFd.text!),\(self.m_PhoneNumberTxtFd.text!),\(self.m_PriceTxtFd.text!)"
exifData.setValue(metaStr, forKey: kCGImagePropertyExifDictionary as String)
metadata = exifData
fileManager.requestImageData(for: fetchResult.object(at: i) as PHAsset, options: requestOptions, resultHandler: { (imagedata, dataUTI, orientation, info ) in
if let info = info {
if info.keys.contains(NSString(string: "PHImageFileURLKey")) {
path = info[NSString(string: "PHImageFileURLKey")] as? NSURL
size = (imagedata! as NSData).length
self.name = PHAssetResource.assetResources(for:fetchResult.object(at: i)).first?.originalFilename
self.imageData = imagedata
}
}
})
I am trying to display an image from the local library in another view using its url like so...
let myImgObj = messagesFromTheDisk[indexPath.row].images
print(myImgObj)
print(myImgObj[0].url)
Printing myImgObj gives [MyApp.ProductImage(url: assets-library://asset/asset.PNG?id=A636DA16-8C7C-4CC5-ADB3-E944DC24BDA1&ext=PNG)] and printing myImgObj[0].url gives assets-library://asset/asset.PNG?id=A636DA16-8C7C-4CC5-ADB3-E944DC24BDA1&ext=PNG
But when I try to show display this image its showing as null though there seems to be an url. I'm using the library SDWebImage to display the image like so...
cell.productImageView.sd_setImage(with: myImgObj[0].url, placeholderImage:UIImage(named: "sampleImg"))
What am I doing wrong...?
I set the image libary url nil and use the contentsOfFile to not catche the images in the disk so that immediate loading of images will be implemented and it works.However you must put the images not in .xcassettes folder but a separate group folder.
let bundlePath = Bundle.main.path(forResource: myImgObj, ofType: "jpg")
imageView.sd_setImage(with: nil, placeholderImage: UIImage(contentsOfFile: bundlePath!))
This is without SDWebImage as I don't it need for PHAssets. I am fetching assests from library from my custom album like this :
func fetchCustomAlbumPhotos( completion : (_ array : [PHAsset]) -> Void)
{
var assetCollection = PHAssetCollection()
var photoAssets = PHFetchResult<AnyObject>()
var arrayOfPHAsset = [PHAsset]()
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %#", CustomAlbum.albumName)
let collection:PHFetchResult = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
if let _:AnyObject = collection.firstObject{
assetCollection = collection.firstObject!
}else {
completion([])
}
_ = collection.count
photoAssets = PHAsset.fetchAssets(in: assetCollection, options: nil) as! PHFetchResult<AnyObject>
photoAssets.enumerateObjects({(object: AnyObject!,
count: Int,
stop: UnsafeMutablePointer<ObjCBool>) in
if object is PHAsset{
let asset = object as! PHAsset
arrayOfPHAsset.append(asset)
}
})
completion(arrayOfPHAsset)
}
This is how I call it in my ViewController's viewDidLoad() method:
CustomAlbum().fetchCustomAlbumPhotos { (array) in
self.arrayOfPHAsset = array
self.collectionView.reloadData()
}
From that function i get arrayOfPHAsset and this is how I am displaying them in my collection view cellForItemAt method:
let asset : PHAsset = arrayOfPHAsset[indexPath.item]
Or convert your url to PHAsset
self.imageURL = (info[UIImagePickerControllerReferenceURL] as? NSURL)!
let asset = PHAsset.fetchAssetsWithALAssetURLs([imageUrl], options: nil).firstObject as! PHAsset
And request Image for that PHAsset
if asset.mediaType == .video{
cell.videoIndicatorImage.isHidden = false
}
cell.userImagesStoredInAlbum.alpha = 0
let imageSize = CGSize(width: asset.pixelWidth,height: asset.pixelHeight)
DispatchQueue.main.async {
PHImageManager.default().requestImage(for: asset, targetSize: imageSize, contentMode: .aspectFill, options: nil, resultHandler: {(result, info)in
if result != nil {
cell.userImagesStoredInAlbum.image = result
UIView .animate(withDuration: 0.5, delay: 0, options: .curveEaseIn, animations: {
cell.userImagesStoredInAlbum.alpha = 1
}, completion: { (succes) in
})
}
})
}
I am using the documents directory of my application to cache images locally, but when I go to access them, they are not updated until I close the app and reopen.
Here is my save:
var readPath = ""
let nsDocumentDirectory = NSSearchPathDirectory.DocumentDirectory
let nsUserDomainMask = NSSearchPathDomainMask.UserDomainMask
if let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true) {
if paths.count > 0 {
if let dirPath = paths[0] as? String {
readPath = dirPath.stringByAppendingPathComponent("\(user).png")
UIImagePNGRepresentation(imageView.image).writeToFile(readPath, atomically: true)
}
}
}
Here is my retrieval:
var readPath = ""
let nsDocumentDirectory = NSSearchPathDirectory.DocumentDirectory
let nsUserDomainMask = NSSearchPathDomainMask.UserDomainMask
if let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true) {
if paths.count > 0 {
if let dirPath = paths[0] as? String {
readPath = dirPath.stringByAppendingPathComponent("\(user).png")
//UIImagePNGRepresentation(imageView.image).writeToFile(readPath, atomically: true)
}
}
}
let cachedImage = UIImage(named: readPath)
if (cachedImage != nil)
{
println("cached")
self.userPictures.append(cachedImage!)
}
For some reason though, it is not until I have reset the application that these resources become available.
Can anyone shed some light on why this could be?
The image that gets returned to cachedImage is an image that I had previously saved into that specific path btw
This may helps you....
let fileManager = NSFileManager.defaultManager()
var paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as! String
var getImagePath = paths.stringByAppendingPathComponent("\(fileName).png")
if (fileManager.fileExistsAtPath(getImagePath))
{
println("FILE AVAILABLE");
//Pick Image and Use accordingly
var imageis: UIImage = UIImage(contentsOfFile: getImagePath)!
self.image = imageis // UIImageView Class
let datas: NSData = UIImagePNGRepresentation(imageis)
}
else
{
println("FILE NOT AVAILABLE");
let getImage = UIImage(data: self.data)
self.image = getImage
var filePathToWrite = "\(paths)/\(fileName).png"
var imageData: NSData = UIImagePNGRepresentation(self.image)
fileManager.createFileAtPath(filePathToWrite, contents: imageData, attributes: nil)
}
Check the Project in Github