I need to let the user select a photo from the Photo Library and be able to size and crop their image while using an Overlay image. Using UIImagePickerControllerSourceTypeCamera with cameraOverlayView is fine, but UIImagePickerControllerSourceTypeSavedPhotosAlbum does not support that property.
Strangely enough, when I add the overlay view as a subView with alpha set at half, the overlay appears on the Photo selection screen, but this wont fly with Apple's approval process.
-(void)choosePhotoDialog:(id)sender
{
UIBarButtonItem * barThing = (UIBarButtonItem*)sender;
OverlayView * overlay = [[OverlayView alloc] initWithFrame: CGRectMake(0, 0, SCREEN_WIDTH_IPHONE, SCREEN_HEIGTH_IPHONE)
andPhotoOverlay: [dict objectForKey:#"imageUrl"]];
[overlay setUserInteractionEnabled: NO];
UIImagePickerController * picker = [[UIImagePickerController alloc] init];
switch (barThing.tag)
{
case 0: [picker setSourceType: UIImagePickerControllerSourceTypeCamera];
[picker setShowsCameraControls: YES];
[picker setCameraOverlayView: overlay];
break;
case 1: [picker setSourceType: UIImagePickerControllerSourceTypeSavedPhotosAlbum];
[picker.view addSubview: overlay];
[overlay setAlpha: 0.5f];
break;
}
[picker setDelegate: self];
[picker setAllowsEditing: YES];
[picker setNavigationBarHidden: YES];
[picker setWantsFullScreenLayout: YES];
[self presentModalViewController:picker animated:YES];
[picker release];
}
Question
What is the correct way to allow a user to select a photo from the PhotoLibrary with an Overlay using UIImagePickerControllerSourceTypeSavedPhotosAlbum?
Resolved
Basically, I needed to write 3 separate classes and combine them to create my own custom photo editing view, which also saves pinch / zoom / rotate edits.
I ended up writing several classes:
An OverlayView class which is a UIView and simply retrieves the .png image with transparency and is the bottom-most layer.
An InteractiveWallpaper class which is a UIImageView and handles all of the touch events, including the transformation events.
And finally, an EditingView class which is a UIViewController. This adds the 2 views previously mentioned as well as saves the photo that the user edited.
This also allowed me to customize the behavior of the view. When the user touches the imported photo, the top-most photo decreases it's alpha value, allowing the user to still see the overlay while the imported photo is more visible.
Related
I am pick Images using Camera in my app & try to show in horizontal scrollview.
But the images are overlapping
My code
-(IBAction)act_photo:(id)sender
{
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
//picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:picker animated:YES completion:NULL];
}
#pragma mark - Image Picker via Camera
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *chosenImage = info[UIImagePickerControllerOriginalImage];
[picker dismissViewControllerAnimated:YES completion:^{
[arr_images insertObject:chosenImage atIndex:0];
[self scrollImages_Setup2];
}];
}
-(void)scrollImages_Setup2
{
for (int k=0; k<arr_images.count; k++) {
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake((CGRectGetWidth(scl.frame) * k) + CGRectGetWidth(scl.frame), 0, CGRectGetWidth(scl.frame), CGRectGetHeight(scl.frame))];
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.image=[arr_images objectAtIndex:k] ;
[scl addSubview:imageView];
}
scl.contentSize = CGSizeMake((CGRectGetWidth(scl.frame) * arr_images.count)+CGRectGetWidth(scl.frame), CGRectGetHeight(scl.frame));
}
Problem
Image1
Image 2
As shown above first I was taken Landscape Image2 & then I was taken Portrait Image 1 .
but as you see, Image 1 has background of Image2.
I think this is because there is something going wrong with scrollview?
Possiblity 2(mostly) Scrollview keeps strong reference of Imageview evenif it is deleted from array
Let me know how to solve this?
Help me to solve this
Thanks
You need to set Y value in you loop, your image Y value same any time,
Each time you take a new image, your completion-Handler puts the new image as the first element into your array and then calls [self scrollImages_Setup2]; where you iterate over all elements in your array and add them as new subviews to your scrollview.
When you take the first image (Image1) it's getting added to the array and then added as and subview to your scrollview. When you take the second image (Image2) it's getting added to the array as the first element. So then there are two elements in the array (Image2 and Image1) which are both getting added as subview to the scrollview. But Image1 has already been added to the scrollview, so that's causing your problem.
A solution to your problem could be either to always add only the new image and calculate the x position with the number of elements in your array, or to always remove all subviews before you add and layout all images again.
I have a simple application with only one button.
When user clicks on it, he can take a pictures, click "Done" in the camera and then can save it and see it on the ScrollView.
However, when he is taking another picture and clicking "Done" in the camera, the new picture overwrites the previous one and he can see only the picture that he has taken.
I want to save all these pictures and then if the user takes 4-5 pictures, he can see all of them by scrolling them.
Here is my code, im not sure why it is not working.
- (IBAction)Camera:(id)sender {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:picker animated:YES completion:NULL];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
NSMutableArray *images = [NSMutableArray arrayWithCapacity:[info count]];
for (UIView *v in [_scrollView subviews]) {
[v removeFromSuperview];
}
[self dismissViewControllerAnimated:YES completion:nil];
UIImage* image=[info valueForKey:#"UIImagePickerControllerEditedImage"];
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
UIImageView *imageview = [[UIImageView alloc] initWithImage:image];
[_scrollView addSubview:imageview];
[images addObject:image];
self.chosenImages = images;
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
[_scrollView setPagingEnabled:YES];
}
And in header i have an array of chosenImages
#property (nonatomic, copy) NSArray *chosenImages;
There are lots of things wrong with your code. Every time the user picks an image, you remove all the subviews from your scroll view, then add just the single selected image.
You have an array chosenImages which you might use to hold all the selected images, but you replace it with a new array, images, which only contains the single newly selected image.
You allocate images as a mutable array with enough capacity for the count of the info dictionary you get in didFinishPickingMediaWithInfo, but there's no point to doing that. The count of that dictionary is going to be the number of key/value pairs in the dictionary, which does not reflect the number of images the user selected (I believe the number of images the user selected will always be 1, ignoring the different formats like the original image and the (possible) edited image.)
I would suggest leaving the previous images in your scroll view, tracking the number and placement of those images, and simply adding a new image to the scroll view after the user picks.
You might think about using a UIPageViewController in page scroll mode rather than a raw scroll view. It manages paged scrolling much better than a scrollview will. There is a sample app from Apple called PhotoScroller (link) that even supports tiled rendering of the images, pinch-to-zoom, and panning around an image. It would be pretty easy to stitch that code into your app for handling these images. (You might not decide to deal with the tiled images - I adapted the PhotoScroller code, with tiled image support, into a client project, and generating the image tiles is a fair amount of work.)
Assuming that self.chosenImages is of NSMutableArray type, try this
[self.chosenImages addObjectsFromArray:images]
instead of
self.chosenImages = images;
and if it isn't mutable, you can always set it like so:
NSMutableArray *newArray = [self.chosenImages mutableCopy];
newArray = [newArray addObjectsFromArray:images];
self.chosenImages = [newArray copy];
I have a routine that I use to trigger the camera to take a photo. After the camera takes the photo the user is then given an option to crop the image by default before the delegate passes me back the UIImage. Is there any way that I can pass in a dynamic CGRect to make this default crop area a specific size? One thing I should mention is that the application is a landscape iPad application.
Here is a code sample:
-(void)triggerCamera:(id)sender
{
UIImagePickerController *camera = [[UIImagePickerController alloc] init];
camera.delegate = self;
camera.allowsEditing = YES;
camera.sourceType = UIImagePickerControllerSourceTypeCamera;
//pass in some sort of CGRect ??
[self presentViewController:camera animated:YES completion:NULL];
}
-(void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info {
UIImage *img = [info objectForKey: UIImagePickerControllerOriginalImage];
//process my image further
}
Unfortunately you can't set crop size. I was dealing with same problem over 2 years ago and I got stuck with creating my own viewController for cropping image.
Maybe take a look at GKImagePicker on GitHub. This project hasn't had much activity in the past few months (maybe more), but could be worth a shot. It even comes with an option to have a resizable crop area. I have not tried it myself, but the implementation looks to be pretty simple:
self.imagePicker = [[GKImagePicker alloc] init];
self.imagePicker.cropSize = CGSizeMake(320, 90);
self.imagePicker.delegate = self;
[self presentModalViewController:self.imagePicker.imagePickerController animated:YES];
I 'm trying to take a shot and it works, but with 2 problems. First, the pop over controller is displayed in a minimum size (it doesn't obey the setPopoverContentSize) and second and most important, the captured shot is only 640x640 pixels, whereas I want to be the maximum available (5MP).
What's the problem in the following code?
imgPicker = [[UIImagePickerController alloc] init];
imgPicker.delegate = self;
imgPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imgPicker.showsCameraControls = YES;
pop = [[UIPopoverController alloc] initWithContentViewController:imgPicker];
pop.delegate = self;
CGRect re = CGRectMake(50,20,100,20);
CGRect re2 = CGRectMake(0,0,500,500);
[pop setPopoverContentSize:re2.size];
[pop presentPopoverFromRect:re inView:[self view] permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
Thanks a lot
You are setting the content size incorrectly. You don't call setPopoverContentSize: on the popover, you call it on the view controller that is displayed in the popover. In your case, set the content size of the image picker.
The image received from the image picker is the full sized image. Perhaps you are obtaining the edited image instead of the original image.
I am trying to add some basic functionality to a camera application.
The app works like this: You press the camera button somewhere in the app, the camera activates and then gives you some extra basic functionality aside from the flash, switchcameras, cancel and take picture buttons.
Having clicked through quite a bit of search results it seems like only a new cameraoverlay is possible.
Now, I've managed to show some text or a button on itsself somewhere on the camera screen following the scanning example on musicalgeometry.com.
But what I'm trying to do here is add an entire view, constructed in IB, as a cameraOverlay. (for example just a toolbar with some buttons and the rest is blank).
Can I use storyboards for this or is this easier working with Nib files?
Or can the toolbar be programmatically added to a UIView so it can serve as cameraOverlay?
I would think the latter (programmatically) is the most straight forward but I haven't been able to find any examples for either possible solution so anything is welcome.
This is the basic overlay code from the example:
- (void) viewDidAppear:(BOOL)animated {
OverlayView *overlay =
[[OverlayView alloc] initWithFrame:CGRectMake(
0, 0, SCREEN_WIDTH, SCREEN_HEIGTH)];
// Create a new image picker instance:
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
// Set the image picker source:
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
// Hide the controls:
picker.showsCameraControls = NO;
picker.navigationBarHidden = YES;
// Make camera view full screen:
picker.wantsFullScreenLayout = YES;
picker.cameraViewTransform = CGAffineTransformScale(picker.cameraViewTransform,
CAMERA_TRANSFORM_X, CAMERA_TRANSFORM_Y);
// Insert the overlay:
picker.cameraOverlayView = overlay;
// Show the picker:
[self presentModalViewController:picker animated:YES];
[picker release];
[super viewDidAppear:YES];
}