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();
Related
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
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 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.
I want it to flow like this I'm doing it tons of times and dosent work.
User pushes the photo button in the app and takes picture.
After taking the picture users has to input detail. sorts options comes out where user can pick 8 different default genre's, and user pushes save.
It goes back to the Home Screen and the User can see the 8 different genre in button & when pushed pictures comes out as a coverflow(flow cover) that is saved in the app. I want to make it work like the above but dosent work.
My Code is until now is:
#implementation ViewController
-(IBAction)TakePhoto {
picker = [[UIImagePickerController alloc]init];
picker.delegate = self;
[picker setSourceType: UIImagePickerControllerSourceTypeCamera ];
[self presentViewController:picker animated:YES completion:NULL];
}
-(IBAction)ChooseExisting{
picker2 = [[UIImagePickerController alloc]init];
picker2.delegate = self;
[picker2 setSourceType: UIImagePickerControllerSourceTypePhotoLibrary];
[self presentViewController:picker2 animated:YES completion:NULL];
}
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:
(NSDictionary *) info {
image = [info objectForKey:UIImagePickerControllerOriginalImage] ;
[imageview setImage:image];
[self dismissViewControllerAnimated:YES completion:NO];
}
- (void) imagePickerControllerDidCancel:(UIImagePickerController *)picker{
[self dismissViewControllerAnimated:YES completion:NULL];
}
#end
#implementation CVCLCoverFlowLayout
-(NSInteger)count {
return [self.collectionView numberOfItemsInSection:0 ];
}
-(CGSize)collectionViewContentSize{
CGSize size = self.collectionView.bounds.size;
size.width = self.count * self.cellInterval;
return size;
}
You are not saving the image you clicked in the delegate function .and when you want to use the saved image then you need to write down the code for same .:
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:
(NSDictionary *) info {
image = [info objectForKey:UIImagePickerControllerOriginalImage] ;
[imageview setImage:image];
/ save the image to local storage of your application /
[self dismissViewControllerAnimated:YES completion:NO];
}
You can check the code for same over :
http://dcraziee.wordpress.com/2013/05/20/how-to-save-and-get-image-from-cache-directory/
Please share the blog if you like it.
Two issues are showing up now that I want to update my app that previously worked fine in iOS4.x.x and below. Previous version of app running on iOS5.0.1 works though and I did not update any of the code around the camera functions
Camera - after user takes a picture, you get the standard "Retake" or "Use" buttons. Retake is fine but "Use" causes the app to freeze and crash.
Camera Roll - after user chooses image from camera roll, nothing appears to happen. It actually did select though -- but now you have to click "Cancel" and the image appears in the main window.
In both cases, no error messages in the debugging window so not sure what happened. Code for the two functions in question:
//Camera Method//////////////////////////
- (IBAction) cameraDeviceAction {
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] == YES) {
imgPicker = [[UIImagePickerController alloc] init];
imgPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imgPicker.delegate = self;
imgPicker.allowsImageEditing = NO;
if([ApplicationUtils getSystemVersionAsAnInteger] >= __IPHONE_3_1) {
if(cameraOverlayView == nil) {
cameraOverlayView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"photo_guideline_640x960.png"]];
cameraOverlayView.frame = CGRectMake(0, 0, 320, 431);
}
imgPicker.cameraOverlayView = cameraOverlayView;
}
[self presentModalViewController:imgPicker animated:YES];
}
}
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
[self showBackdropScreen:[info objectForKey:#"UIImagePickerControllerOriginalImage"]];
}
//Photo Library Method //////////////////////////
- (IBAction) libraryAction {
imgPicker = [[UIImagePickerController alloc] init];
imgPicker.allowsImageEditing = NO;
imgPicker.delegate = self;
[self presentModalViewController:imgPicker animated:YES];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo {
[self showBackdropScreen : img];
}
I believe that the error lies somewhere in there, but please let me know what you think or if you need more of the file.
Thanks!
Although it a old question but the answer is :
use [self dismissModalViewControllerAnimated:YES]; in function - (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info;in the end