I am having tough time with getting UIImagePickerController to work. It always crashes with memory error. These are the things I have done. Please advice what I can do differently.
I am using NSOperationQueue to do the save operation in a different thread.
I am not passing the UIImage which can be large, so I write the image to photo album and pass the NSURL of the asset.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
[self dismissViewControllerAnimated:YES completion:^{
UIImage *chosenImage = info[UIImagePickerControllerOriginalImage];
NSMutableDictionary *mutable = [[info objectForKey:UIImagePickerControllerMediaMetadata] mutableCopy];
NSBlockOperation *saveOp = [NSBlockOperation blockOperationWithBlock:^{
[[MyViewController defaultAssetsLibrary] writeImageToSavedPhotosAlbum:[chosenImage CGImage] metadata:mutable completionBlock:^(NSURL *assetURL, NSError *error) {
if ([self.delegate respondsToSelector:#selector(imageSelected:)]) {
[self.delegate imageSelected:assetURL];
}
}];
}];
[saveOp setCompletionBlock:^{
}];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:saveOp];
}];
}
Related
I am trying to go through and clean up some deprecation warnings by updating ALAsset with PHPhoto. I am getting confused by this code and need some help to make sure I am not missing something. I added in some comments about what is confusing me.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
NSURL *assetsURL = [info objectForKey:UIImagePickerControllerReferenceURL];
UIImage *pickedImage = [info objectForKey:UIImagePickerControllerOriginalImage];
NSMutableDictionary *metadata = [NSMutableDictionary dictionary];
// This is where I am getting confused.
// What is the difference between the meta data of the else statement
// and the if statement.
if (assetsURL) {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
[library assetForURL:assetsURL
resultBlock:^(ALAsset *asset) {
[metadata addEntriesFromDictionary:asset.defaultRepresentation.metadata];
dispatch_semaphore_signal(sema);
}
failureBlock:^(NSError *error) {
dispatch_semaphore_signal(sema);
}];
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
} else {
[metadata addEntriesFromDictionary:[info objectForKey:UIImagePickerControllerMediaMetadata]];
}
// Undocumented method guessing it rotates image to Portrait
pickedImage = [pickedImage IN_rotateToPortraitOrientation];
[metadata setImageOrientation:UIImageOrientationUp];
if (!assetsURL) {
[library writeImageToSavedPhotosAlbum:pickedImage.CGImage
metadata:metadata
completionBlock:^(NSURL *assetURL, NSError *error) {
$l(#"Saved to photo album");
}];
}
...
}
If you could help me understand the difference in meta data. If there is a difference how could I accomplish the same thing with PHPhotos.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
NSURL *assetURL;
if( [picker sourceType] == UIImagePickerControllerSourceTypeCamera )
{
assetURL = [info objectForKey:UIImagePickerControllerReferenceURL]; // always return nil !!
}
else if( [picker sourceType] == UIImagePickerControllerSourceTypePhotoLibrary)
{
assetURL = [info objectForKey:UIImagePickerControllerReferenceURL];
}
how can i get assetURL when i selected UIImagePickerControllerSourceTypeCamera.
UIImagePickerControllerSourceTypePhotoLibrary is work.
When you take an image using UIImagePickerControllerSourceTypeCamera, the image is not saved into photo library automatically. You have to write it manually. After writing, you can get the URL.
Sample code:
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) {
UIImage* cameraImage = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init];
[assetsLibrary writeImageToSavedPhotosAlbum:cameraImage.CGImage
metadata:[info objectForKey:UIImagePickerControllerMediaMetadata]
completionBlock:^(NSURL *assetURL, NSError *error) {
if (!error) {
//use assetURL as you need.
}
}];
}
}
A warning though, writing is a time consuming operation.
I am using ALAssetsLibrary to list details of photos present in cameraroll. But how to get details of a particular selected photo from cameraroll using ALAssetsLibrary?
Assume i selected ABC.jpeg from cameraroll. I want to display the exif details of only ABC.jpeg. Not exif details of other photos present in cameraroll.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *image = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
self.imageView.image = image;
NSLog(#"image %#\ninfo: %#",image, info);
[picker dismissViewControllerAnimated:YES completion:NULL];
ALAssetsLibrary* library = [[ALAssetsLibrary alloc] init];
[library enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
if (group) {
[group setAssetsFilter:[ALAssetsFilter allPhotos]];
[group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop){
if (asset){
NSDictionary *data = [[asset defaultRepresentation] metadata];
NSLog(#"%#",data);
}
}];
}
} failureBlock:^(NSError *error) {
NSLog(#"error enumerating AssetLibrary groups %#\n", error);
}];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissViewControllerAnimated:YES completion:NULL];
}
ok here is the code how to get the asset of a media picker with the image picker:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *image = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
self.imageView.image = image;
NSLog(#"media image info: %#", info);
//use assetLib
NSURL *imageURL = [info objectForKey:UIImagePickerControllerReferenceURL];
if(imageURL) {
[self getPictureInfoFromAssetURL:imageURL
success:^(NSDictionary*)alInfo {
NSLog(#"asset lib image info: %#", alInfo);
} failure:^(NSError *error) {
NSLog(#"error reading asset lib image info: %#", error);
}];
}
[picker dismissViewControllerAnimated:YES completion:NULL];
}
- (void)getPictureInfoFromAssetURL:(NSURL *)url
success:(void (^)(NSDictionary *alInfo))success
failure:(void (^)(NSError *error))failure {
ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc] init];
[assetslibrary assetForURL:url
resultBlock: ^(ALAsset *myasset) {
ALAssetRepresentation *rep = [myasset defaultRepresentation];
if(success {
success([rep metadata]);
}
failureBlock: ^(NSError *err) {
if (failure) {
failure(err);
}
}];
}
I am using following code to modify the metadata of Gallery Image.
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)mediaInfo
{
ALAssetsLibrary *library =nil;
void (^ALAssetsLibraryAssetForURLResultBlock)(ALAsset *) = ^(ALAsset *asset)
{
NSDictionary *metadata = asset.defaultRepresentation.metadata;
NSLog(#"Image Meta Data: %#",metadata);
NSMutableDictionary* dict=[[NSMutableDictionary alloc] initWithDictionary:metadata];
[dict setValue:#"sdfdfsfsfsfdsfsf" forKey:(NSString*)kCGImagePropertyIPTCKeywords];
UIImage *anImage = [mediaInfo valueForKey:UIImagePickerControllerOriginalImage];
NSData *imageData = UIImageJPEGRepresentation(anImage, 1.0);
[asset writeModifiedImageDataToSavedPhotosAlbum:imageData metadata:dict completionBlock:^(NSURL *assetURL, NSError *error) {
}];
};
NSURL *assetURL = [mediaInfo objectForKey:UIImagePickerControllerReferenceURL];
library = [[ALAssetsLibrary alloc] init];
[library assetForURL:assetURL
resultBlock:ALAssetsLibraryAssetForURLResultBlock
failureBlock:^(NSError *error) {
}];
}
But it is not working. Please help.
Here is a minimal example to do it:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *imageToSave = (UIImage *) [info objectForKey:UIImagePickerControllerOriginalImage];
/* modify metadata dict */
NSMutableDictionary *imageMetadata = [[info objectForKey: UIImagePickerControllerMediaMetadata] mutableCopy];
NSLog(#"Inspect current metadata: %#", imageMetadata);
NSDictionary *iptc = #{(id)kCGImagePropertyIPTCKeywords: #"awesome photo"};
[imageMetadata setObject:iptc forKey:(id)kCGImagePropertyIPTCDictionary];
/* Save to the Camera Roll with modified medatadata */
[[ALAssetsLibrary new] writeImageToSavedPhotosAlbum:imageToSave.CGImage
metadata:imageMetadata
completionBlock:NULL];
[self performDismiss];
}
If you use a metadata viewer (OS X's Preview is good enough) you'll see something like this:
But, as pawan suggests, use an existing library to do it more easily. Google around, there are quite a few options out there.
I'm trying to save an image from camera to Photo Library and then store the URL of the saved image. My code:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
ALAssetsLibrary *library = [[ALAssetsLibrary alloc]init];
[library writeImageToSavedPhotosAlbum:(__bridge CGImageRef)([info objectForKey:UIImagePickerControllerOriginalImage])
orientation:ALAssetOrientationUp completionBlock:^(NSURL *assetURL, NSError *error) {
if(error == nil) {
_myImageUrl = [NSString stringWithFormat:#"%#",assetURL];
NSLog(#"%#",assetURL);
} else NSLog(#"%#",error);
}];
[picker dismissViewControllerAnimated:YES completion:nil];}
My problem is that assetUrl is always NULL. Any ideas?
Thank you!
Finally, after reading more, I found out the answer: the first parameter of the function is of CGImageRef type and (__bridge CGImageRef) doesn't do what I expected; but if I call the CGImage method of UIImage object, it works. The correct way to do this is:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
ALAssetsLibrary *library = [[ALAssetsLibrary alloc]init];
CGImageRef image = [[info objectForKey:UIImagePickerControllerOriginalImage] CGImage];
[library writeImageToSavedPhotosAlbum:image
orientation:ALAssetOrientationUp
completionBlock:^(NSURL *assetURL, NSError *error) {
if(error == nil) {
_myImageUrl = [NSString stringWithFormat:#"%#",assetURL];
NSLog(#"%#",assetURL);
} else NSLog(#"%#",error);
}];
self.toDoImage.image = [info objectForKey:UIImagePickerControllerOriginalImage];
[picker dismissViewControllerAnimated:YES completion:nil];
}