How do I save a UIImage to a file? - iphone

If I have a UIImage from an imagePicker, how can I save it to a subfolder in the documents directory?

Of course you can create subfolders in the documents folder of your app. You use NSFileManager to do that.
You use UIImagePNGRepresentation to convert your image to NSData and save that to disk.
// Create path.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *filePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"Image.png"];
// Save image.
[UIImagePNGRepresentation(image) writeToFile:filePath atomically:YES];
Core Data has nothing to do with saving images to disk by the way.

In Swift 3:
// Create path.
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let filePath = "\(paths[0])/MyImageName.png"
// Save image.
UIImagePNGRepresentation(image)?.writeToFile(filePath, atomically: true)

You have to construct a representation of your image as a particular format (say, JPEG or PNG), and then call writeToFile:atomically: on the representation:
UIImage *image = ...;
NSString *path = ...;
[UIImageJPEGRepresentation(image, 1.0) writeToFile:path atomically:YES];

The above are useful, but they don't answer your question of how to save in a subdirectory or get the image from a UIImagePicker.
First, you must specify that your controller implements image picker's delegate, in either .m or .h code file, such as:
#interface CameraViewController () <UIImagePickerControllerDelegate>
#end
Then you implement the delegate's imagePickerController:didFinishPickingMediaWithInfo: method, which is where you can get the photograph from the image picker and save it (of course, you may have another class/object that handles the saving, but I'll just show the code inside the method):
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// get the captured image
UIImage *image = (UIImage *)info[UIImagePickerControllerOriginalImage];
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *imageSubdirectory = [documentsDirectory stringByAppendingPathComponent:#"MySubfolderName"];
NSString *filePath = [imageSubdirectory stringByAppendingPathComponent:#"MyImageName.png"];
// Convert UIImage object into NSData (a wrapper for a stream of bytes) formatted according to PNG spec
NSData *imageData = UIImagePNGRepresentation(image);
[imageData writeToFile:filePath atomically:YES];
}
If you want to save as JPEG image, the last 3 lines would be:
NSString *filePath = [imageSubdirectory stringByAppendingPathComponent:#"MyImageName.jpg"];
// Convert UIImage object into NSData (a wrapper for a stream of bytes) formatted according to JPG spec
NSData *imageData = UIImageJPEGRepresentation(image, 0.85f); // quality level 85%
[imageData writeToFile:filePath atomically:YES];

extension UIImage {
/// Save PNG in the Documents directory
func save(_ name: String) {
let path: String = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let url = URL(fileURLWithPath: path).appendingPathComponent(name)
try! UIImagePNGRepresentation(self)?.write(to: url)
print("saved image at \(url)")
}
}
// Usage: Saves file in the Documents directory
image.save("climate_model_2017.png")

NSData *imageData = UIImagePNGRepresentation(image);
[imageData writeToFile:path atomically:YES];
where path is the name of the file you want to write it to.

First you should get the Documents directory
/* create path to cache directory inside the application's Documents directory */
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *filePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"fileName"];
Then you should save the photo to the file
NSData *photoData = UIImageJPEGRepresentation(photoImage, 1);
[photoData writeToFile:filePath atomically:YES];

In Swift 4.2:
// Create path.
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
if let filePath = paths.first?.appendingPathComponent("MyImageName.png") {
// Save image.
do {
try image.pngData()?.write(to: filePath, options: .atomic)
} catch {
// Handle the error
}
}

In Swift 4:
// Create path.
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
if let filePath = paths.first?.appendingPathComponent("MyImageName.png") {
// Save image.
do {
try UIImagePNGRepresentation(image)?.write(to: filePath, options: .atomic)
}
catch {
// Handle the error
}
}

Related

Imageview image save in SQL database using URL in iOS

I want to save displayed UIImageview image in SQL database. I am capturing the image using the camera/albums/library which are displayed in UIImageview. I want to save this image in my SQL database using URL.
Also I need to display this image in another view.
How can I take a path(URL) of my imageview image? How can I store this path(URL) & also store & display into another view?
How to grab the UIImage and write to internal directory:
UIImageView *imageView = "[your image]";
// define your own path and storage for image
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentPath = [paths objectAtIndex:0];
documentPath = [documentPath stringByAppendingPathComponent:#"test.jpg"];
NSData *imageData = UIImageJPEGRepresentation(imageView.image, 1.0);
[imageData writeToFile:documentPath atomically:YES];
How to get the NSURL/NSString for a file path in internal directory:
// specify fileURL as it is an internal file, don't use URLWithString:
NSURL *fileURL = [NSURL fileURLWithPath:documentDirectory];
// store as a string in database
NSString *fileURLString = fileURL.path;
Please take note that the NSURL for local file is different with normal NSURL.
// for normal URL
NSURL *webURL = [NSURL URLWithString:"http://www.google.com/"];
[webURL absoluteString]; // -> http://www.google.com/
// for local file path URL
NSURL *localURL = [NSURL fileURLWithPath:"/User/path/samplefile.ext"];
[localURL absoluteString]; // -> file://User/path/samplefile.ext
[localURL path]; // -> /User/path/samplefile.ext
just save name of your image in database and store image in phone memory...it will be easy or this way try this line
UIImage *img = [UIImage imageWithContentsOfFile:(the file path)];
UIImageView *imgView = [[UIImageView alloc] initWithImage:img];

How to unzip a .zip file on iOS? [duplicate]

This question already has answers here:
unzip source code in Iphone
(2 answers)
Is there any zip decompression for iPhone?
(3 answers)
Closed 9 years ago.
After StoreKit downloads the IAP content package it returns an NSURL to me which looks like this:
file://localhost/private/var/mobile/Applications/45EF2B3A-3CAB-5A44-4B4A-631A122A4299/Library/Caches/BA32BC55-55DD-3AA4-B4AC-C2A456622229.zip/
Despite all sources I found claiming that StoreKit unzips the content package once downloaded, it hands me over a ZIP. This ZIP probably contains the file structure of the content package. But how do I unzip this?
Use Zip Foundation if you are working in Swift language. It's easy to use and one of the best swift library for unzipping a zip file.
Zip:
let fileManager = FileManager()
let currentWorkingPath = fileManager.currentDirectoryPath
var sourceURL = URL(fileURLWithPath: currentWorkingPath)
sourceURL.appendPathComponent("file.txt")
var destinationURL = URL(fileURLWithPath: currentWorkingPath)
destinationURL.appendPathComponent("archive.zip")
do {
try fileManager.zipItem(at: sourceURL, to: destinationURL)
} catch {
print("Creation of ZIP archive failed with error:\(error)")
}
UnZip:
let fileManager = FileManager()
let currentWorkingPath = fileManager.currentDirectoryPath
var sourceURL = URL(fileURLWithPath: currentWorkingPath)
sourceURL.appendPathComponent("archive.zip")
var destinationURL = URL(fileURLWithPath: currentWorkingPath)
destinationURL.appendPathComponent("directory")
do {
try fileManager.createDirectory(at: destinationURL, withIntermediateDirectories: true, attributes: nil)
try fileManager.unzipItem(at: sourceURL, to: destinationURL)
} catch {
print("Extraction of ZIP archive failed with error:\(error)")
}
If you are using Objective-C then SSZipArchive is the best choice for this.
You can unzip using this
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *outputPath = [documentsDirectory stringByAppendingPathComponent:#"/ImagesFolder"];
NSString *zipPath = Your zip file path;
[SSZipArchive unzipFileAtPath:zipPath toDestination:outputPath delegate:self];
Hope it helps you.
There is a great 3rd party tool for zipping/unzipping files for iPhone
https://github.com/soffes/ssziparchive
Very simple to use. Hope that helps!!
Edit:
Quick method I created which takes url, downloads the zip and unzips it
-(void)downloadAndUnzip : (NSString *)sURL_p : (NSString *)sFolderName_p
{
dispatch_queue_t q = dispatch_get_global_queue(0, 0);
dispatch_queue_t main = dispatch_get_main_queue();
dispatch_async(q, ^{
//Path info
NSURL *url = [NSURL URLWithString:sURL_p];
NSData *data = [NSData dataWithContentsOfURL:url];
NSString *fileName = [[url path] lastPathComponent];
NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:fileName];
[data writeToFile:filePath atomically:YES];
dispatch_async(main, ^
{
//Write To
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:sFolderName_p];
[SSZipArchive unzipFileAtPath:filePath toDestination:dataPath];
});
});
}

Iphone-saving full size image to document directory hangs my app

I am working on an app similar to photo app in iPhone. The flow is I get images through UIImagePickerController. When I use Actual image and further save that image to documents,
My app hangs. I saw on profile tool that allocation goes to 19 to 20 mb. If there is any solution to that.
Getting image from UIImagepicker controller
Saving it to documents.
-(NSString *)saveImageInDocumentsAtPath:(NSNumber *)number
{
NSString *fileName=[NSString stringWithFormat:#"image%#.png",number];
NSString *imagePath= [[NSString alloc] initWithFormat:#"%#/%#", [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0],fileName];
UIImage *image = self.selectedImage.image;
NSData *imageData = UIImagePNGRepresentation(image);
[imageData writeToFile:imagePath atomically:YES];
return imagePath;
}
A typical image is going to be around 3Megabytes, if I am not mistaken (depending on the iPhone and its camera). So going from 19 to 20 is not unreasonable. Why you are at 19 to begin with ay be another question. See if you're loading in too many other images, large files etc.
If you use AV Foundation instead of ImagePicker, you have some other options for handling the images.
And you can write the image to the filesystem asynchronously.
This looks like a great opportunity for some error checking in your code.
Why not try this?
-(NSString *)saveImageInDocumentsAtPath:(NSNumber *)number
{
NSString *fileName=[NSString stringWithFormat:#"image%#.png",number];
NSArray * docDirectoryArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
if(docDirectoryArray)
{
NSString *imagePath= [[NSString alloc] initWithFormat:#"%#/%#", [docDirectoryArray objectAtIndex:0],fileName];
UIImage *image = self.selectedImage.image;
if(image)
{
NSData *imageData = UIImagePNGRepresentation(image);
if(imageData)
{
BOOL success = [imageData writeToFile:imagePath atomically:YES];
if(success)
{
// only return the image path in the success == YES case
return imagePath;
} else {
NSLog( #"did not save file to %#", imagePath);
}
} else {
NSLog( #"could not get image data out of the image");
}
} else {
NSLog( #"no image selected");
}
}
// you might want to check in the caller to make certain the imagePath is NULL
return NULL;
}

Saving in NSDocumentDirectory

Having weird problem with my NSDocumenDirectory saving.
Here is a sneak preview:
First I pick images ( in my imagePickerViewController):
in my PreviewController:
So at first try, it was okay.
Then I revisit the imagePickerViewController to add another image:
in my PreviewController:
This is where the problem occurs. At the image above, it recopies the last image from the old preview (like a duplicate). I dunno what Im doing wrong in my codes. But Im saving it when a file exist. Kindly see:
for (int i = 0; i < info.count; i++) {
NSLog(#"%#", [info objectAtIndex:i]);
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask ,YES );
NSString *documentsDir = [paths objectAtIndex:0];
NSString *savedImagePath = [documentsDir stringByAppendingPathComponent:[NSString stringWithFormat:#"firstSlotImages%d.png", i]];
if ([[NSFileManager defaultManager] fileExistsAtPath:savedImagePath]) {
NSLog(#"file doesnt exist");
} else {
ALAssetRepresentation *rep = [[info objectAtIndex: i] defaultRepresentation];
UIImage *image = [UIImage imageWithCGImage:[rep fullResolutionImage]];
//----resize the images
image = [self imageByScalingAndCroppingForSize:image toSize:CGSizeMake(256,256*image.size.height/image.size.width)];
NSData *imageData = UIImagePNGRepresentation(image);
[imageData writeToFile:savedImagePath atomically:YES];
NSLog(#"saving at:%#",savedImagePath);
}
}
What I need is to just reAdd AGAIN the same image with the new one.
Same as, like the last preview.
The four images are passed in the sequence that they show in the preview, so in the first example the orange cat is third, and in the second example, the orange cat is fourth. The new image isn't saving because it is third, and you already have a file named "firstSlotImages2.png". If you re-save each image without checking if the file exists, you should get the result you are looking for.
There's a key in the media info: UIImagePickerControllerMediaURL which returns an NSURL, convert it to a string and get the the lastPathComponent. Use this as the file name to save to the directory you are saving it to. You can then save the reference to these images by saving this same file name either in an NSMutableArray, or an NSMutableDictionary

iPhone - UIImagePickerController -> save the image to app folder

I have an iPhone application using a UIImagePickerController. As sourceType I have
UIImagePickerControllerSourceTypePhotoLibrary
UIImagePickerControllerSourceTypeCamera
UIImagePickerControllerSourceTypeSavedPhotosAlbum
so the user can make a photo or select one from the photo library from the photos or camera photos.
The image will be displayed in a UIImageView. The image should be saved if the user closes the app. So for text fields, I use NSUserDefaults. I know, it is not a good way to save the image inside the NSUSerDefaults with NSData, so I want to save / copy the image to a folder which is controlled by my application similar to the NSUserDefaults.
How can I do this? I want to save it, and then I can write the path to the file into my NSUserDefaults and read it on startup of the application.
Thank you in advance & Best Regards.
You can use the following code in UIImagePickerControllerDelegate delegate implementation
- (void) imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info {
//obtaining saving path
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *imagePath = [documentsDirectory stringByAppendingPathComponent:#"latest_photo.png"];
//extracting image from the picker and saving it
NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
if ([mediaType isEqualToString:#"public.image"]){
UIImage *editedImage = [info objectForKey:UIImagePickerControllerEditedImage];
NSData *webData = UIImagePNGRepresentation(editedImage);
[webData writeToFile:imagePath atomically:YES];
}
}
UPD
Swift 3.0 code by XueYu
here the image is saved as jpeg but you can also save it as png. the
0.0 parameter stands for compression and it's the lowest quality, if you want to get the best use 1.0.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
//obtaining saving path
let fileManager = FileManager.default
let documentsPath = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first
let imagePath = documentsPath?.appendingPathComponent("image.jpg")
// extract image from the picker and save it
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
try! UIImageJPEGRepresentation(pickedImage, 0.0)?.write(to: imagePath!)
}
self.dismiss(animated: true, completion: nil)
}
Depending on the file format you want to save, you can use
[UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
OR
[UIImageJPEGRepresentation(image) writeToFile:path atomically:YES];
This is the code to save the UIImage into the document directory. You can use this code in didFinishPickingImage delegate method:
// Create paths to output images
NSString *pngPath = [NSHomeDirectory();
stringByAppendingPathComponent:#"Documents/Test.png"];
NSString *jpgPath = [NSHomeDirectory();
stringByAppendingPathComponent:#"Documents/Test.jpg"];
// Write a UIImage to JPEG with minimum compression (best quality)
// The value 'image' must be a UIImage object
// The value '1.0' represents image compression quality as value from 0.0 to 1.0
[UIImageJPEGRepresentation(image, 1.0) writeToFile:jpgPath atomically:YES];
// Write image to PNG
[UIImagePNGRepresentation(image) writeToFile:pngPath atomically:YES];
// Let's check to see if files were successfully written...
// Create file manager
NSError *error;
NSFileManager *fileMgr = [NSFileManager defaultManager];
// Point to Document directory
NSString *documentsDirectory = [NSHomeDirectory();
stringByAppendingPathComponent:#"Documents"];
// Write out the contents of home directory to console
NSLog(#"Documents directory: %#", [fileMgr contentsOfDirectoryAtPath:documentsDirectory error:&error]);
EDIT
You can also use:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
to find the path to your application document directory, instead of NSHomeDierctory.
Update knuku's answer for Swift 3.0
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
//obtaining saving path
let fileManager = FileManager.default
let documentsPath = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first
let imagePath = documentsPath?.appendingPathComponent("image.jpg")
// extract image from the picker and save it
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
try! UIImageJPEGRepresentation(pickedImage, 0.0)?.write(to: imagePath!)
}
self.dismiss(animated: true, completion: nil)
}
here the image is saved as jpeg but you can also save it as png. the 0.0 parameter stands for compression and it's the lowest quality, if you want to get the best use 1.0.