I need to use the iOS device camera to take a photo and then upload it to the server. The problem is that, by default, the UIImage taken form UIImagePickerController info does not include GPS metadata.
Following this post I have been able to save the image in the Camerra Roll with the correct GPS info. The code used is the following one:
- (void)saveImage:(UIImage *)imageToSave withInfo:(NSDictionary *)info {
// Get the image metadata (EXIF & TIFF)
NSMutableDictionary * imgMtd = [[info objectForKey:UIImagePickerControllerMediaMetadata] mutableCopy];
// create CLLocation for image
locationManager = [[CLLocationManager alloc] init];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
CLLocation * loc = [locationManager location];
if (loc) {
[imgMtd setObject:[self gpsDictionaryForLocation:loc] forKey:(NSString*)kCGImagePropertyGPSDictionary];
}
// Get the assets library
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
// create a completion block for when we process the image
ALAssetsLibraryWriteImageCompletionBlock imageWriteCompletionBlock =
^(NSURL *newURL, NSError *error) {
if (error) {
NSLog( #"Error writing image with metadata to Photo Library: %#", error );
} else {
NSLog( #"Wrote image %# with metadata %# to Photo Library",newURL,imgMtd);
}
};
// Save the new image to the Camera Roll, using the completion block defined just above
[library writeImageToSavedPhotosAlbum:[imageToSave CGImage] metadata:imgMtd completionBlock:imageWriteCompletionBlock];
}
However, I am using this photo to upload it to a server. Therefore, the desired behavior is to save it at a temporal path (so the image won't be available at the Camera Roll), upload it to the server and then delete it. With the code provided, I am making the image public, and don't know its path to upload it.
Related
I've using uiimagepickercontroller and taken images via camera and stored into folder that was created in sandbox. That stored images are not displayed in iPads or iPhone photo gallery. I want to display those sandbox pictures in device gallery. Any one help me out from this.
My optimum goal is to copy image from sandbox and paste it to device's internal memory.
You use the UIImageWriteToSavedPhotosAlbum() function.
UIImageWriteToSavedPhotosAlbum(IMAGE_TO_STORED, nil, nil, nil);
Edit:
- (IBAction)savedPhoto:(id)sender{
UIImageWriteToSavedPhotosAlbum(IMAGE_TO_STORED, nil, nil, nil);
}
Another way to stored image is:
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library saveImage:image toAlbum:nil withCompletionBlock:^(NSError *error) {
if (error!=nil)
{
NSLog(#"Error: %#", [error description]);
}
}];
I downloaded an gif image from the network using AFNetworking 2.0 then save it to camera roll using ALAssetsLibrary
[assetsLibrary writeImageToSavedPhotosAlbum:[responseObject CGImage] orientation:(ALAssetOrientation)[responseObject imageOrientation] completionBlock:^(NSURL *assetURL, NSError *error)
{
if (error)
{
[App showAlertWithTitle:#"Error" message:#"Save message failed"];
}
else
{
[App showAlertWithTitle:#"Success" message:#"Saved success"];
}
}];
Then I tried to retrieve this image from camera using UIImagePickerViewController, but the image I retrieved was not a GIF image but a jpeg image with reference url:
UIImagePickerControllerReferenceURL = "assets-library://asset/asset.JPG?id=2E7C87E4-5853-4946-B86B-CC8AAF094307&ext=JPG";
I don't know whether the fault is ALAssetsLibrary or UIImagePickerViewController and how to surpass it
The photo library does not support GIFs.
It has support for PHAssetMediaTypeImage (a JPG), PHAssetMediaTypeVideo (a MOV), or PHAssetMediaTypeAudio (probably an M4A, not sure here).
https://developer.apple.com/library/ios/documentation/Photos/Reference/Photos_Constants/index.html#//apple_ref/c/tdef/PHAssetMediaSubtype
The writeImageToSavedPhotosAlbum: methods only save still images as JPEGs, as do the new Photos methods. However, there are ways of saving other formats, including (yes!) GIF.
You don't need to mess about with CGImageRefs—just grab the GIF data and then save it, using the writeImageDataToSavedPhotosAlbum:metadata:completionBlock: method. Something like this:
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
NSData *data = [NSData dataWithContentsOfURL:
[NSURL URLWithString:#"http://somewhere/something.gif"]]];
[library writeImageDataToSavedPhotosAlbum:data
metadata:nil
completionBlock:^(NSURL *assetURL, NSError *error) {
if (error) {
[App showAlertWithTitle:#"Error" message:#"Save message failed"];
} else {
[App showAlertWithTitle:#"Success" message:#"Saved success"];
}
}];
See this answer.
If you want to generate a GIF, it's somewhat more complex, but simply saving one is straightforward.
I tried to write the file format of "output.aif". I used the below code to write it to a path. The file got saved in two locations one at the path I specified and one more it got saved in the image gallery by default and the name of the file is of a random number. While exiting the application I use to delete the saved ".aif" files from the location I saved, But I couldnt delete the files that got saved in the gallery as I dont know the name of the files.
Is there any way to stop saving the "aif" files from gallery which is happening default.
Can any one suggest a different code to save the file in a location, which wont save the file in gallery?
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library writeVideoAtPathToSavedPhotosAlbum:url completionBlock:^(NSURL *assetURL, NSError *error){
if (error) {
}
else{
NSString *outputTp = [[[NSHomeDirectory() stringByAppendingString:#"/Documents/"] stringByAppendingString:#"output.aif"] retain];
inUrl = [url retain];
outUrl = [[NSURL fileURLWithPath:outputSound] retain];
reader = [[EAFRead alloc] init];
writer = [[EAFWrite alloc] init];
self.url = outputTp;
// this thread does the processing
[NSThread detachNewThreadSelector:#selector(processThread:) toTarget:self withObject:nil];
}
}];
I am currently saving a UIImage to the camera roll this way.
UIImageWriteToSavedPhotosAlbum(finalPicture.image, nil, nil, nil);
But what happens if the user denies us permission to access their photos... how can I tell that this has happened and display an error message?
To save the image to the camera roll I'm Using ALAssetsLibrary so in the method:
//Called after taking the photo with the camera or selected the image from the gallery
- (void)imagePickerController:(UIImagePickerController *) Picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
NSURL *referenceURL;
if(Picker.sourceType==UIImagePickerControllerSourceTypeCamera){
UIImage* takenImage=info[UIImagePickerControllerOriginalImage];
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
// Request to save the image to camera roll
[library writeImageToSavedPhotosAlbum:[takenImage CGImage] orientation:(ALAssetOrientation)[takenImage imageOrientation] completionBlock:^(NSURL *assetURL, NSError *error){
if (error) {
//NOT SAVED
//DISPLAY ERROR THE PICTURE CAN'T BE SAVED
} else {
//SAVED
}
}];
}
}else{
//Selected from gallery
}
Also remember that you have to check first if the camera is available.
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
//The camera is available
}else{
//No camera available
}
I am working on an iOS app and I recently implemented a imagePicker in a popover that allows a user to record photos and videos. I would like to store these in the iPad's photo roll so that the user can sync them in iTunes later. I've been able to do this successfully, but I would like to give each photo and video a unique name that contains useful information about the photo and video so I can load them later. Specifically, I would like to store the photo using a property of the class, live_trial_id, as the filename. Below is the code that I am currently using to store my photos and videos to the photo roll. I understand that I could do this with metadata for pictures, but for the videos I am lost. Thanks in advance for any help with this issue!
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
UIImage *originalImage, *editedImage, *imageToSave;
// Handle a still image capture
if( [mediaType isEqualToString:#"public.image"]){
editedImage = (UIImage *) [info objectForKey:
UIImagePickerControllerEditedImage];
originalImage = (UIImage *) [info objectForKey:
UIImagePickerControllerOriginalImage];
if (editedImage) {
imageToSave = editedImage;
} else {
imageToSave = originalImage;
}
// Get the image metadata
UIImagePickerControllerSourceType pickerType = picker.sourceType;
if(pickerType == UIImagePickerControllerSourceTypeCamera)
{
NSDictionary *imageMetadata = [info objectForKey:
UIImagePickerControllerMediaMetadata];
// Get the assets library
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
ALAssetsLibraryWriteImageCompletionBlock imageWriteCompletionBlock =
^(NSURL *newURL, NSError *error) {
if (error) {
NSLog( #"Error writing image with metadata to Photo Library: %#", error );
} else {
NSLog( #"Wrote image with metadata to Photo Library");
}
};
// Save the new image (original or edited) to the Camera Roll
[library writeImageToSavedPhotosAlbum:[imageToSave CGImage]
metadata:imageMetadata
completionBlock:imageWriteCompletionBlock];
}
}
if ([mediaType isEqualToString:#"public.movie"]) {
UIImagePickerControllerSourceType pickerType = picker.sourceType;
if(pickerType == UIImagePickerControllerSourceTypeCamera)
{
NSURL *mediaURL = [info objectForKey:UIImagePickerControllerMediaURL];
// Get the assets library
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
ALAssetsLibraryWriteVideoCompletionBlock videoWriteCompletionBlock =
^(NSURL *newURL, NSError *error) {
if (error) {
NSLog( #"Error writing image with metadata to Photo Library: %#", error );
} else {
NSLog( #"Wrote image with metadata to Photo Library");
}
};
// Save the new image (original or edited) to the Camera Roll
[library writeVideoAtPathToSavedPhotosAlbum:mediaURL
completionBlock:videoWriteCompletionBlock];
}
}
I would also like to avoid creating a custom library or custom metadata if at all possible. I really just wanted to change the filename on the way to the photo roll
I ended up answering my own question. What I wanted to do was to save to the application's documents directory instead of the photo roll. This allowed me to access the files that I had saved and also to sync them to the computer when attached later.