I am using UIImagePickerViewController to take photo from iPhone default camera in my App and storing it in Document directory. It is taking long time to complete the process and also it is displaying very slowly on tableview.Does resizing image help here?
-(IBAction)takePhoto:(id)sender
{
if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera])
{
imgPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentModalViewController:imgPicker animated:YES];
}
}
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *pickedImage = [info objectForKey:UIImagePickerControllerOriginalImage];
[self dismissModalViewControllerAnimated:YES];
NSData *imageData = UIImagePNGRepresentation(pickedImage);
NSString *path = [SAVEDIMAGE_DIR stringByAppendingPathComponent:#"image.png"];
[imageData writeToFile:path atomically:YES];
}
Sure!
I do the following in my app:
store the image in an image store in a background thread
create a thumbnail (also in background thread), store this thumbnail in a core data table; in an field of type ID
So I get a smooth UI, where the User can take about a picture every 2 seconds.
The smoothness of the table views are also no problem. Although I populate the TableViewCells ImageViews also from a background-thread (preparing the image in the background, assigning to the UIImageView in the mainthread, of course).
I hope, that helps you. Further questions are welcome.
Some code for your convenience:
As Imagestore I use these: https://github.com/snowdon/Homepwner/blob/master/Homepwner/ImageStore.m
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[self performSelectorInBackground:#selector(saveFoto:) withObject:info];
// you should add some code for indicating the save process
}
// saves the photo in background-thread
-(void)saveFoto:(NSDictionary*)info {
// the following is some stuff that I do in my app - you will probably do some other things
UIImage *image = [ImageHelper normalizeImageRotation: [info objectForKey:UIImagePickerControllerOriginalImage]];
UIImage *thumb = [ImageHelper image:image fitInSize:CGSizeMake(imgWidth, imgWidth) trimmed:YES];
NSString *myGUID = myGUIDCreator();
[[ImageStore defaultImageStore] setImage:image forKey:myGUID];
myCoreDataManagedObject.thumb = thumb;
[self performSelectorOnMainThread:#selector(showYourResultsInTheUI:) withObject:thumb waitUntilDone:NO]; // every UI-Update has to be done in the mainthread!
}
Related
I am new in ios development. I am doing a photo cropper app.
I want to browse an image from the iPhone picture library by clicking browse button (that I added in my app) and load it to UIImageview that I placed in a view.
How can I browse the image ?.
Is it possible to browse the complete phone memory ? (Just like asp:FileUpload).
Is there any control available in iPhone to use just like asp:FileUpload ?
Thanks in advance.
Super easy to do!
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[imagePicker setDelegate:self];
[self presentModalViewController:imagePicker animated:YES];
and
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[picker dismissModalViewControllerAnimated:YES];
[picker release];
// Edited image works great (if you allowed editing)
//myUIImageView.image = [info objectForKey:UIImagePickerControllerEditedImage];
// AND the original image works great
//myUIImageView.image = [info objectForKey:UIImagePickerControllerOriginalImage];
// AND do whatever you want with it, (NSDictionary *)info is fine now
//UIImage *myImage = [info objectForKey:UIImagePickerControllerEditedImage];
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
[customImageView setImage:image];
customImageView.contentMode = UIViewContentModeScaleAspectFill;
}
got this code from stackoverflow, didn't save the URL, sorry.
The whole file system is not available, if you're running a non-jailbroken phone. Neither are there filesystem browser controls (for the same reason), However, you can browse the user's photo library, or even take a photo with the camera using UIImagePickerController. Docs: http://developer.apple.com/library/ios/#documentation/uikit/reference/UIImagePickerController_Class/UIImagePickerController/UIImagePickerController.html
I'm attempting to take and save photos with the camera rapidly, as quickly as the iPhone can. The problem is that they don't save until the end and it then takes forever, or about 1/2 to 3/4 don't save at all (Write busy error or -[NSKeyedUnarchiver initForReadingWithData:]: data is NULL).
I bet I'm just overloading the phone's memory, but I can't think of a way to handle it efficiently. The standard iPhone camera app can handle it just fine -- snap away at almost 1 photo/second and it saves with no problem.
Any ideas on how to manage the process/memory better so that it can save as it goes but still shoot rapidly?
Here's a bit of my code. takePicture is called whenever self.readyToTake = YES.
- (void)takePicture {
self.delegate = self;
[super takePicture];
self.readyToTake = NO;
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
self.readyToTake = YES;
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
UIImageWriteToSavedPhotosAlbum(image, self, #selector(image:didFinishSavingWithError:contextInfo:), nil);
}
- (void)image:(UIImage*)image didFinishSavingWithError:(NSError *)error contextInfo:(NSDictionary*)info {
if (error)
{
NSLog([NSString stringWithFormat:#"** ERROR SAVING PHOTO: %#", [error localizedDescription]]);
}
}
Thank you for your help!
EDIT
If I resize the photos to much smaller dimensions before saving, like 480x640, I have no problem saving quickly. However, I'm wanting to capture and save full-size images. The native Camera app seems to handle it fine.
you can do like this.
ie., enable taking the next photo only after the previous photo is saved.
Also introduce autorelease pool for memory management.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
UIImageWriteToSavedPhotosAlbum(image, self, #selector(image:didFinishSavingWithError:contextInfo:), nil);
[pool drain];
}
- (void)image:(UIImage*)image didFinishSavingWithError:(NSError *)error contextInfo:(NSDictionary*)info {
if (error)
{
NSLog([NSString stringWithFormat:#"** ERROR SAVING PHOTO: %#", [error localizedDescription]]);
}
self.readyToTake = YES;
}
The first thing I'd try is offloading those calls asynchronously to a dispatch queue:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
self.readyToTake = YES;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
UIImageWriteToSavedPhotosAlbum(image, self, #selector(image:didFinishSavingWithError:contextInfo:), nil);
});
}
If you're still having trouble, I'd look into AVCaptureSession and friends. This gives you a lot more control and generally better performance. There's a great sample project using this method at the developer portal: SquareCam
EDIT
You could also try using AssetsLibrary instead of UIImageWriteToSavedPhotosAlbum (This is what we use in all our apps) Something like:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
self.readyToTake = YES;
// you probably want to create this once and keep it around as a property
// on your controller
ALAssetsLibrary* library = [[ALAssetsLibrary alloc] init];
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
[library writeImageToSavedPhotosAlbum:image.CGImageRef orientation:(ALAssetOrientation)image.orientation completionBlock:^(NSURL *assetURL, NSError *error) {
// do whatever you need to do when the image is saved
}];
}
there is one best example app on developer.apple.com site in which the solution for your problem is shown in it they save photos for 1second interval automatically when user tap on "timed" button here is its code it surely helps you as i can able to store 5 consicutive photos 1/second speed
Please see page MyViewController.m and after getting images in array you can save them to the photo album using some function on another queue
i am trying to create thumbnail of a image i am importing from photo library or camera using a UIImagePickerController using - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)selectedImage editingInfo:(NSDictionary *)editingInfo when i use the camera the thumbnail of the image clicked is easily created but when the same is done by selecting a image from photo library my app crashes.. When i enabled NSZombie in my app it shows f-[UIImage drawInRect:]: message sent to deallocated instance 0x5abc140 on myThumbnail variable..
What am i possible doing wrong??
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)selectedImage editingInfo:(NSDictionary *)editingInfo
{
[self saveImage:selectedImage];
}
- (void)saveImage:(UIImage *)img
{
myThumbNail = img;
UIGraphicsBeginImageContext(CGSizeMake(60.0,60.0));
[myThumbNail drawInRect:CGRectMake(0.0, 0.0, 60.0, 60.0)];// gets killed here
}
What is image in your saveImage: method? I think it should be img.
Hope this helps
- (void)saveImage:(UIImage *)img
{
[img retain];
//alloc your myThumbNail before this
myThumbNail = img;
[img release];
UIGraphicsBeginImageContext(CGSizeMake(60.0,60.0));
[myThumbNail drawInRect:CGRectMake(0.0, 0.0, 60.0, 60.0)];// gets killed here
}
+ (UIImage *)resizeImage:(UIImage *)image toResolution:(int)resolution
{
NSData *imageData = UIImagePNGRepresentation(image);
CGImageSourceRef src = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL);
CFDictionaryRef options = (__bridge CFDictionaryRef) #{
(id) kCGImageSourceCreateThumbnailWithTransform : #YES,
(id) kCGImageSourceCreateThumbnailFromImageAlways : #YES,
(id) kCGImageSourceThumbnailMaxPixelSize : #(resolution)
};
CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(src, 0, options);
CFRelease(src);
UIImage *img = [[UIImage alloc]initWithCGImage:thumbnail];
return img;
}
This method takes a UIImage and the resolution as the arguments and returns a UIImage with the required resolution.
For example: If you want to convert 1024x1024 resolution image to 240x240, then pass 1024x1024 UIImage in argument1 and 240 in argument2. In return you get 240x240 UIImage (or whatever thumbnail size you want).
Are you calling alloc init on myThumbNail anywhere? It sounds like you either have not allocated memory for it in the first place, or you have released it somewhere you shouldn't have.
I need to add objects selected by UIImagePickerController into an NSMutabeArray, the code goes as:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
[picker dismissModalViewControllerAnimated:YES];
if(![imagesArray containsObject:[info objectForKey:#"UIImagePickerControllerOriginalImage"]])
{
[imagesArray addObject:[info objectForKey:#"UIImagePickerControllerOriginalImage"]];
}
else {
//some procedures
}
}
The problem is that it always fells into the if block and never executes the else block when picking same images repeatedly. Any clue over this would be appreciated.
I think your problem is that two instances of UIImage can't be compared using isEqual:, which containsObject: is using, even if they point to the same image file. I don't know how to compare two UIImage but you can perhaps look at Generate hash from UIImage or search for "comparing UIImage".
Check by casting. Add it in this way:
UIImage *img =[info objectForKey:#"UIImagePickerControllerOriginalImage"];
if(![imagesArray containsObject:img])
[imagesArray addObject:img];
I've not found a answer to this question anywhere, but this seems like a typical problem:
I am taking pictures from an iPhone 4, and I have to send these pics to a server through a POST-Request, but the server does not accept pictures that are bigger than 0,5 MB, so I have to compress the pictures before I send them. In order to achieve this, I am calling following method: "NSData *imageData = UIImageJPEGRepresentation(tempImage, 0.7);", which means: I am compriming the image data, and it takes a lot of time (about 10s / pic).
Is there any way to control the quality of the camera device in order to take low quality pictures?
Thanks in advance for helping.
Anything that will block the main thread should be done in a background thread, including converting an image to a JPEG. So you should start the JPEG conversion using performSelectorInBackground:withObject: and, when the conversion is done, pass the resulting NSData object back to the main thread.
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
[self dismissModalViewControllerAnimated:YES];
[self performSelectorInBackground:#selector(encodePhotoInBackground:) withObject:image];
}
- (void)encodePhotoInBackground:(UIImage*)image {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSData *imageData = UIImageJPEGRepresentation(image, 0.60);
[self performSelectorOnMainThread:#selector(saveImageData:) withObject:imageData waitUntilDone:NO];
[pool release];
}
- (void)saveImageData:(NSData*)imageData {
// Do something with the image
}