i am trying to overlaying an image with another image. I have tried this But, its not exactly gives the output what i am expecting. Let me explain it clearly through below image,
Above is my ViewController where i am showing the Camera for taking the picture (Backgorund Image) using UIImagePickerController There is an Overlay Image i have placed. My overlay image can be rotate and zoom it :
if ([self isCameraAvailable] && [self doesCameraSupportTakingPhotos]) {
cameraPicker = [[UIImagePickerController alloc] init];
cameraPicker.delegate = self;
cameraPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
NSMutableArray *mediaTypes = [[NSMutableArray alloc] init];
[mediaTypes addObject:(__bridge NSString *)kUTTypeImage];
cameraPicker.mediaTypes = mediaTypes;
cameraPicker.showsCameraControls = NO;
cameraPicker.navigationBarHidden = YES;
cameraPicker.toolbarHidden = YES;
cameraPicker.delegate = self;
cameraPicker.allowsEditing = NO;
[self presentViewController:cameraPicker animated:YES completion:^{
overLayCustomView.hidden = NO;
[cameraPicker.view addSubview:overLayCustomView];
}];
}
Once, the picture has been taken, i have overlaid the image with captured image through below code :
NSString *mediaType = info[UIImagePickerControllerMediaType];
if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) {
UIImage *image = [self scaleAndRotateImage:[info objectForKey:UIImagePickerControllerOriginalImage]];
UIGraphicsBeginImageContextWithOptions(image.size, FALSE, 0.0);
[image drawInRect:CGRectMake( 0, 0, image.size.width, image.size.height)];
[renderedImage.image drawInRect:CGRectMake( renderedImage.frame.origin.x, renderedImage.frame.origin.y, renderedImage.frame.size.width, renderedImage.frame.size.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIImageWriteToSavedPhotosAlbum(newImage, nil, nil, nil);
UIGraphicsEndImageContext();
[picker dismissViewControllerAnimated:YES completion:^{
[self performSegueWithIdentifier:#"previewPage" sender:newImage];
}];
}
else if ([mediaType isEqualToString:(NSString *)kUTTypeMovie]) {
// Code here to support video if enabled
}
Code for scaleAndRotateImage
When, i tried these result for the image processing working weird. It gives below issues,
Captured image (Background Image) clarity has been lost.
Overlay image not placed exact point of the frame.
Frame of the overlay image changing and if its rotated not captured as rotated one.
Any, idea about my brief explanation with my code?
Update
Yeah, finally, i have achieved this and using AVCaptureSession to capture a Picture instead of using UIImagePickerController which would be an useful one. Now, the only thing is, My overlay image can be rotated though below one,
UIRotationGestureRecognizer *rotationRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(handleRotate:)];
[rotationRecognizer setDelegate:self];
[self.overLayImage addGestureRecognizer:rotationRecognizer];
- (void)handleRotate:(UIRotationGestureRecognizer *)recognizer {
recognizer.view.transform = CGAffineTransformRotate(recognizer.view.transform, recognizer.rotation);
recognizer.rotation = 0;
}
I am not able to overlay the rotated the overlay image into another one. Not able to get the rotated image? How can i achieve this?
Related
I want to develop a application in which user can change there hair style. so i add a overlay in camera view by using following code files and try to combine both image.
Here is my ViewController.h file
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController<UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIPopoverControllerDelegate>{
UIImagePickerController *imagePicker;
UIPopoverController *popoverController;
NSData *imageData;
}
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#end
and ViewController.m file
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// assign action to button
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
myButton.frame = CGRectMake(0, 0, 200, 60);
myButton.center = self.view.center;
[myButton addTarget:self action:#selector(buttonPress:) forControlEvents:UIControlEventTouchUpInside];
[myButton setTitle:#"Image Picker" forState:UIControlStateNormal];
[self.view addSubview:myButton];
}
- (void)buttonPress:(id)sender {
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
// alert the user that the camera can't be accessed
UIAlertView *noCameraAlert = [[UIAlertView alloc] initWithTitle:#"No Camera" message:#"Unable to access the camera!" delegate:nil cancelButtonTitle:#"Dismiss" otherButtonTitles:nil, nil];
[noCameraAlert show];
} else {
// prepare imagePicker view
imagePicker = [[UIImagePickerController alloc] init];
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.cameraDevice = UIImagePickerControllerCameraDeviceFront;
imagePicker.delegate = self;
imagePicker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
imagePicker.navigationBarHidden = YES;
imagePicker.toolbarHidden = YES;
imagePicker.extendedLayoutIncludesOpaqueBars = YES;
// create view for overlay
CGRect overlayRect = CGRectMake(0, 0, imagePicker.view.frame.size.width, imagePicker.view.frame.size.height-50);
UIView *overlayView = [[UIView alloc] initWithFrame:overlayRect];
// prepare the image to overlay
UIImageView *overlayImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"wig"]];
overlayImage.center = overlayView.center;
//overlayImage.alpha = 0.5;
[overlayView addSubview:overlayImage];
// add the image as the overlay
[imagePicker setCameraOverlayView:overlayView];
// display imagePicker
[self.navigationController presentViewController:imagePicker animated:YES completion:nil];
}
}
#pragma mark - UIBarButton Selectors
- (void)takePictureButtonPressed:(id)sender {
NSLog(#"takePictureButtonPressed...");
// TODO: take picture!
[self presentViewController:imagePicker animated:YES
completion:^ {
[imagePicker takePicture];
}];
}
- (void)startStopButtonPressed:(id)sender {
NSLog(#"startStopButtonPressed...");
// TODO: make this do something
}
- (void)timedButtonPressed:(id)sender {
NSLog(#"timedButtonPressed...");
// TODO: implement timer before calling takePictureButtonPressed
}
- (void)cancelButtonPressed:(id)sender {
NSLog(#"cancelButtonPressed");
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - UIImagePickerController Delegate Methods
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)editingInfo {
[picker dismissViewControllerAnimated:YES completion:NULL];
[popoverController dismissPopoverAnimated: YES];
NSData *image1 = UIImageJPEGRepresentation([editingInfo valueForKey:UIImagePickerControllerOriginalImage],1.0);
UIImage *Imgg = [self addOverlayToBaseImage:[editingInfo valueForKey:UIImagePickerControllerOriginalImage]];
image1 = UIImageJPEGRepresentation(Imgg,1.0);
imageData = image1;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *imagePath =[documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.png",#"cached"]];
NSLog((#"pre writing to file"));
if (![imageData writeToFile:imagePath atomically:NO])
{
NSLog((#"Failed to cache image data to disk"));
}
else
{
[[NSUserDefaults standardUserDefaults] setValue:imagePath forKey:#"imagePath"];
NSLog(#"the cachedImagedPath is %#",imagePath);
}
[self.imageView setImage:Imgg];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (UIImage*)addOverlayToBaseImage:(UIImage*)baseImage{
UIImage *overlayImage = [UIImage imageNamed:#"wig.png"];
CGPoint topCorner = CGPointMake(0, 0);
CGSize targetSize = CGSizeMake(self.view.frame.size.width, self.view.frame.size.height);
CGRect scaledRect = CGRectZero;
CGFloat scaledX = self.view.frame.size.height * baseImage.size.width / baseImage.size.height;
CGFloat offsetX = (scaledX - self.view.frame.size.width) / -2;
scaledRect.origin = CGPointMake(offsetX, 0.0);
scaledRect.size.width = scaledX;
scaledRect.size.height = self.view.frame.size.height;
UIGraphicsBeginImageContext(targetSize);
[baseImage drawInRect:scaledRect];
[overlayImage drawAtPoint:topCorner];
UIImage* result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result;
}
#end
This code combine both image but i want the exact same image which user can see in camera preview. My problem is when i capture image and see image in UIImageview its totally different from camera preview.
Camera Preview Image
What i get
Help me to get same image like Camera preview.
I was also facing the same issue. I have fixed this issue here you can find my complete git repo
Camera Preview Image
What i get
I am trying to add an overlay to image taken with imagePicker such as a frame, shown during snap taking. I was trying to use the following code:
self.picker = [[UIImagePickerController alloc] init];
self.picker.sourceType = UIImagePickerControllerSourceTypeCamera;
self.picker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
self.picker.cameraDevice = UIImagePickerControllerCameraDeviceRear;
self.picker.showsCameraControls = NO;
self.picker.navigationBarHidden = YES;
self.picker.toolbarHidden = YES;
self.picker.wantsFullScreenLayout = YES;
// Insert the overlay
self.overlay = [[OverlayViewController alloc] initWithNibName:#"Overlay" bundle:nil];
self.overlay.pickerReference = self.picker;
self.picker.cameraOverlayView = self.overlay.view;
self.picker.delegate = self.overlay;
[self presentModalViewController:self.picker animated:NO];
But this helps when changing the image picker skin. How can I add and process an overlay with the snapshot?
If you need to merge a picture taken with another UIImageView that contains an image, here's a useful snippet:
yourFile.h:
UIImage *combinedImage;
yourFile.m:
-(void)savePicture { // call this method from an IBAction button
// Crop a Combined Image from the taken picture
CGRect rect = [_imagePreview bounds];
UIGraphicsBeginImageContextWithOptions(rect.size,YES,0.0f);
// Render both images, the captured one from the camera and the UIImageView that is over that picture
[__myCapturedImage.layer renderInContext:UIGraphicsGetCurrentContext()];
[_overlayImageView.layer renderInContext:UIGraphicsGetCurrentContext()];
combinedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
_myCapturedImage.image = combinedImage;
// Automatically Save the Image into Photo Album (if you want to do so)
UIImageWriteToSavedPhotosAlbum(combinedImage, nil, nil, nil);
}
Hope this helps!
PS: we have made a nice template that actually processes overlays images (which are frames around images) here: http://codecanyon.net/item/picshape-frame-image-editor-full-app-template/7852895?ref=fvimagination
Cheers!
My application receive images from a UIImagePickerController and when the image comes from a 5S I can properly load the image in quick view in debug, however if the image comes from a 4S I cannot view it and my application does not properly work.
Here is my code for the UIImagePickerController
- (IBAction)scanButton:(UIButton *)sender
{
_imagePicker = [[UIImagePickerController alloc] init];
_imagePicker.delegate = self;
_imagePicker.sourceType = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] ? UIImagePickerControllerSourceTypeCamera : UIImagePickerControllerSourceTypePhotoLibrary;
if (_imagePicker.sourceType == UIImagePickerControllerSourceTypeCamera) {
//_imagePicker.cameraFlashMode = UIImagePickerControllerCameraFlashModeAuto;
_imagePicker.showsCameraControls = NO;
CGAffineTransform translate = CGAffineTransformMakeTranslation(0.0, 71.0); //This slots the preview exactly in the middle of the screen by moving it down 71 points
_imagePicker.cameraViewTransform = translate;
CGAffineTransform scale = CGAffineTransformScale(translate, 1.333333, 1.333333);
_imagePicker.cameraViewTransform = scale;
CGRect screenRect = [[UIScreen mainScreen]bounds];
_overlay = [[CameraOverlay alloc] initWithFrame:CGRectMake(0, 0, screenRect.size.width, screenRect.size.height)];
[_overlay.shootButton addTarget:self action:#selector(takePhoto) forControlEvents:UIControlEventTouchUpInside];
[_overlay.cancelButton addTarget:self action:#selector(cancelPhoto) forControlEvents:UIControlEventTouchUpInside];
[_overlay.flashButton addTarget:self action:#selector(flashButton) forControlEvents:UIControlEventTouchUpInside];
_imagePicker.cameraOverlayView = _overlay;
}
_imagePicker.mediaTypes = [NSArray arrayWithObject:(NSString *)kUTTypeImage];
_imagePicker.allowsEditing = NO;
[self presentViewController:_imagePicker animated:YES completion:NULL];
}
And my didFinish method
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
_image = info[UIImagePickerControllerOriginalImage];
_pickerDismissed = YES;
[self dismissViewControllerAnimated:YES completion:nil];
}
When I view _image from a 5S I can load the image, but from a 4S I cannot.
Does anyone have any idea why this might be happening?
Sounds weird, try a different iPhone 4S
Bellow is my didFinishPickingMediaWithInfo method and I know that I have a lot of unnecessary code, retains, releases, etc... But this was the way I could get it to work and I'm afraid of breaking it on trying to optimize it.
Can anyone help me on taking off the unnecessary stuff and have this method clean?
Also, I have a view controller that will load up 4 photos (Camera Roll or Camera) and after the 2nd or 3rd photo selection at the picker, the app crashes or at least, I got one of these alerts below. What I'm doing wrong? THanks!
-2012-06-23 10:54:07.399 LookdoDia[6525:707] Received memory warning.
-wait_fences: failed to receive reply: 10004003
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
[self dismissModalViewControllerAnimated:YES];
UIImage *img = [info objectForKey:UIImagePickerControllerEditedImage];
if(!img) img = [info objectForKey:UIImagePickerControllerOriginalImage];
uiimvImagem.image = [img retain];
uiimvImagem.alpha = 0;
UIImageView *tempImageView = [[UIImageView alloc] initWithImage:img];
self.uiimvImagem = [tempImageView retain];
[tempImageView release];
CGRect frame = uiimvImagem.frame;
frame.size.width = 359;
frame.size.height = img.size.height / (img.size.width / 359);
uiimvImagem.frame = frame;
uisv1.showsVerticalScrollIndicator = NO;
uisv1.showsHorizontalScrollIndicator = NO;
uisv1.contentSize = CGSizeMake(uiimvImagem.frame.size.width, uiimvImagem.frame.size.height);
uisv1.maximumZoomScale = 3.0;
uisv1.minimumZoomScale = 0.8;
uisv1.clipsToBounds = YES;
uisv1.delegate = self;
[uisv1 addSubview:uiimvImagem];
[img release];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *img = [info objectForKey:UIImagePickerControllerEditedImage];
if(!img) img = [info objectForKey:UIImagePickerControllerOriginalImage];
uiimvImagem.image = img; //why bother?
uiimvImagem.alpha = 0; //why bother?
UIImageView *tempImageView = [[UIImageView alloc] initWithImage:img];
self.uiimvImagem = tempImageView; //Make sure your self.uiimvImagem is a retained property! Also, don't forget to nil it out in your dealloc method
[tempImageView release];
CGRect frame = uiimvImagem.frame;
frame.size.width = 359;
frame.size.height = img.size.height / (img.size.width / 359);
uiimvImagem.frame = frame;
uisv1.showsVerticalScrollIndicator = NO;
uisv1.showsHorizontalScrollIndicator = NO;
uisv1.contentSize = CGSizeMake(uiimvImagem.frame.size.width, uiimvImagem.frame.size.height);
uisv1.maximumZoomScale = 3.0;
uisv1.minimumZoomScale = 0.8;
uisv1.clipsToBounds = YES;
uisv1.delegate = self;
[uisv1 addSubview:uiimvImagem];
[self dismissModalViewControllerAnimated:YES];
}
This should be a bit better - though I'm not sure about how the rest is hooked up (i.e. property declarations and I'm not sure where uisv1 is allocated.) There's still something that doesn't look right - you are assigning an image to an image view but then running the whole thing over with a newly allocated UIImageView.
I am using a transparent image with a cut out for a user to insert / take their own image. For some reason, while using the UIImagePickerControllerEditedImage and cropping the user-taken photo, the image does not save as it was edited; see photo for example.
My issue is that the image does not save exactly how the photo was edited. (i.e: cropped / resized).
Setting up the UIImagePicker
-(void)choosePhotoDialog:(id)sender
{
OverlayView * overlay = [[OverlayView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH_IPHONE, SCREEN_HEIGTH_IPHONE) andPhoto:[dict objectForKey:#"imageUrl"]];
[overlay setUserInteractionEnabled: NO];
UIImagePickerController * picker = [[UIImagePickerController alloc] init];
[picker setSourceType: UIImagePickerControllerSourceTypeCamera];
[picker setDelegate: self];
[picker setAllowsImageEditing: YES];
[picker setShowsCameraControls: YES];
[picker setNavigationBarHidden: YES];
[picker setWantsFullScreenLayout: YES];
[picker setCameraOverlayView: overlay];
[self presentModalViewController:picker animated:YES];
[picker release];
}
After the image is edited:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
SDWebImageManager * manager = [SDWebImageManager sharedManager];
UIImage * cachedImage = [manager imageWithURL: [NSURL URLWithString: #"http://www.someurl.com/test.png"]];
UIImage * userOriginal = [info valueForKey:UIImagePickerControllerEditedImage];
/* combining the overlay and the user-photo */
UIGraphicsBeginImageContext( CGSizeMake(640,960) );
/* for some reason I have to push the user-photo
down 60 pixels for it to show correctly as it
was edited.
*/
[userOriginal drawAtPoint:CGPointMake(0,60)];
[cachedImage drawAtPoint:CGPointMake(0,0)];
UIImage * draft = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum( draft, self, #selector(image:didFinishSavingWithError:contextInfo:), nil );
}
As well, there are white spaces from the editing "crop" portion as demonstrated in the following:
I believe this is because the edited photo does not include the parts obscured by the semi-transparent framing overlay that is shown as part of the standard iOS image editor. (The 60px you've found you must offset by is the 60px of the top half of this overlay.)
You can extract and expand the UIImagePickerControllerCropRect key from the info dictionary and do the edit again yourself on the UIImagePickerControllerOriginalImage in order to get the resultant image you desire.