I'm trying to save a GIF from URL to Camera Roll with the following code:
var image = UIImage(data: NSData(contentsOfURL: self.imageView.sd_imageURL())!)
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
but after saving, the GIF become a still image, anyone can help me?
Thanks!
You can save GIF via PHPhotoLibrary
PHPhotoLibrary.shared().performChanges({
let request = PHAssetCreationRequest.forAsset()
request.addResource(with: .photo, fileURL: YOUR_GIF_URL, options: nil)
}) { (success, error) in
if let error = error {
completion(.failure(error))
} else {
completion(.success(true))
}
}
Try this:
import AssetsLibrary
let image = NSData(contentsOfURL: url)
ALAssetsLibrary().writeImageDataToSavedPhotosAlbum(image, metadata: nil, completionBlock: { (assetURL: NSURL!, error: NSError!) -> Void in
print(assetURL)
})
Related
I have a portrait image with depth data with it and after some processing, I want to save a copy of it to a user photo album with depth data preserved (UIImage not an option in this case). For this task, I am using the function writeJPEGRepresentation() which seems to successfully save the modified image with the depth info to somewhere; however, it does not show up on the photo album.
In order it to appear on the photo album, I when try performChanges() function of PHPhotoLibrary,
this time it appeared on the album, but not the modified but the original one!?
Any help highly appreciated. Thanks.
Here is the code:
func saveWithDepth(image : CIImage) {
do {
let colorSpace = CGColorSpace(name: CGColorSpace.sRGB)
let depthdata = DepthData
let url = Url
try Context.writeJPEGRepresentation(of: image, to: url!, colorSpace: colorSpace!,
options: [CIImageRepresentationOption.avDepthData :depthdata!])
PHPhotoLibrary.shared().performChanges({
let options = PHAssetResourceCreationOptions()
let creationRequest = PHAssetCreationRequest.forAsset()
creationRequest.addResource(with: .alternatePhoto, fileURL: url!, options: options)
}, completionHandler: { success, error in
if !success {
print("AVCam couldn't save the movie to your photo library: \(String(describing: error))")
}
})
} catch {
print("failed")
}
}
I think the problem is that JPEG can't store depth data (as far as I know). HEIF would be the format you should use for that. Maybe you can try something like this:
func saveWithDepth(image: CIImage) {
let colorSpace = CGColorSpace(name: CGColorSpace.sRGB)
let depthdata: DepthData
let imageData = context.heifRepresentation(of: image, format: .BGRA8, colorSpace: colorSpace!,
options: [CIImageRepresentationOption.avDepthData: depthdata!])
PHPhotoLibrary.shared().performChanges({
let options = PHAssetResourceCreationOptions()
let creationRequest = PHAssetCreationRequest.forAsset()
creationRequest.addResource(with: .photo, data: imageData, options: options)
}, completionHandler: { success, error in
if !success {
print("Couldn't save the photo to your photo library: \(String(describing: error))")
}
})
}
A few remarks:
I assume depthdata is actually a meaningful value?
You can create and later pass the image data directly to the creationRequest. Then you don't need to save a file to some intermediate location (which you would need to delete afterward).
I am new to swift. I am loading image with url
mainImageView.setImageWith(URL(string: ("https:" + (content?.imagePath)!)), placeholderImage: nil)
print("dimensions after loading \(String(describing: mainImageView.image?.size))")
In case, I print the dimensions of the image as shown above then dimensions come out to be 21*6.5. However, if I wait for sometime and then print the dimensions are 188*109. How do I add a completion block to setImageWith so that I can come to know when image has finished loading?
You can use Sdwebimage for loading the image with completion block https://github.com/rs/SDWebImage
imageView.sd_setImageWithURL(NSURL(string: urlString), completed: {
(image, error, cacheType, url) in
// you can get the image width here...
})
It is happening because URL will always take a time to load image thats why first you got 21*6.5 dimensions and then got real dimensions 188*109.
As best way to prefer 3rd party library SDWebImage that will manage all the thing, You just need to set image URL.
There is method name is
open func sd_setImage(with url: URL!, placeholderImage placeholder: UIImage!, options: SDWebImageOptions = [], completed completedBlock: SDWebImage.SDWebImageCompletionBlock!)
that has completion block so you can manage whatever you want.
Convert image URL into data then Data into UIIamge, Here is a function:
func getImageFromUrl(_ strUrl: String, completionHandler handler: #escaping (_ img: UIImage) -> Void) {
DispatchQueue.global(qos: .background).async {
let url = URL(string: strUrl)
let dataFromUrl = Data(contentsOf: url!)
if dataFromUrl == nil {
return
}
DispatchQueue.main.async(execute: {() -> Void in
handler(UIImage(data: dataFromUrl!))
})
})
}
Use This: -
let imageCache = NSCache<AnyObject, AnyObject>()
typealias CompletionHandler = (_ success:Bool, _ image:UIImage?) -> Void
func loadImageUsingCacheWithUrlString(_ urlString:
String,completionHandler: #escaping CompletionHandler) {
let image = UIImage()
//check cache for image first
if let cachedImage = imageCache.object(forKey: urlString as AnyObject) as? UIImage {
image = cachedImage
completionHandler(true, image!)
return
}
if urlString.characters.count == 0 {
completionHandler(false, image)
return
}
//otherwise fire off a new download
let url = URL(string: urlString)
URLSession.shared.dataTask(with: url!, completionHandler: { (data, response, error) in
//download hit an error so lets return out
if error != nil {
print(error ?? "")
completionHandler(false,nil)
return
}
DispatchQueue.main.async(execute: {
if let downloadedImage = UIImage(data: data!) {
image = downloadedImage
imageCache.setObject(downloadedImage, forKey: urlString as AnyObject)
completionHandler(true,image)
}
})
}).resume()
}
appName[8121:97068] 8121: CFNetwork internal error (0xc01a:/BuildRoot/Library/Caches/com.apple.xbs/Sources/CFNetwork_Sim/CFNetwork-808.2.16/Loading/URLConnectionLoader.cpp:304)
I have a chat app, and I want to send an image to others.
I: IPhone ; others: simulator
I take a photo by camera, and press "use this photo",then I'll send an url to others and upload image to server.
Others receive url message immediately, and I use sdWebimage to show this image.
But,when I receive the image, the image request print log error.
log say this image don't exist.
I dont know make this image download error,whether the image is uploading and the server don't have this image or not.
How can prevent this situation or have any function to set download again after 10 seconds of downloading error ?
this is my sd_image func:
cell.photoImageView.sd_setImage(with: url, placeholderImage: nil, options: .progressiveDownload, progress: nil
, completed: { (image, error, cacheType, url) in
guard image != nil else{
print("Image not exist!")
cell.photoImageView.image = resizeImage(image:#imageLiteral(resourceName: "img_refresh"), newWidth: 125)
return
}
print("image here!!!")
DispatchQueue.global().async {
let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
if data != nil
{
if let image = UIImage(data: data!)
{
if !FileManager.default.fileExists(atPath: fileURL.path) {
if let jpegData = UIImageJPEGRepresentation(image, 0.001)
{
do {
try jpegData.write(to: fileURL, options: .atomic)
print("image save local done!!!")
} catch {
debug(object: error)
}
}
} else {
print("image already esist")
}
DispatchQueue.main.async {
cell.photoImageView.image = resizeImage(image: image, newWidth: 175)
self.tableView.reloadRows(at: [indexPath], with: .automatic)
}
}
}
}
})
uploading
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let uuid = NSUUID().uuidString
let imageName:String = chatroomId + "_" + uuid + ".jpg"
let documentsPath = NSHomeDirectory().appending("/Documents/\(chatroomId)/")
let imagePath = documentsPath.appending(imageName)
let imageUrl = URL(fileURLWithPath: imagePath)
print("imageUrl is here:\(imageUrl)")
photoImage = info[UIImagePickerControllerOriginalImage] as? UIImage
if picker.sourceType == .camera {
photoImage = info[UIImagePickerControllerOriginalImage] as? UIImage
UIImageWriteToSavedPhotosAlbum(photoImage!, nil, nil, nil)
}
let imageData:Data = UIImageJPEGRepresentation(photoImage!, 0.001)!
do {
try imageData.write(to: imageUrl,options: .atomic)
} catch let error {
print(error)
}
//uploading
let objectKey:String = "chatroom/" + imageName
server.uploadObjectAsync(imageUrl, objectKey: objectKey)
let message = server.url + imageName
self.room.send(message: message)
self.tableView.scrollToBottom()
self.tableView.reloadData()
self.dismiss(animated: true, completion: nil)
}
try to add .allowInvalidSSLCertificates to your sd_setImage function :
cell.photoImageView.sd_setImage(with: url, placeholderImage: nil, options: .allowInvalidSSLCertificates, progress: nil
, completed: { (image, error, cacheType, url) in
Hi all I'm using ALAssetsLibrary to write videos/images to the album.
But XCode is telling me that ALAssetsLibrary is deprecated and I need to use PHPhotoLibrary, which is all well and good but there are no examples or documentation of how to make this transition.
Can anyone show me how to change this code to use PHPHotoLibrary?
let data:NSData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer)
let image:UIImage = UIImage( data: data)!
let library:ALAssetsLibrary = ALAssetsLibrary()
let orientation: ALAssetOrientation = ALAssetOrientation(rawValue: image.imageOrientation.rawValue)!
library.writeImageToSavedPhotosAlbum(image.CGImage, orientation: orientation, completionBlock: nil)
and for video:
ALAssetsLibrary().writeVideoAtPathToSavedPhotosAlbum(outputFileURL, completionBlock: {
(assetURL:NSURL!, error:NSError!) in
if error != nil{
print(error)
}
do {
try NSFileManager.defaultManager().removeItemAtURL(outputFileURL)
} catch _ {
}
if backgroundRecordId != UIBackgroundTaskInvalid {
UIApplication.sharedApplication().endBackgroundTask(backgroundRecordId)
}
})
Saving image:
PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.creationRequestForAsset(from: image)
}, completionHandler: { (success, error) in
// completion callback
})
Video:
PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: mediaUrl as URL)
}, completionHandler: { (success, error) in
// completion callback
})
Now that AssetsLibrary has been deprecated, we're supposed to use the photos framework, specifically PHPhotoLibrary to save images and videos to a users camera roll.
Using ReactiveCocoa, such a request would look like:
func saveImageAsAsset(url: NSURL) -> SignalProducer<String, NSError> {
return SignalProducer { observer, disposable in
var imageIdentifier: String?
PHPhotoLibrary.sharedPhotoLibrary().performChanges({
let changeRequest = PHAssetChangeRequest.creationRequestForAssetFromImageAtFileURL(url)
let placeholder = changeRequest?.placeholderForCreatedAsset
imageIdentifier = placeholder?.localIdentifier
}, completionHandler: { success, error in
if let identifier = imageIdentifier where success {
observer.sendNext(identifier)
} else if let error = error {
observer.sendFailed(error)
return
}
observer.sendCompleted()
})
}
}
I created a gif from a video using Regift and I can verify that the gif exists inside my temporary directory. However when I go save that gif to the camera roll, I get a mysterious error: NSCocoaErrorDomain -1 (null), which is really super helpful.
Has anyone ever experienced this issue?
You can try this.
let data = try? Data(contentsOf: /*Your-File-URL-Path*/)
PHPhotoLibrary.shared().performChanges({
PHAssetCreationRequest.forAsset().addResource(with: .photo, data: data!, options: nil)
})