How can I assure that UIImagePickerController always returns a squared image?
WhatsApp does it but I have not found a way to achieve this.
How it is in my App (Build in iOS 7)
How it should be (WhatsApp - iOS 6)
My code:
- (IBAction)showImagePicker:(id)sender {
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.allowsEditing = YES;
if ([sender tag] == 1) {
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
}
else {
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
}
[self presentModalViewController:imagePicker animated:YES];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
_imageView.image = [info objectForKey:UIImagePickerControllerEditedImage];
[self dismissModalViewControllerAnimated:YES];
}
well to change the size of the image captured you need to set the mode for view in your UIImageView in IB to scale to fill. then when the image is chosen from library or from camera, it automaticaly will be resized. you do have to turn the autolayout off though since it wont allow the ImageView to be resized. you code is fine. anyhow here is sample app codes you can build to understand it a bit better.
.h
#import <UIKit/UIKit.h>
#interface ImageTestViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
#property (strong, nonatomic) IBOutlet UIImageView *imageView;
- (IBAction)takePhoto: (UIButton *)sender;
- (IBAction)selectPhoto:(UIButton *)sender;
#end
.m
#import "ImageTestController.h"
#interface ImageTestViewController ()
#end
#implementation ImageTestViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
UIAlertView *myAlertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Device has no camera"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles: nil];
[myAlertView show];
}
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
}
- (IBAction)takePhoto:(UIButton *)sender {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:picker animated:YES completion:NULL];
}
- (IBAction)selectPhoto:(UIButton *)sender {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:picker animated:YES completion:NULL];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *chosenImage = info[UIImagePickerControllerEditedImage];
self.imageView.image = chosenImage;
[picker dismissViewControllerAnimated:YES completion:NULL];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissViewControllerAnimated:YES completion:NULL];
}
#end
in the ImageTestController Xib or view in storyboard, place two buttons, one for each action and create the necessary links in IB. then place a UIImageView to fill whatever size you want in the view. click the UIImageView and in view section of attribute inspector change the mode to scale to fill. turn the autolayout off. try adding an image to your simulator just to test it. make sure the image is of the landscape size. build and run and when you select the image from image library, it will automatically resize to square or any other size you set your UIImageView.
i know you are aware of most of the steps above, but i wrote this answer not to just help you get rid of your issue but for others that may have similar issues. hope it helps you out man.
Related
Im newish to Objective-C and I want to create an app with that will eventually take pictures with the camera but with images overlaid. But I thought I would start with a simple camera app just to get the base for it. I have followed a tutorial for creating a app that you can take pictures with and access image library. BUT when I build it to my iPhone 4s it just loads a white screen. If any one could take a look at the code, but I think its right and offer an answer it would be great thanks.
//ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
<UIImagePickerControllerDelegate, UINavigationControllerDelegate>
#property (strong, nonatomic) IBOutlet UIImageView *imageView;
- (IBAction)takePhoto:(UIButton *)sender;
- (IBAction)selectPhoto:(UIButton *)sender;
#end
//ViewController.m
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
UIAlertView *myAlertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Device has no camera"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles: nil];
[myAlertView show];
}
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
}
- (IBAction)takePhoto:(UIButton *)sender {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:picker animated:YES completion:NULL];
}
- (IBAction)selectPhoto:(UIButton *)sender {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:picker animated:YES completion:NULL];
}
#pragma mark - Image Picker Controller delegate methods
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *chosenImage = info[UIImagePickerControllerEditedImage];
self.imageView.image = chosenImage;
[picker dismissViewControllerAnimated:YES completion:NULL];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissViewControllerAnimated:YES completion:NULL];
}
#end
I am trying to display a UIImagePicker from a programatically generated UIView that's added as a subview of the original view controller. The image picker comes up and so does the camera but the functionality breaks and nothing navigates properly. How do I properly load an image picker from a UIView and not a UIControlView?
code that breaks:
- (void)captureImage:(id)sender
{
[[[UIActionSheet alloc] initWithTitle:nil
delegate:self
cancelButtonTitle:#"Close"
destructiveButtonTitle:nil
otherButtonTitles:#"Take photo", #"Camera Roll", nil]
showInView:self];
}
//UIImagePicker specific methods
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
switch (buttonIndex)
{
case 0:
[self takePhoto];
break;
case 1:
[self fromCameraRoll];
break;
}
}
-(void)takePhoto
{
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] == YES)
{
// Create image picker controller
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
// Set source to the camera
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
// Delegate is self
imagePicker.delegate = self;
// Show image picker
[self addSubview:imagePicker.view];
}
}
-(void)fromCameraRoll
{
UIImagePickerController *imgPicker = [[UIImagePickerController alloc] init];
imgPicker.delegate = self;
imgPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self addSubview:imgPicker.view];
}
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// Access the uncropped image from info dictionary
UIImage *image = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
//do something with the image
//add code to pick images here and store them in the preview
[picker dismissModalViewControllerAnimated:NO];
}
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[picker dismissModalViewControllerAnimated:NO];
}
UIImagePickerController is view controller class, you better present your image picker to your parent view controller by a delegate call or something like with an overlay subview to achieve your goal.
UIImagePickerController *imgPicker = [[UIImagePickerController alloc] init];
imgPicker.delegate = self;
imgPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
CustomOverlayView *overlayview = [[CustomOverlayView alloc] init];
imgPicker.cameraOverlayView = overlayview;
[self presentModelViewController:imgPicker animated:YES];
add another delegate in your overlay class to dismiss your camera picker controller view
[imgPicker dismissModelViewControllerAnimated:YES];
I am trying out a simple camera app for practice. Was following these examples: iOS 6 App
and iOS 4 App
My code looks like this:
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController<UINavigationControllerDelegate, UIImagePickerControllerDelegate>
{
UIButton *button;
UIImageView *imageView;
}
#property (nonatomic, retain) IBOutlet UIImageView *imageView;
- (IBAction)useCamera;
- (IBAction)useCameraRoll;
#end
ViewController.m
#import "ViewController.h"
#import <MobileCoreServices/MobileCoreServices.h>
#interface ViewController ()
#end
#implementation ViewController
#synthesize imageView;
- (void) alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)buttonIndex
{
// After saving iamge, dismiss camera
[self dismissViewControllerAnimated:YES completion:NULL];
}
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
UIAlertView *alert;
// Unable to save the image
if (error)
alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Unable to save image to Photo Album."
delegate:self cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
else // All is well
alert = [[UIAlertView alloc] initWithTitle:#"Success"
message:#"Image saved to Photo Album."
delegate:self cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alert show];
}
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// Access the uncropped image from info dictionary
UIImage *image = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
// Save image
UIImageWriteToSavedPhotosAlbum(image, self, #selector(image:didFinishSavingWithError:contextInfo:), nil);
}
- (id)init
{
if (self = [super init])
{
self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
self.view.backgroundColor = [UIColor grayColor];
// Button to activate camera
button = [[UIButton alloc] initWithFrame:CGRectMake(80, 55, 162, 53)];
[button setBackgroundImage:[UIImage imageNamed:#"Camera.png"] forState:UIControlStateNormal];
[button addTarget:self action:#selector(buttonPressed:) forControlEvents: UIControlEventTouchUpInside];
[self.view addSubview:button];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)useCamera
{
if ([UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypeCamera])
{
UIImagePickerController *imagePicker =
[[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType =
UIImagePickerControllerSourceTypeCamera;
imagePicker.mediaTypes = [NSArray arrayWithObjects:
(NSString *) kUTTypeImage,
nil];
imagePicker.allowsEditing = NO;
[self presentViewController:imagePicker animated:YES completion:nil];
}
}
- (IBAction)useCameraRoll
{
if ([UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypeSavedPhotosAlbum])
{
UIImagePickerController *imagePicker =
[[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType =
UIImagePickerControllerSourceTypePhotoLibrary;
imagePicker.mediaTypes = [NSArray arrayWithObjects:
(NSString *) kUTTypeImage,
nil];
imagePicker.allowsEditing = NO;
[self presentViewController:imagePicker animated:YES completion:nil];
}
}
#end
My problem I like to access the camera from the app itself. What happens is that when i click useCamera button, it opens up the camera and take the image. Is it possible it could do that from the app itself? Sorry if it is a stupid question. Do point me out if I am doing something wrong.
Yes, use the UIImagePickerController class.
When the camera button is clicked, present an instance of UIImagePickerController. Also, since some iOS devices like the original iPad or some older iPod touches don't have cameras, I wouldn't recommend using separate buttons/methods for taking a new picture vs using one from the saved photos. Use one button and set its source type based on the device's capabilities using the available methods in the class. It may require rethinking your app's design, but it's also more likely to pass Apple's UI inspection, as they may not approve an app that has a button exclusively for taking a picture but can run on a device without a camera.
Once the user has either taken a new photo or chosen a photo from either the camera roll, use the imagePickerController:didFinishPickingMediaWithInfo: method from the UIImagePickerControllerDelegate class to pass the user's choice to your code.
Instances of UIImagePickerController are designed to be presented modally on all iOS devices when using the camera. Remember, as the name suggests, they are controllers and NOT views, so they shouldn't be used as subviews of UIView. While it may be possible to get creative with how you present it, you'll almost certainly have some side-effects and you'll further increase the chance that Apple will reject it. It only SEEMS like it's getting out the app to take the photo, but because you're presenting the controller from your app, it's still very much a part of it. Apple doesn't allow direct access to the camera hardware, which is exactly why they've created this class.
I have a hierarchy of views:
compView with two children:
bgView
objectView.
I'm passing objectView to the cameraOverlayView property of the UIImagePickerController. Once the ImagePicker is done I update the image in the bgView and I would like to continue to display the view tree including the objectView which was passed to the UIImagePickerController as an overlayView.
The problem is that after calling dismissModalViewControllerAnimated to close the UIImagePickerController, the objectView is not appearing, as if the UIImagePickerContoller is hiding it. I checked in the debugger and it doesn't seem to be dealocated. The pointer is still valid. But the view is not showing.
Any ideas of what I might be doing wrong?
Thanks,
Eddy
Here a bit of code to show you what I'm doing:
From myViewController.m:
- (void)loadView {
CGRect rect = self.navigationController.view.bounds;
compView = [[UIView alloc] initWithFrame:rect];
bgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Storage/dummy_bg.png"]];
objectView = [[PropImageView alloc] initWithImage:[UIImage imageNamed:#"Storage/rasta.png"]];
[objectView setUserInteractionEnabled:YES];
[objectView setMultipleTouchEnabled:YES];
[compView addSubview:bgView];
[compView addSubview:objectView];
self.view = compView;
[self placeObject];
[objectView release];
[bgView release];
[compView release];
}
- (void) placeObject
{
NSLog(#"camera button pressed");
// make sure camera is avaialble before setting it as source
//
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
#if !TARGET_IPHONE_SIMULATOR
UIImagePickerController* picker = [[UIImagePickerController alloc] init];
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.delegate = self;
picker.allowsEditing = NO;
picker.view.hidden = NO;
picker.cameraOverlayView = objectView;
[self presentModalViewController:picker animated:NO];
[picker release];
#endif
}
// from PickImageAppDelegate.m
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo
{
// Dismiss the image selection, hide the picker and
[picker dismissModalViewControllerAnimated:YES];
bgView.image = [self rotateImage:image byOrientationFlag:UIImageOrientationRight];
}
[picker dismissModalViewControllerAnimated:YES];
That should be
[self dismissModalViewControllerAnimated:YES];
I've got a very simple app where the user selects a UIImageView and presses a button to take a photo with the camera. The image is then returned and displayed in the UIImageView.
However, since the UIImageViews are sharing the same delegate, when there's already an image in one of the UIImageViews, and I go to take a photo to be placed in another, the previous UIImageView is replaced with empty content (i.e. no image). I guess this is because they're sharing the same delegate. Is there any way I can essentially copy the image instead of referencing the delegate version of it?
Here's some sample code:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo {
[picker.parentViewController dismissModalViewControllerAnimated:YES];
if (topView == YES)
{
NSLog(#"topView = %i", topView);
imageView.image = image;
}
else {
NSLog(#"topView = %i", topView);
imageView2.image = image;
}
}
Thanks!
Edit: Here's the code that gets called by the IBAction on the button presses
- (IBAction) pushPick {
topView = YES;
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentModalViewController:picker animated:YES];
[picker release];
}
- (IBAction) pushPick2 {
topView = NO;
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentModalViewController:picker animated:YES];
[picker release];
}
Something like this:
UIImage * newImage = [UIImage imageWithCGImage:[image CGImage]];
use
[image copy];
But remember that you will need to release the object on dealloc