I'm using a simple implementation of UIImagePickerController to take a picture and save it to my app directory. I"m running into problems with didFinishPickingMediaWithInfo, where I retrieve the image from the info, convert it into NSData using UIImageJPEGRepresentation, and then save it to a file. Problem is, the NSData object appears never to be overwritten, so the first time I take a picture it saves the picture just fine, but any subsequent pictures are not saved, because when I redisplay the image located at the filePath I'm saving it to, it's always the very first picture I took.
I have NSLog statements right now printing out the hash of the UIImage and of the NSData object I'm saving the image to. The UIImage hash changes each time, but the NSData hash is exactly the same all the time...shouldn't that change too?
My code is below. Note that everything not declared in the delegate method below is a global var that isn't causing me any trouble (at least they don't seem to be).
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documentsDirectory = [paths objectAtIndex:0];
filePath = [NSString stringWithFormat:#"%#/%#", documentsDirectory, fileNameString];
NSData *imageData = UIImageJPEGRepresentation(image, 0.5f);
// imageData = [NSData dataWithData:UIImageJPEGRepresentation(image, 0.5f)];
[imageData writeToFile:filePath atomically:YES];
[self dismissModalViewControllerAnimated:YES];
}
When I get rid of the NSData object entirely and replace all instances of
imageData
with
UIImageJPEGRepresentation(image, 0.5f)
I still have the same problem, namely that the hash of UIImageJPEGRepresentation(image, 0.5f) is always the same, even though the hash of the UIImage it takes as a parameter always changes.
Try this:
NSData *imageData = UIImageJPEGRepresentation(image, 0.5f);
imageData = [NSKeyedArchiver archivedDataWithRootObject:imageData];
//imageData = [NSData dataWithData:UIImageJPEGRepresentation(image, 0.5f)];
NSError *error= nil;
[imageData writeToFile:filePath options:NSDataWritingAtomic error:&error];
Also take a look at this link
Are you creating the directory? Use this code to create the directory:
NSArray* dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString* docsDir = [dirPaths objectAtIndex:0];
pathString = [docsDir stringByAppendingPathComponent:#"%#",filePath];
NSFileManager* filemgr = [NSFileManager defaultManager];
//Creates Directory
if ([filemgr createDirectoryAtPath:pathString
withIntermediateDirectories:YES
attributes:nil
error: NULL] == YES){
Related
The following code works without error or exception - but still, it does not do what it should ! I wanted to save an image into the iOS library/Application Support folder. More precisely, the image should be placed into a /library/Application Support/bundleID_name/subfolder/ (and the subfolder being called "location1").
If I check the functionality with the iOS-Simulator, I can see the creation of the subfolder (i.e. .../library/Application Support/bundleID_name/location1/). Also the function "saveImage" works without exception. But there is no image being saved !!!! (i.e.the image-file is missing and the folder remains empty) !!
What could be the mistake ??
Here is my code with the call of two functions (see code below):
UIImage *in_image = [UIImage imageNamed:#"template009c.jpg"];
NSString *locDirectoryName = #"location1";
NSURL *LocationDirectory = [self appendLocationToApplicationDirectory:locDirectoryName];
[self saveImage:in_image :#"image1" :LocationDirectory];
With the corresponding function-Nr1:
- (NSURL*)appendLocationToApplicationDirectory:(NSString*)locationDirName
{
NSString* appBundleID = [[NSBundle mainBundle] bundleIdentifier];
NSFileManager*fm = [NSFileManager defaultManager];
NSURL* dirPath = nil;
// Find the application support directory in the home directory.
NSArray* appSupportDir = [fm URLsForDirectory:NSApplicationSupportDirectory
inDomains:NSUserDomainMask];
if ([appSupportDir count] > 0) {
// Append the bundle ID and the location-Foldername to the URL for the Application Support directory
dirPath = [[[appSupportDir objectAtIndex:0] URLByAppendingPathComponent:appBundleID] URLByAppendingPathComponent:locationDirName];
// If the directory does not exist, this method creates it.
// This method call works in OS X 10.7 and later only.
NSError* theError = nil;
if (![fm createDirectoryAtURL:dirPath withIntermediateDirectories:YES attributes:nil error:&theError]) {
// Handle the error.
NSLog(#"%#", theError.localizedDescription);
return nil;
}
else {
// Mark the directory as excluded from iCloud backups
if (![dirPath setResourceValue:#YES
forKey:NSURLIsExcludedFromBackupKey
error:&theError]) {
NSLog(#"Error excluding %# from iCloud backup %#", [dirPath lastPathComponent], theError.localizedDescription);
}
else {
NSLog(#"Location Directory excluded from iClud backups");
}
}
}
return dirPath;
}
And function Nr2:
//saving an image
- (void)saveImage:(UIImage*)image :(NSString*)imageName :(NSURL*)pathName {
NSData *imageData = UIImagePNGRepresentation(image); //convert image into .png format.
NSFileManager *fileManager = [NSFileManager defaultManager];
// NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
// NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *LocationDirectory = [pathName absoluteString];
NSString *fullPath = [LocationDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.png", imageName]];
/***** THE FOLLOWING LINE DOES NOT SEEM TO DO WHAT IT IS SUPPOSED TO *******/
[fileManager createFileAtPath:fullPath contents:imageData attributes:nil];
/**** I also tried without the FileManager, but same problem - no file written... ***/
// [imageData writeToFile:fullPath atomically:NO];
NSLog(#"image saved");
}
By the way, getting the "fullPath" with the XCode-Debugger, I get:
"fullPath NSPathStore2 * #"file:/Users/username/Library/Application%20Support/iPhone%20Simulator/7.1/Applications/2BCC3345-9M55F-4580-A1E7-6694E33456777/Library/Application%20Support/bundleID_name/image1.png" 0x09d50950
Doesn't that also seem correct ?? But why is [fileManager createFileAtPath:fullPath contents:imageData attributes:nil]; not performing ???
This:
"fullPath NSPathStore2 * #"file:/Users/username/Library/Application%20Support/iPhone%20Simulator/7.1/Applications/2BCC3345-9M55F-4580-A1E7-6694E33456777/Library/Application%20Support/bundleID_name/image1.png" 0x09d50950
is not a valid path, it's a URL path but stored in a string. If you are going to use URL's then use ULRs rather than trying to convert to a string:
[imageData writeToURL:pathName atomically:YES];
(preferably naming the parameter as pathURL) and if you want to use paths then don't use a URL at any stage.
Also, where an API method returns an error or status flag, check it in the code as standard.
I'm pretty sure you can't save an image on a path you specify. You can save images on the gallery or in DocumentDirectory. This should be the code to save an image on the DocumentDirectory:
NSString *imgName=[#"imgname.png"];
[[NSUserDefaults standardUserDefaults]setValue:imgName forKey:#"imageName"];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *savedImagePath = [documentsDirectory stringByAppendingPathComponent:imgName];
UIImage *image = imageView.image; // imageView is my image from camera
NSData *imageData = UIImagePNGRepresentation(image);
[imageData writeToFile:savedImagePath atomically:NO];
I'm working on an app and I need to get bytes from an UIImage.
For the moment, I use UIImagePickerController, and get the UIImage like this,
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
and then get data from UIImage using this code,
NSData *data = UIImageJPEGRepresentation(image, 1.0);
However, data appears to get corrupted in this case.
On other hand, I have add the jpeg to app's bundle, and tried to convert the image then to data,
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"mapa" ofType:#"jpeg"];
NSData *myData = [NSData dataWithContentsOfFile:filePath];
Surprisingly this works perfectly.
Here are my questions:
How can I get the bytes of image selected from UIImagePickerController correctly?
Is there a way to add photos to the bundle programmatically?
Thanks!
EDIT:
I have some metadata bytes on the original JPEG ("GEO-Information").
If i store the jpeg on the ipad, that metadata disappear, and I need them :S
Use the below code to store image in document directory;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *getImagePath = [documentsDirectory stringByAppendingPathComponent:#"savedImage.png"];
[data writeToFile:savedImagePath atomically:NO];
Here 'data' will be the NSData you have obtained from your image captured.
I am making an app that will save a file to the iPhones Documents Directory and then when the View Controller is reloaded it will fetch it from that same location and display it. But it is not fetching it and displaying it.
I am using the following method to save the image:
void UIImageWriteToFile(UIImage *image, NSString *fileName)
{
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectoryPath = dirPaths[0];
NSString *filePath = [documentDirectoryPath stringByAppendingPathComponent:fileName];
NSData *imageData = UIImagePNGRepresentation(image);
[imageData writeToFile:filePath atomically:YES];
}
I am trying to recall the image I have saved from the viewDidLoad method with the following code:
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectoryPath = dirPaths[0];
NSString *fileName = [NSString stringWithFormat:#"/%#.png", self.fullname.text];
NSString *filePath = [documentDirectoryPath stringByAppendingString:fileName];
[self.imageView setImage:[UIImage imageNamed: filePath]];
However, it is not showing my image. Can anyone help me and tell me where I am going wrong please. I am new to iOS Development.
replace this line: [self.imageView setImage:[UIImage imageNamed: filePath]];
with this one :
UIImage *image = [[UIImage alloc] initWithContentsOfFile:filePath];
[self.imageView setImage:image];
You can use [UIImage imageNamed:] with images from the Documents folder and have the benefits of the underlying caching mechanism, but the file path is slightly different.
Use the following:
NSString *fileName = [NSString stringWithFormat:#"../Documents/%#.png", self.fullname.text];
UIImage *image = [UIImage imageNamed:fileName];
You need to use method
- (UIImage*)initWithContentsOfFile:(NSString*)path
to init images from Documents or Cache directories.
imageNamed: is used for getting images from application bundle.
I have an app that I am saving images to the NSDocumentDirectory. I can see that the path is being set correctly but when I try to retrieve them the NSData is null.
Here are some of my snippets..
NSData *imageData = UIImagePNGRepresentation(image);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"myApp"];
//Create unique filename
CFUUIDRef newUniqueId = CFUUIDCreate(kCFAllocatorDefault);
CFStringRef newUniqueIdString = CFUUIDCreateString(kCFAllocatorDefault, newUniqueId);
path = [path stringByAppendingPathComponent:(__bridge_transfer NSString *)newUniqueIdString];
path = [path stringByAppendingPathExtension: #"png"];
[imageData writeToFile:path atomically:NO];
[self showPhoto:path];
Then in my showPhoto method
NSData *pngData = [NSData dataWithContentsOfFile:path];
UIImage *image = [UIImage imageWithData:pngData];
If I debug pngData it is 0 bytes but my path show what I think is the correct path?
Any way of debugging if the photo is actually on the phone? Im not sure if it is getting saved or not.
You can do something like this and check if the file exists first and use imageWithContentsOfFile: to retrieve it.
NSString *imagePath = [NSHomeDirectory() stringByAppendingPathComponent:localFilePath];
bool fileExists = [[NSFileManager defaultManager] fileExistsAtPath:imagePath];
if(fileExists == YES)
{
UIImage *_image = [UIImage imageWithContentsOfFile:localFilePath]
}
If the image is still empty then there is something wrong with your image.
If you running app in simulator you can find application files here: /Users/{user}/Library/Application Support/iPhone Simulator/5.0/Applications
If you debugging on iPhone you can use iExplorer to see files on iPhone.
Simple question regarding data persistance between application sessions.
My application allows the user to select an image from the Library using a UIImagePickerController. The selected photo is then used as the background to the application.
As the UIImagePickerController delegate method actually returns an image as opposed to an image path, I am wondering what is the best way to persist this image over user sessions?
I do not require any other data to be persisted at the moment, as everything else is pulled in from SQL Server, but I do not want the added overhead of having to store the image in the server as well, which would mean that everytime the user opened the application the background image would first have to be downloaded from the server into a byte array and then converted into an image.
I have found the following code that can save the image:
- (void)saveImage:(UIImage *)image withName:(NSString *)name {
//save image
NSData *data = UIImageJPEGRepresentation(image, 1.0);
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:name];
[fileManager createFileAtPath:fullPath contents:data attributes:nil];
}
I am not on a mac at the moment, so I cannot test this code, but I have a couple of questions regarding the code above:
I don't want a lot of files cluttering the file system. So I would like a single background file (background.png); how would the code above handle a situation where this file already existed?
Would it overwrite the existing file or would it throw an error?
How would I go about loading the image again?
You have to remove the file first:
- (void)saveImage:(UIImage *)image withName:(NSString *)name {
//save image
NSData *data = UIImageJPEGRepresentation(image, 1.0);
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:name];
NSError *error = nil;
if( [fileManager fileExistsAtPath:fullPath] ){
if( ! [fileManager removeItemAtPath:fullPath error:&error] ) {
NSLog(#"Failed deleting background image file %#", error);
// the write below should fail. Add your own flag and check below.
}
}
[data writeToFile:fullPath atomically:YES];
}
Reading back in should work as follows:
...
UIImage *bgImage = [UIImage imageWithContentsOfFile:fullPath];
...