I am writing a Mac app based on an iOS app. The code below converts a UIImage to NSData to upload to Parse.com.
I would like to do the same for Mac but I do not seem to be able to convert it to NSData. What should I be doing?
Thanks
var image = UIImage(named: "SmudgeInc")
let imageData = UIImagePNGRepresentation(image)
let imageFile = PFFile(name:"image.png", data:imageData)
You can use the NSImage property TIFFRepresentation to convert your NSImage to NSData:
let imageData = yourImage.TIFFRepresentation
If you need to save your image data to a PNG file you can use NSBitmapImageRep(data:) and representationUsingType to create an extension to help you convert Data to PNG format:
Update: Xcode 11 • Swift 5.1
extension NSBitmapImageRep {
var png: Data? { representation(using: .png, properties: [:]) }
}
extension Data {
var bitmap: NSBitmapImageRep? { NSBitmapImageRep(data: self) }
}
extension NSImage {
var png: Data? { tiffRepresentation?.bitmap?.png }
}
usage
let picture = NSImage(contentsOf: URL(string: "https://i.stack.imgur.com/Xs4RX.jpg")!)!
let imageURL = FileManager.default.urls(for: .desktopDirectory, in: .userDomainMask).first!.appendingPathComponent("image.png")
if let png = picture.png {
do {
try png.write(to: imageURL)
print("PNG image saved")
} catch {
print(error)
}
}
Related
I have UIImageView which is displaying GIF image, now I am unable to save GIF image into photo gallery.
I am using below swift code
guard let image = imageView.image else { return }
UIImageWriteToSavedPhotosAlbum(image,
self,
#selector(savedImage),
nil);
When I use above code it only save single image in photo gallery not saving as GIF.
Suggestion required, how to save GIF loaded from URL or available in the UIImageView into Gallery.
First your need to get all images of gif from imageView and the duration of the image, now you can generate the gif and save in document directory. Finally, save the file from URL to Photo Album
import ImageIO
import Photos
import MobileCoreServices
#IBAction func btnSaveGifFilePressed(_ sender: Any) {
if let imgs = self.imgView.image?.images, imgs.count > 0 {
var animationDuration = self.imgView.image?.duration ?? 1.0
animationDuration = animationDuration / Double(imgs.count);
let url = FileManager.default.urlForFile("lion.gif")
FileManager.default.createGIF(with: imgs, url: url, frameDelay: animationDuration)
PHPhotoLibrary.shared().performChanges ({
PHAssetChangeRequest.creationRequestForAssetFromImage(atFileURL: url)
}) { saved, error in
if saved {
print("Your image was successfully saved")
}
}
}
}
Create GIF using the following code.
func createGIF(with images: [UIImage], url: URL, frameDelay: Double) {
if let destinationGIF = CGImageDestinationCreateWithURL(url as CFURL, kUTTypeGIF, images.count, nil) {
let properties = [
(kCGImagePropertyGIFDictionary as String): [(kCGImagePropertyGIFDelayTime as String): frameDelay]
]
for img in images {
let cgImage = img.cgImage
CGImageDestinationAddImage(destinationGIF, cgImage!, properties as CFDictionary?)
}
CGImageDestinationFinalize(destinationGIF)
}
}
Get a URL in single line:
func urlForFile(_ fileName: String, folderName: String? = nil) -> URL {
var documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
if let folder = folderName {
documentsDirectory = documentsDirectory.appendingPathComponent(folder)
if !self.fileExists(atPath: documentsDirectory.path) {
try? self.createDirectory(atPath: documentsDirectory.path, withIntermediateDirectories: true, attributes: nil)
}
}
let fileURL = documentsDirectory.appendingPathComponent(fileName)
return fileURL;
}
I have this simply code to get an uiImage from Photo Library:
private func getDataOfMedia (asset:PHAsset) -> Data {
let requestOptions = PHImageRequestOptions()
requestOptions.isSynchronous = true
requestOptions.isNetworkAccessAllowed = true
let imgManager = PHImageManager.default()
var imgData = Data()
// Request Image
imgManager.requestImage(for: asset, targetSize: PHImageManagerMaximumSize, contentMode: .default, options: requestOptions) { (uiimage, info) in
if let uiimage = uiimage {
DispatchQueue.main.async {
if let imageData = uiimage.jpegData(compressionQuality: 1) {
imgData = imageData
}
}
}
}
return imgData
}
but, of course, I can't see the camera data, location data and exif data of the image saved from func getDataOfMedia(asset: asset), but if I download the same image directly from Photo, I can see camera data, location data and exif data.
How can I do to add camera data, location data and exif data to data that I have from requestimage of PHAsset?
How can I add the unique id, for example asset.localIdentifier, to know that I have download this image?
UPDATE
I managed to extract camera data, location data and exif data from an image from an asset object, with this code:
private func getDataOfImageC (asset:PHAsset, completion: #escaping (Data) -> Void) {
//For get exif data
let options = PHContentEditingInputRequestOptions()
options.isNetworkAccessAllowed = true //download asset metadata from iCloud if needed
asset.requestContentEditingInput(with: options) { (contentEditingInput: PHContentEditingInput?, _) -> Void in
let fullImage = CIImage(contentsOf: contentEditingInput!.fullSizeImageURL!)
let image = UIImage(ciImage: fullImage!)
print(fullImage!.properties)
for (key, value) in fullImage!.properties {
print("key: \(key) - value: \(value)")
}
completion(image.jpegData(compressionQuality: 1)!)
}
}
but turning CIImage to UIImage to Data format, to save it locally, it loses all camera data, location data and exif data.
I hope that someone help me.
After some study, this the code that work for me to save image (not video) from photoLibrary with all properties.
private func saveDataOfImageCI (asset:PHAsset, urlMedia: URL) {
//For get exif data
let options = PHContentEditingInputRequestOptions()
options.isNetworkAccessAllowed = true //download asset metadata from iCloud if needed
asset.requestContentEditingInput(with: options) { (contentEditingInput: PHContentEditingInput?, _) -> Void in
let url = contentEditingInput!.fullSizeImageURL!
let fullImage = CIImage(contentsOf: contentEditingInput!.fullSizeImageURL!)
do {
try CIContext().writeJPEGRepresentation(of: fullImage!,
to: urlMedia,
colorSpace: (fullImage?.colorSpace)!)
} catch {
print("error: \(error.localizedDescription)")
}
//To print properties data (exif, camera data, ....)
for (key, value) in fullImage!.properties {
print("key: \(key) - value: \(value)")
}
}
}
Sorry to ask such a simple but this is my first program in Swift... I try to create a NSImage from a NSData that contains a JPEG image I loaded from disk (URLs are in an array name choseFiles[]).
The compiler issues an error on the second and I'm stuck:'NSData' is not implicitly convertible to 'Data'; did you mean to use 'as' to explicitly convert?
Thank you
let imageAsNSData = NSData(contentsOf: chosenFiles[0]) // UIKit/UIImage for iOS not MacOS !
let imageAsNSImage = NSImage(data: imageAsNSData)
if (imageAsNSImage) {
// image could be created from NSData
//
} else {
// image could NOT be created from NSData
//
}
----- EDIT -----
I tried
let imageAsNSImage = NSImage(data: imageAsNSData! as Data)
if (imageAsNSImage != nil) {
which seems to work (at least for the compiler). Am I correct?
You can use swift Data to get your image:
do {
let imageData = try Data(contentsOf: chosenFiles[0])
NSImage(data: imageData)
} catch {
print("Unable to load data: \(error)")
}
Now in swift3 NSData is replaced by Data. When you are downloading image from url store it as Data not NSData.
imageView.image = NSImage.init(data: data! as Data)
I am going to save an image into the iphone device and read from it.
So I had written like this for this function.
/*
* save image to local device
*/
func saveImageToLocal(image: UIImage, fileName: String) {
if let data = UIImagePNGRepresentation(image) {
let filePath = self.getDocumentsDirectory().appendingPathComponent(fileName)
try? data.write(to: filePath, options: .atomic)
}
}
/*
* get image from local device
*/
func getImageFromLocal(fileName:String) -> UIImage? {
if let filePath = "\(self.getDocumentsDirectory())\(fileName)" as String! {
if let image = UIImage(contentsOfFile: filePath) {
return image
}
}
return nil
}
/*
* get document directory to save/read local file
*/
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}
But it didn't work correctly.
Which mistake do I have for this?
How can I implement this?
Regards.
You have the problem in getting filePath inside your getImageFromLocal(fileName:) -> UIImage? method. Change this according to your saveImageToLocal(image:) method as like below:
func getImageFromLocal(fileName:String) -> UIImage? {
let filePath = self.getDocumentsDirectory().appendingPathComponent(fileName)
if let image = UIImage(contentsOfFile: filePath.path) {
return image
}
return nil
}
I am trying to upload an UIImage to CloudKit in two steps:
get a file URL for my UIImage
get an CKAsset for my file URL
However, when debugging the CKAsset I create in the second step I noticed that the file path to my image doesn't exist and therefore CloudKit is unable to save the asset!
Here is my code:
// thumbnail is my UIImage
if let thumbnailURL = thumbnail.urlOf() {
self.thumbnailAsset = CKAsset(fileURL: thumbnailURL)
self.record["thumbnail"] = thumbnailAsset
} else {
NSLog("Could not create thumbnail asset!")
}
extension UIImage {
func urlOf() -> URL? {
do {
let imageData = UIImageJPEGRepresentation(self, 1)
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentDirectory = paths[0] as String
let myFilePath = NSURL(fileURLWithPath: documentDirectory).appendingPathComponent("thumbnail.jpg")
try imageData?.write(to: myFilePath!, options: .atomicWrite)
let url = myFilePath! as URL
return url
} catch {
NSLog("Could not save thumbnail to local directory!")
return nil
}
}
}
Any idea what is going on here? Is this a regression in beta 6 or is my code wrong?
Thanks for feedback!
-- Mark
Here some lldb statements:
(lldb) po thumbnailURL
▿ file:///Volumes/Work/Users/mark/Library/Developer/CoreSimulator/Devices/B1F9E45D-2A75-454F-AC56-37186428E833/data/Containers/Data/Application/E02EE6DF-17E4-4809-8978-339E76ED1EB3/Documents/picture
(lldb) po self.record["thumbnail"]
▿ Optional<CKRecordValue>
(lldb) po self.record["thumbnail"]!
<CKAsset: 0x6100001e8400; path=~/Documents/picture, UUID=BF838CB7-E828-4CD8-8517-911E25818088>