I am trying to save images in a directory. Images are correctly saved in the right place, but when I inspect these with the path in the finder, all the images are damaged and unsable.
damaged images
Below the static method:
static func writeImageFile(with data: Data, issue: Issue, page: Int, isThumbnail: Bool) throws -> URL {
let url = MediaFileManager.issueImagesDirectoryURL(issue: issue).ensuringDirectoryExists()
let imageURL = url.appendingPathComponent(imageName(for: page, isThumbnail: isThumbnail))
try data.write(to: imageURL)
return url
}
And the call in the class:
DispatchQueue.main.async {
guard let data = result.data else {
self.downloadDidFail(for: result.page)
return
}
do {
let writeImageFile = try MediaFileManager.writeImageFile(with: data, issue: self.issue, page: result.page, isThumbnail: false)
let writeThumbFile = try MediaFileManager.writeImageFile(with: data, issue: self.issue, page: result.page, isThumbnail: true)
print(writeImageFile)
print(writeThumbFile)
} catch let error as NSError {
print(error.localizedDescription)
}
}
I will assume, since you don't quite specify this, that you have a bunch of UIImage objects.
And I also noticed that you want your images to be saved as JPEG, which is no trouble at all, don't worry.
I would go with something like this:
if let image = UIImage(named: "example.png") {
if let data = UIImageJPEGRepresentation(image, 1.0) {
let filename = getDocumentsDirectory().appendingPathComponent("copy.png")
try? data.write(to: filename)
}
}
Where the func getDocumentsDirectory() is the following:
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return paths[0]
}
You might wonder why I used 1.0 for the second parameter in UIImageJPEGRepresentation, well that's the JPEG quality mapped between 0.0 and 1.0 (it's a float).
If you have any details that I am not aware of, please reply and I will try to help accordingly.
Hope it helps you, cheers!
Source: link
Have you tried to load the image to a UIImageView to see if the images are being properly downloaded? imageView.image = UIImage(data: data).
But I also detect that you're saving Data instead of the image, in order to make sure that you're saving an image I would try the following
static func writeImageFile(with data: Data, issue: Issue, page: Int, isThumbnail: Bool) throws -> URL {
let url = MediaFileManager.issueImagesDirectoryURL(issue: issue).ensuringDirectoryExists()
let imageURL = url.appendingPathComponent(imageName(for: page, isThumbnail: isThumbnail))
let image = UIImage(data: data)
let imgData = UIImageJPEGRepresentation(image, 1)
try imgData.write(to: imageURL)
return url
}
Yes, it might have unnecessary steps, worth trying, this way we're making sure that it's saved as Jpeg. But again, I would check if the images are being properly downloaded first.
Related
I'm trying to bridge React and Swift code by passing a string for an image path, which I've verified appears correctly on the Native side, and having a bit of an issue. The image path comes from React as NSString, and my goal is to pass that as a String to a Native function that will ultimately send data back to React.
Here's a snippet of some code that handles part of this
classifyImage(value as String)
and some of the body of the classifiyImage is as follows:
#objc func classifyImage(_ image: String) {
let imageData = Data(base64Encoded: image, options: .ignoreUnknownCharacters)!
let uiImage = UIImage(data: imageData)
guard let orientation = CGImagePropertyOrientation(
rawValue: UInt32((uiImage?.imageOrientation.rawValue)!)) else {
return
}
...code
}
The exact error is at the line with the rawVale, reading
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
Here's more info if it may help...
Image data can come from the camera as such image NSMutableString "file:///var/mobile/Containers/Data/Application/54691469-2196-444E-9B45-C0D6F2CABEBC/Library/Caches/Camera/EEC3631C-3E96-44DA-B258-411363A2F10C.jpg" 0x00000002815a8420
or from the phone's gallery image String "ph://8F109DC0-CE95-4D0A-9D11-1B2E9CE6B8D3/L0/001"
Image from a file
First, we need to turn the string into a URL, then the URL into data like so:
let url = URL(string: image)
do {
let data = try Data(contentsOf: url)
} catch {
print(e)
}
Then we can use it to create the image.
do {
let data = try Data(contentsOf: url)
let image = UIImage(data: data)
guard let orientation = CGImagePropertyOrientation(
rawValue: UInt32(image.imageOrientation.rawValue)) else {
print("that didn't work")
return
}
} catch {
print(e)
}
I have an image stored inside an AppGroup, but I'm unable to show the image and I'm not sure why.
I have this inside my view:
Image(uiImage: getImageFromDir(imageName: name)!)
.resizable()
I get the image using the following function:
func getImageFromDir(imageName: String) -> UIImage? {
let appGroupPath = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.myId")!
let imagePath = appGroupPath.appendingPathComponent(imageName)
do {
let imageData = try Data(contentsOf: imagePath)
return UIImage(data: imageData)
} catch {
print("Error loading image : \(error)")
}
return nil
}
This runs fine and the catch block is never hit, but the image still isn't visible. My initial thought was that I had an invalid path, but this doesn't seem the case since I can load the image as expected in React Native using the path.
There's also nothing wrong with my styles since a different image loaded from Assets.xcassets works fine.
Assuming the file is really existed at specified location (you can verify generated URL for that) try with security scoped resource wrapper, like below
func getImageFromDir(imageName: String) -> UIImage? {
let appGroupPath = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.myId")!
let imagePath = appGroupPath.appendingPathComponent(imageName)
do {
if imagePath.startAccessingSecurityScopedResource() { // << this !!
defer {
imagePath.stopAccessingSecurityScopedResource() // << and this !!
}
let imageData = try Data(contentsOf: imagePath)
return UIImage(data: imageData)
}
} catch {
print("Error loading image : \(error)")
}
return nil
}
While my solution is working, it is NOT a valid answer to why my images aren't showing and I would still like to know why, if anyone knows who comes across this post in the future.
To solve this, instead of using an absolute path to the image, I used a base64 string to use as the data. The image now succesfully shows.
i'm a baby of xcode developer, and i really need a help. Below is one of my json data, that i have print in output, for the text i already got display into my screen, but now i'm trying to get the image from the server, and i don't know how to do it.
JSON :
"MoviePhotoL" : "\/Data\/UploadFile\/cnymv-01_1.jpg",
"MoviePhotoP" : "\/Data\/UploadFile\/cnymv-02_1.jpg"
XCODE:
let userImage = iP["MoviePhotoP"] as? String
cell.imageView.image = userImage (??????)
i know that String cannot be converted into UIImage, and i already try to convert it to NSData and convert the NSData to UIImage(data), but still not get the picture :'(.... can somebody please help me?? i really need some help
Those paths seem relative to another source.
You need to generate or get an absolute URL that will let you access the image.
Right now you have a simple string and that's all, you can't convert this to data or image.
You need a string that you can put in a browser and load an image.
Once you're able to do that, you can load the image in your app.
Example:
func getImage(from string: String) -> UIImage? {
//2. Get valid URL
guard let url = URL(string: string)
else {
print("Unable to create URL")
return nil
}
var image: UIImage? = nil
do {
//3. Get valid data
let data = try Data(contentsOf: url, options: [])
//4. Make image
image = UIImage(data: data)
}
catch {
print(error.localizedDescription)
}
return image
}
//1. Get valid string
let string = "https://images.freeimages.com/images/large-previews/f2c/effi-1-1366221.jpg"
if let image = getImage(from: string) {
//5. Apply image
cell.imageView.image = image
}
NOTE: Data(contentsOf:options:) is synchronous and can reduce performance. The larger the image, the longer it will lock it's thread.
Generally you would do such intensive tasks in a background thread and update UI on the main thread, but... to keep this answer simple, I chose not to show that.
Now: i am uploading data and saving it to my public folder:
let info = req.data
guard let fileBytes = info["photo"]?.bytes
else {
var answerJson = JSON();
try answerJson.set("success", "false");
return answerJson
}
let dir = URL(fileURLWithPath: self.config.workDir).appendingPathComponent("Public/FleaMarketProductImages")
let dirWithImage = dir.appendingPathComponent("test3.jpg")
let fileManager = FileManager()
let data = Data(bytes: fileBytes)
fileManager.createFile(atPath: dirWithImage.path, contents: data, attributes: nil)
Then on device for downloaing this file i am doing next:
Alamofire.download(url).responseData { response in
if let data = response.result.value {
completionHandler(data)
}
}
I am getting some data, but when i do UIImage(data: data), i dont see my image. Where i did something wrong? Maybe there is another way to do it. And files in my public directory dont looks like image. They just files. Maybe do you know how to save it like an image????
The uploaded image will be one part of a multi-part request, so you need to use just the part that contains the image. .bytes will give you the whole request. I use:
guard let fileBytes = info.formData?["photo"]?.part.body
Or
guard let fileBytes = info?["photo"]?.part.body
if you aren't using a form.
I am trying to create an iOS Photo Extension which compresses images, and this is finishContentEditingWithCompletionHandler function:
func finishContentEditingWithCompletionHandler(completionHandler: ((PHContentEditingOutput!) -> Void)!) {
dispatch_async(dispatch_get_global_queue(CLong(DISPATCH_QUEUE_PRIORITY_DEFAULT), 0)) {
atomically: true)
let url = self.input?.fullSizeImageURL
if let imageUrl = url {
var fullImage = UIImage(contentsOfFile:
imageUrl.path!)
//Just compresses the image
let renderedJPEGData =
UIImageJPEGRepresentation(fullImage, self.comprestionRatioFloat)
var currentFilter = "FakeFilter"
renderedJPEGData.writeToURL(
output.renderedContentURL,
atomically: true)
let archivedData =
NSKeyedArchiver.archivedDataWithRootObject(
currentFilter)
output.adjustmentData = PHAdjustmentData(formatIdentifier:"MyApp.Ext", formatVersion:"1.0", data:archivedData)
}
completionHandler?(output)
// Clean up temporary files, etc.
}
}
When I test it on the device it says "Unable to Save Changes", Is there anything wrong?
Finally I've found out it's because the output image is almost the same as input. A little scaling down the output image fixed the problem.