I am using the UIImagePickerController to select images for my app. But I am facing a issue with the aspect ratio of the selected images.The image is showing larger than its original size and the complete image is not shown.I have tried changing UIViewContentMode property to all possible values still no use.Can anyone guide me how to make it work in?
Here is the implementation of UIImagePickerController delegate
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingImage:(UIImage *)image
editingInfo:(NSDictionary *)editingInfo {
self.imageProfile.contentMode = UIViewContentModeScaleAspectFit;
self.imageProfile.image = image;
[picker dismissViewControllerAnimated:YES completion:nil];
}
Well as you are using autolayouts, first define an outlet with your image height constraint will called imageHeightConstraint and then modify your code with this one
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingImage:(UIImage *)image
editingInfo:(NSDictionary *)editingInfo {
float aspectRatio = image.size.height/image.size.width
self.imageProfile.contentMode = UIViewContentModeScaleAspectFit;
self.imageProfile.image = image;
[self.imageHeightConstraint setConstant: self.imageProfile.frame.size.width * aspectRatio];
[picker dismissViewControllerAnimated:YES completion:nil];
}
EDITED
this is my code
#import "ViewController.h"
#interface ViewController () <UINavigationControllerDelegate,UIImagePickerControllerDelegate>
#property (weak, nonatomic) IBOutlet UIImageView *imageProfile;
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *imageConstraintHeigth;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (IBAction)selectImage:(id)sender {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:picker animated:YES completion:NULL];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(nullable NSDictionary<NSString *,id> *)editingInfo{
float aspectRatio = image.size.height/image.size.width;
self.imageProfile.contentMode = UIViewContentModeScaleAspectFit;
self.imageProfile.image = image;
//this if you need adjust heigth according to width
[self.imageConstraintHeigth setConstant: self.imageProfile.frame.size.width * aspectRatio];
[picker dismissViewControllerAnimated:YES completion:nil];
}
#end
and this are my constraints
I hope this help, for me works just fine
Related
When I take a picture with the phone in Portrait mode, using a UIImagePickerController, the UIImage item that is returned has the top of the image facing left and an imageOrientation property of UIImageOrientationRight , // 90 deg CCW, which is as expected (I think).
When I share the image via a UIActivityViewController, all activities seem to behave correctly except for the Copy activity. When I paste the image into another application (for instance, Messages), the image seems to be ignoring the imageOrientation property.
Has anyone else seen this / found a workaround?
Updated with complete code: (project contains storyboard with a single button mapped to self.takeImageButton and - (IBAction)takeImageAndShare:(id)sender;)
#import "ViewController.h"
#interface ViewController () <UIImagePickerControllerDelegate,UINavigationControllerDelegate>
#property (weak, nonatomic) IBOutlet UIButton *takeImageButton;
#end
#implementation ViewController
- (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)takeImageAndShare:(id)sender {
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.popoverPresentationController.sourceView = self.takeImageButton;
[self presentViewController:imagePicker animated:YES completion:nil];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *chosenImage = info[UIImagePickerControllerOriginalImage];
[picker dismissViewControllerAnimated:YES completion:NULL];
NSLog(#"Image Orientation: %li",chosenImage.imageOrientation);
// Now share the selected image
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:#[chosenImage] applicationActivities:nil];
activityViewController.modalPresentationStyle = UIModalPresentationPopover;
activityViewController.popoverPresentationController.sourceView = self.takeImageButton;
[self presentViewController:activityViewController animated:YES completion:nil];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker;
{
[picker dismissViewControllerAnimated:YES completion:NULL];
}
#end
If you run this code, take a photo with the phone in Portrait (.imageOrientation is 3 = UIImageOrientationRight) and select share activities like Messages, Save Image, etc., the image orientation is correct. If you select the copy activity, the image that gets pasted elsewhere is rotated (top of the image is to the left).
Submitted as Radar 19456881. Complete project is available here.
By Default capture image orientation behavior is UIImageOrientationRight, sp you have to set capture image orientation is
[UIDevice currentDevice].orientation
Based on this post, I decided to create my own copy activity:
//
// PhotoActivityCopy.m
//
// Created by Jeff Vautin on 1/13/15.
// Copyright (c) 2015 Jeff Vautin. All rights reserved.
//
#import "PhotoActivityCopy.h"
#import "ImageKit.h"
#import MobileCoreServices;
#interface PhotoActivityCopy ()
#property (strong,nonatomic) NSData *imageJPEGData;
#end
#implementation PhotoActivityCopy
NSString *PhotoActivityCopyActivityType = #"com.me.uiactivitytype.copy";
NSString *PhotoActivityCopyActivityTitle = #"Copy";
+ (UIActivityCategory)activityCategory
{
return UIActivityCategoryAction;
}
- (NSString *)activityType
{
return PhotoActivityCopyActivityType;
}
- (NSString *)activityTitle
{
return PhotoActivityCopyActivityTitle;
}
- (UIImage *)activityImage
{
CGSize imageSize;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
imageSize = CGSizeMake(76.0, 76.0);
} else {
imageSize = CGSizeMake(60.0, 60.0);
}
return [ImageKit imageOfIconCopyWithExportSize:imageSize];
}
- (BOOL)canPerformWithActivityItems:(NSArray *)activityItems
{
BOOL canPerform = NO;
if ([activityItems count] > 1) {
canPerform = NO;
} else if ([[activityItems firstObject] isKindOfClass:[UIImage class]]) {
canPerform = YES;
}
return canPerform;
}
- (void)prepareWithActivityItems:(NSArray *)activityItems
{
self.imageJPEGData = UIImageJPEGRepresentation(activityItems[0], 1.0);
}
- (void)performActivity
{
[[UIPasteboard generalPasteboard] setData:self.imageJPEGData forPasteboardType:(id)kUTTypeJPEG];
[self activityDidFinish:YES];
}
#end
And then I excluded the native copy activity:
PhotoActivityCopy *copyActivity = [[PhotoActivityCopy alloc] init];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:#[chosenImage] applicationActivities:#[copyActivity]];
activityViewController.excludedActivityTypes = #[UIActivityTypeCopyToPasteboard];
I have a UImage view that opens and you can take a picture with it and view it in the uiimageview. But I added another image view and copied the code and now the image shows up the same image as the second one. I believe it may have something to do with the '[UIImagePickerControllerOriginalImage];'
- (void)imagePickerController:(UIImagePickerController *)
picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[self dismissViewControllerAnimated:YES completion:nil];
// Get the image and store it in the image view
image = info[UIImagePickerControllerOriginalImage];
self.personimgThumbNail.image = image;
}
- (void)imagePickerControllertwo:(UIImagePickerController *)
picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[self dismissViewControllerAnimated:YES completion:nil];
// Get the image and store it in the image view
imagetwo = info[UIImagePickerControllerOriginalImage];
self.personimgThumbNailtwo.image = imagetwo;
}
Just need a next step, been stuck on this one for quite a while.
There can be only one didFinish-Method. You have to differentiate between what to do inside the method itself. The method already gives you the UIImagePickerController, which is calling the method, so you just have to compare the pointers to it.
- (void)imagePickerController:(UIImagePickerController *)
picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[self dismissViewControllerAnimated:YES completion:nil];
if(picker == self.pickerController1){
// Get the image and store it in the image view
image = info[UIImagePickerControllerOriginalImage];
self.personimgThumbNail.image = image;
}else if(picker == self.pickerController2){
// Get the image and store it in the image view
imagetwo = info[UIImagePickerControllerOriginalImage];
self.personimgThumbNailtwo.image = imagetwo;
}
}
Edit: You have to have 2 properties defined in the .m file of your class
#property (strong) UIImagePickerController *pickerController1;
#property (strong) UIImagePickerController *pickerController2;
What you have to do now, when instantiating your image-picker is the following
(code taken from the OPs comment under this answer)
- (IBAction)accessPhotoLibrary:(id)sender {
if(!self.pickerController1){
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.delegate = self;
self.pickerController1 = imagePicker;
}
[self presentViewController:self.pickerController1 animated:YES completion:nil];
}
I have 2 questions relating to button images:
Setting a button image
Changing an image to a circular image
I have an iPhone application that has a UIButton created in Storyboard. Using the Attributes Inspector, I have set the buttons image to be an image that I created and added to the project.
The button will allow users to add a profile picture.
When I click the button, I ask the user to either use the phones camera to take an image or to select an image from camera roll.
This all works and I can access the camera to take a picture as well as camera roll image gallery to select an image.
My question is:
1.
How do I set the button image to the user-selected image?
In my didFinishPickingMediaWithInfo method I have:
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
// Set the image of the Button to the selected image
[sender setImage:image forState:UIControlStateNormal];
But I get error "Use of undeclared identifier" - because my button isn't the sender.
How do I set my button image as the image from the camera or camera roll image? If I create the button programatically I can set the image but it seems like a lot of unnecessary work to do if the button is created in Storyboard already?
Or do I need to create the button programatically to do this?
2.
I try to mask the image to have a rounded appearance in my didFinishPickingMediaWithInfo but I am unable to do so. How do I do this? I can make the image rounded by pacing the code below in my viewDidLoad but it does not work in my didFinishPickingMediaWithInfo
self.image.layer.cornerRadius = self.profileImageView.frame.size.width / 2;
self.image.clipsToBounds = YES;
Here is an example:
#import "MyViewController.h"
#import <QuartzCore/QuartzCore.h>
#interface MyViewController () <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
#property (weak, nonatomic) IBOutlet UIButton *profilePictureButton;
#end
#implementation MyViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
// make the button a circle.
_profilePictureButton.imageView.contentMode = UIViewContentModeScaleAspectFill;
_profilePictureButton.imageView.layer.cornerRadius = _profilePictureButton.frame.size.width / 2.f;
}
- (IBAction)takePicture:(id)sender
{
UIImagePickerController *imagePickerController = [UIImagePickerController new];
imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
imagePickerController.delegate = self;
[self presentViewController:imagePickerController
animated:YES
completion:nil];
}
#pragma mark - UIImagePickerControllerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
[_profilePictureButton setImage:image forState:UIControlStateNormal];
[picker dismissViewControllerAnimated:YES
completion:nil];
}
#end
You have to make sure that the button's type is UIButtonTypeCustom or this won't work at all.
Make sure you have an IBOutlet set up for the UIButton as cameraButton, and make sure your UIButton is set to a "Custom" type.
Make your view controller conform to the
#interface ViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
Tie your UIButton's TouchUpInside event to the following IBAction:
-(IBAction)showCameraAction:(id)sender
{
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:picker animated:YES completion:NULL];
}
In your view controller, put the following delegate implementation methods.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *chosenImage = info[UIImagePickerControllerEditedImage];
[self.cameraButton setImage:chosenImage forState:UIControlStateNormal];
self.cameraButton.clipsToBounds = YES;
self.cameraButton.layer.cornerRadius = (self.cameraButton.frame.size.width / 2);//half of the width
self.cameraButton.layer.borderColor=[UIColor blackColor].CGColor;
self.cameraButton.layer.borderWidth=1.0f;
[picker dismissViewControllerAnimated:YES completion:NULL];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissViewControllerAnimated:YES completion:NULL];
}
I did all this, and ended up with a button I could tap that would bring up the camera, and after taking a picture, would display a circular mask of the image with a black border around it. Feel free to remove the border by setting borderWidth to 0.
im pretty newish to this kind of coding but have learnt a fair bit and have unfortunately hit a bump in an app im working on.
I am trying to create a camera application that will allow the user to take a 'before' image, then take an 'after' image, I would then like the option for the images to be put together (left and right) and saved as one image.
So far I have managed to code the app to take a single picture with the code below:
HEADER:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
#property (strong, nonatomic) IBOutlet UIImageView *beforeImage;
- (IBAction)cameraBeforeImage:(UIButton *)sender;
- (IBAction)libraryBeforeImage:(UIButton *)sender;
- (IBAction)deleteBeforeImage:(UIButton *)sender;
#property (strong, nonatomic) IBOutlet UIImageView *afterImage;
- (IBAction)cameraAfterImage:(UIButton *)sender;
- (IBAction)libraryAfterImage:(UIButton *)sender;
- (IBAction)deleteAfterImage:(UIButton *)sender;
- (IBAction)saveImages:(UIButton *)sender;
#end
IMPLEMENTATION:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)cameraBeforeImage:(UIButton *)sender {
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
UIAlertView *myAlertView = [[UIAlertView alloc] initWithTitle:#"Oops!"
message:#"This Device Has No Camera, Please Select An Image From Your Library."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles: nil];
[myAlertView show];
}else{
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:picker animated:YES completion:NULL];
}
}
- (IBAction)libraryBeforeImage:(UIButton *)sender {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:picker animated:YES completion:NULL];
}
- (IBAction)deleteAfterImage:(UIButton *)sender {
}
- (IBAction)saveImages:(UIButton *)sender {
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *chosenImage = info[UIImagePickerControllerEditedImage];
self.beforeImage.image = chosenImage;
[picker dismissViewControllerAnimated:YES completion:NULL];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissViewControllerAnimated:YES completion:NULL];
}
- (IBAction)deleteBeforeImage:(UIButton *)sender {
}
- (IBAction)cameraAfterImage:(UIButton *)sender {
}
- (IBAction)libraryAfterImage:(UIButton *)sender {
}
- (IBAction)saveImages:(UIButton *)sender {
}
#end
Here is the list of things I need to add, any help on any of them would be very much appreciated!
Add the same functionality to the 'After' buttons as the 'Before' but to store the image in the 'afterImage' Image view.
Add functionality to the 'saveImages' button to save the two taken images as one image stitched together.
Thank you all in advance!
1 . The first problem, I guess you question is 'How do you know which picture was taken and where to display it'?
Answer1: Create two UIImagePickerControllers as properties. Once imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info returns an image you can simply check which controller was it if( picker == afterPictureController){....
Answer2: Create a flag indicating whether the next taken picture will be an after or a before picture. It's not very flexible but it works.
2 . To stitch two images, you can create UIGraphicsBeginImageContext with size(image1Width+image2Width, MAX(image1Height, image2Height)) and draw image using the context. After that, you can get the stitched image from the context by calling UIGraphicsGetImageFromCurrentImageContext();
I've checked several tutorials and from what I can tell my code is correct, but at the end I don't get the image. I don't get any error, but the image on the screen I'm trying to set is still blank.
Here's my header file
#interface homeViewController : UIViewController<UIImagePickerControllerDelegate, UINavigationControllerDelegate>
#property (weak, nonatomic) IBOutlet UIImageView *avatarImage;
#property (weak, nonatomic) IBOutlet UIButton *photoButton;
#property (nonatomic, retain) UIImagePickerController *imgPicker;
- (IBAction)setPhoto;
#end
And here's the related methods
- (IBAction)setPhoto
{
self.imgPicker = [[UIImagePickerController alloc] init];
self.imgPicker.sourceType=UIImagePickerControllerSourceTypeCamera;
self.imgPicker.delegate=self;
self.imgPicker.allowsEditing = YES;
self.imgPicker.showsCameraControls=YES;
[self presentModalViewController:self.imgPicker animated:YES];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[picker dismissModalViewControllerAnimated:YES];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
self.avatarImage = [[UIImageView alloc] init];
self.avatarImage.image = image;
[self dismissModalViewControllerAnimated:YES];
}
When I place a breakpoint here: [self dismissModalViewControllerAnimated:YES];
I see that the image variable has a value, but the self.avatarImage has a 0x00000000
Since you specified allowsEditing = NO you need to use the UIImagePickerControllerOriginalImage info key.
Note: it may be that 'EditedImage' defaults to 'OriginalImage' if no editing occurs. In that case your 'image' variable will be valid and the display of the UIImageView in self.avatarView will be the culprit.
You are using the wrong delegate method. Use
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
The delegate method you are using was deprecated in iOS 3.0.
The lines
[picker dismissModalViewControllerAnimated:YES];
[picker release];
Have to appear before using the info dictionary.