pinch zooming in image viewer - objective-c

I have an UIImageView. I need pinch zoom.
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 90, 320, 38)];
[imageView setImage:[UIImage imageNamed:#"accesspanel.png"]];
[self.view addSubview: imageView];

You can add the imageview inside a scrollview and can use Scrollview delegate for the this purpose
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.imageView;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.scrollView.minimumZoomScale=0.5;
self.scrollView.maximumZoomScale=6.0;
self.scrollView.contentSize=CGSizeMake(1280, 960);
self.scrollView.delegate=self;
}

First ---> ADD Pinch Gesture to your Image View -:
UIPinchGestureRecognizer *pgr = [[UIPinchGestureRecognizer alloc]
initWithTarget:self action:#selector(handlePinchGesture:)];
pgr.delegate = self;
[imageView addGestureRecognizer:pgr];
Second ---> Implement Pinch Gesture -:
- (void)handlePinchGesture:(UIPinchGestureRecognizer *)gestureRecognizer {
if([gestureRecognizer state] == UIGestureRecognizerStateBegan) {
// Reset the last scale, necessary if there are multiple objects with different scales.
lastScale = [gestureRecognizer scale];
}
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan ||
[gestureRecognizer state] == UIGestureRecognizerStateChanged) {
CGFloat currentScale = [[[gestureRecognizer view].layer valueForKeyPath:#"transform.scale"] floatValue];
// Constants to adjust the max/min values of zoom.
const CGFloat kMaxScale = 2.0;
const CGFloat kMinScale = 1.0;
CGFloat newScale = 1 - (lastScale - [gestureRecognizer scale]); // new scale is in the range (0-1)
newScale = MIN(newScale, kMaxScale / currentScale);
newScale = MAX(newScale, kMinScale / currentScale);
CGAffineTransform transform = CGAffineTransformScale([[gestureRecognizer view] transform], newScale, newScale);
[gestureRecognizer view].transform = transform;
lastScale = [gestureRecognizer scale]; // Store the previous. scale factor for the next pinch gesture call
}
}

UIPinchGestureRecognizer *pinchGestureRecognizer=[[UIPinchGestureRecognizer alloc]initWithTarget:self action:#selector(pinchGestureDetected:)];
[pinchGestureRecognizer setDelegate:self];
[_third_imageview addGestureRecognizer:pinchGestureRecognizer];
- (void)pinchGestureDetected:(UIPinchGestureRecognizer *)recognizer
{
UIGestureRecognizerState state = [recognizer state];
if (state == UIGestureRecognizerStateBegan || state ==UIGestureRecognizerStateChanged)
{
CGFloat scale = [recognizer scale];
[recognizer.view setTransform:CGAffineTransformScale(recognizer.view.transform, scale, scale)];
[recognizer setScale:1.0];
}
}

Related

Calculate rect in UIView after zoom in out and rotate and pan

I need to build a crop image and let the user pinch in\out and rotate the image.
I have the parent UIView that hold the UIImageView.
parent UIView is clipsToBounds = YES
the inner UIImageView is with contentMode = UIViewContentModeScaleAspectFill;
I don't understand how to calculate the crop rect.
this the parent view before pick image :
this is after the UIImageView add to parentView with frame (0,0,parent.width ,parent.height) and with UIViewContentModeScaleAspectFill.
this is after pinch in :
this is my crop code.
-(UIImage*)createImageToPost:(UIImageView*)imageView withParentView:(UIView*)paretView
{
CGRect rectToCrop = CGRectMake(paretView.frame.origin.x - imageView.frame.origin.x , paretView.frame.origin.y - imageView.frame.origin.y, fabs(paretView.frame.size.width - imageView.image.size.width), fabs(paretView.frame.size.height - imageView.image.size.height));
UIImage * newCropImage = [self cropWithImageView:imageView withCropRect:rectToCrop];
return newCropImage;
}
-(UIImage*)cropWithImageView:(UIImageView*)imageView withCropRect:(CGRect)cropRect
{
CGRect rect = CGRectMake(0, 0, imageView.image.size.width, imageView.image.size.height);
// Begin the drawing
UIGraphicsBeginImageContext(imageView.image.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
// Clear whole thing
CGContextClearRect(ctx, rect);
// Transform the image (as the image view has been transformed)
CGContextTranslateCTM(ctx, rect.size.width*0.5, rect.size.height*0.5);
CGContextConcatCTM(ctx, imageView.transform);
CGContextTranslateCTM(ctx, -rect.size.width*0.5, -rect.size.height*0.5);
// Tanslate and scale upside-down to compensate for Quartz's inverted coordinate system
CGContextTranslateCTM(ctx, 0.0, rect.size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);
// Draw view into context
CGContextDrawImage(ctx, rect, imageView.image.CGImage);
// Create the new UIImage from the context
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
// End the drawing
UIGraphicsEndImageContext();
// Begin the drawing (again)
UIGraphicsBeginImageContext(cropRect.size);
ctx = UIGraphicsGetCurrentContext();
// Clear whole thing
CGContextClearRect(ctx, CGRectMake(0, 0, cropRect.size.width, cropRect.size.height));
// Translate to compensate for the different positions of the image
CGContextTranslateCTM(ctx, -((newImage.size.width*0.5)-(cropRect.size.width*0.5)),
(newImage.size.height*0.5)-(cropRect.size.height*0.5));
// Tanslate and scale upside-down to compensate for Quartz's inverted coordinate system
CGContextTranslateCTM(ctx, 0.0, cropRect.size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);
// Draw view into context
CGContextDrawImage(ctx, CGRectMake(0,0,newImage.size.width,newImage.size.height), newImage.CGImage);
// Create the new UIImage from the context
newImage = UIGraphicsGetImageFromCurrentImageContext();
// End the drawing
UIGraphicsEndImageContext();
return newImage;
}
UIPinchGestureRecognizer *pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(pinchGestureDetected:)];
[pinchGestureRecognizer setDelegate:self];
[imageView addGestureRecognizer:pinchGestureRecognizer];
// create and configure the rotation gesture
UIRotationGestureRecognizer *rotationGestureRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(rotationGestureDetected:)];
[rotationGestureRecognizer setDelegate:self];
[imageView addGestureRecognizer:rotationGestureRecognizer];
// creat and configure the pan gesture
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(panGestureDetected:)];
[panGestureRecognizer setDelegate:self];
[imageView addGestureRecognizer:panGestureRecognizer];
- (void)pinchGestureDetected:(UIPinchGestureRecognizer *)recognizer
{
UIGestureRecognizerState state = [recognizer state];
if (state == UIGestureRecognizerStateBegan || state == UIGestureRecognizerStateChanged)
{
CGFloat scale = [recognizer scale];
[recognizer.view setTransform:CGAffineTransformScale(recognizer.view.transform, scale, scale)];
[recognizer setScale:1.0];
}
}
- (void)rotationGestureDetected:(UIRotationGestureRecognizer *)recognizer
{
UIGestureRecognizerState state = [recognizer state];
if (state == UIGestureRecognizerStateBegan || state == UIGestureRecognizerStateChanged)
{
CGFloat rotation = [recognizer rotation];
[recognizer.view setTransform:CGAffineTransformRotate(recognizer.view.transform, rotation)];
[recognizer setRotation:0];
}
}
- (void)panGestureDetected:(UIPanGestureRecognizer *)recognizer
{
UIGestureRecognizerState state = [recognizer state];
if (state == UIGestureRecognizerStateBegan || state == UIGestureRecognizerStateChanged)
{
CGPoint translation = [recognizer translationInView:recognizer.view];
[recognizer.view setTransform:CGAffineTransformTranslate(recognizer.view.transform, translation.x, translation.y)];
[recognizer setTranslation:CGPointZero inView:recognizer.view];
}
}
this is the image i get after crop:

UIPanGestureRecognizer on multiple view - Objective-c

I have 2 imageviews that I want to be able to move. This is my code:
panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(gestureRecognizerMethod:)];
imageview = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"image.png"]];
imageview.frame = CGRectMake(390, 100, 80, 16);
imageview.userInteractionEnabled = YES;
[imageview addGestureRecognizer:panRecognizer];
[self addSubview:imageview];
imageview2 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"image.png"]];
imageview2.frame = CGRectMake(390, 120, 80, 17);
imageview2.userInteractionEnabled = YES;
[imageview2 addGestureRecognizer:panRecognizer];
[self imageview2];
And in my gestureRecognizer method:
- (void)gestureRecognizerMethod:(UIPanGestureRecognizer *)recognizer
{
if (recognizer.view == imageview)
{
if (recognizer.state == UIGestureRecognizerStateBegan || recognizer.state == UIGestureRecognizerStateChanged)
{
CGPoint startPoint = [recognizer locationInView:self];
imageview.center = startPoint;
}
}
if (recognizer.view == imageview2)
{
if (recognizer.state == UIGestureRecognizerStateBegan || recognizer.state == UIGestureRecognizerStateChanged)
{
CGPoint startPoint = [recognizer locationInView:self];
imageview2.center = startPoint;
}
}
}
I'm only able to move one of the view. What is wrong?
Create a new gesture recognizer for the second image view. You can use the same target and action for both recognisers but you can only attach any one recogniser to a single view.
Try this:
ResizeImage on github

How to scale and rotate smoothly?

I have seen some app, they are able to scale and rotate the image at the same time. It does not require to release the finger touch.
My following code require to:
1. Touch to scale
2. Release
3. Touch to rotate
How do i scale and rotate at the same time?
In my main code:
UIPanGestureRecognizer *imagePanGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(moveImage:)];
[imagePanGesture setMinimumNumberOfTouches:1];
[imagePanGesture setMaximumNumberOfTouches:1];
[tempImageView addGestureRecognizer:imagePanGesture];
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(scaleImage:)];
[tempImageView addGestureRecognizer:pinchGesture];
UIRotationGestureRecognizer *rotationGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(rotateImage:)];
[tempImageView addGestureRecognizer:rotationGesture];
In individual scale and rotate
- (void)scaleImage:(UIPinchGestureRecognizer *)recognizer
{
if([recognizer state] == UIGestureRecognizerStateEnded)
{
previousScale = 1.0;
return;
}
CGFloat newScale = 1.0 - (previousScale - [recognizer scale]);
CGAffineTransform currentTransformation = [recognizer view].transform;
CGAffineTransform newTransform = CGAffineTransformScale(currentTransformation, newScale, newScale);
[[recognizer view] setTransform:newTransform];
previousScale = [recognizer scale];
}
- (void)rotateImage:(UIRotationGestureRecognizer *)recognizer
{
if([recognizer state] == UIGestureRecognizerStateEnded) {
previousRotation = 0.0;
return;
}
CGFloat newRotation = 0.0 - (previousRotation - [recognizer rotation]);
CGAffineTransform currentTransformation = [recognizer view].transform;
CGAffineTransform newTransform = CGAffineTransformRotate(currentTransformation, newRotation);
[[recognizer view] setTransform:newTransform];
previousRotation = [recognizer rotation];
}
You may check this http://www.raywenderlich.com/6567/uigesturerecognizer-tutorial-in-ios-5-pinches-pans-and-more
I believe what you are looking for is
-gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:
Here is the code you are looking for... Add this method to your .m file.
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}

Zooming and Rotation an UIImageView

I would like to zoom and rotate an UIImageView. Here is my code:
#synthesize immagine, velocita, locationManager, direzione;
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading{
double degrees = newHeading.magneticHeading;
double radians = degrees * M_PI / 180;
[UIView animateWithDuration:0.05 animations:^{
self.immagine.transform = CGAffineTransformMakeRotation(-radians);
}];
}
-(UIView *) viewForZoomingInScrollView:(UIScrollView *)scrollView {
return immagine;
}
- (void)viewDidLoad
{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate=self;
locationManager.desiredAccuracy=kCLLocationAccuracyBestForNavigation;
[scrollView setDelegate:self];
[scrollView setContentSize:CGSizeMake(320, 460)];
immagine = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"mappa1"]];
immagine.frame = CGRectMake(0, 0, 320, 460);
immagine.contentMode = UIViewContentModeScaleAspectFit;
[scrollView addSubview:immagine];
locationManager.headingFilter = kCLHeadingFilterNone;
[locationManager startUpdatingHeading];
[super viewDidLoad];
}
But when I'm zooming, the UIImageView exit from the View. Can anyone help me? Thanks in advance!
I have problem like this and these two function will solve your problem
- (void)twoFingerPinch:(UIPinchGestureRecognizer *)recognizer
{
CGRect originalFrame=recognizer.view.frame;
CGRect newFrame=CGRectMake(originalFrame.origin.x, originalFrame.origin.y, originalFrame.size.width*recognizer.scale, originalFrame.size.height*recognizer.scale);
if (newFrame.size.width>70&&newFrame.size.width<150)
{
recognizer.view.frame=newFrame;
}
}
- (void)twoFingersRotate:(UIRotationGestureRecognizer *)recognizer
{
[self.view bringSubviewToFront:[(UIRotationGestureRecognizer*)recognizer view]];
if([(UIRotationGestureRecognizer*)recognizer state] == UIGestureRecognizerStateEnded) {
lastRotation = 0.0;
return;
}
CGFloat rotation = 0.0 - (lastRotation - [(UIRotationGestureRecognizer*)recognizer rotation]);
CGAffineTransform currentTransform = [(UIPinchGestureRecognizer*)recognizer view].transform;
CGAffineTransform newTransform = CGAffineTransformRotate(currentTransform,rotation);
[[(UIRotationGestureRecognizer*)recognizer view] setTransform:newTransform];
lastRotation = [(UIRotationGestureRecognizer*)recognizer rotation];
// recognizer.view.transform=CGAffineTransformMakeRotation(([recognizer rotation] * 180) / M_PI);
}

Moving an image after rotating does not behave correctly

I'm getting problem when I tried to move the after rotating the same image. My code is working fine when I tried to move the image before rotating it. After rotating the image, when I tried to move the rotated image, the image is not moving in the direction which I dragged. Can any one help me.
Thanks in advance. I'm using the code
#import "myDraggableImage.h"
#import <CoreGraphics/CoreGraphics.h>
#import <QuartzCore/CoreAnimation.h>
#implementation myDraggableImage
- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
[[self superview] bringSubviewToFront:self];
CGPoint pt = [[touches anyObject] locationInView:self];
startLocation = pt;
UIRotationGestureRecognizer *rotationRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(rotate:)];
[rotationRecognizer setDelegate:self];
[self addGestureRecognizer:rotationRecognizer];
[rotationRecognizer release];
UIPinchGestureRecognizer *pinchRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(scale:)];
[pinchRecognizer setDelegate:self];
[self addGestureRecognizer:pinchRecognizer];
[pinchRecognizer release];
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(move:)];
[panRecognizer setMinimumNumberOfTouches:1];
[panRecognizer setMaximumNumberOfTouches:1];
[panRecognizer setDelegate:self];
[self addGestureRecognizer:panRecognizer];
[panRecognizer release];
CGRect frame = [self frame];
printf("\n the x co ordinte of the frame is :%f",frame.origin.x);
printf("\n the y co ordinte of the frame is :%f",frame.origin.y);
printf("\n the widht co ordinte of the frame is :%f",frame.size.width);
printf("\n the height co ordinte of the frame is :%f",frame.size.height);
}
-(void)rotate:(id)sender
{
if([(UIRotationGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded)
{
lastRotation = 0.0;
return;
}
CGFloat rotation = 0.0 - (lastRotation - [(UIRotationGestureRecognizer*)sender rotation]);
CGAffineTransform currentTransform = [(UIPinchGestureRecognizer*)sender view].transform;
CGAffineTransform newTransform = CGAffineTransformRotate(currentTransform,rotation);
[[(UIRotationGestureRecognizer*)sender view] setTransform:newTransform];
lastRotation = [(UIRotationGestureRecognizer*)sender rotation];
CGRect frame = [self frame];
}
-(void)scale:(id)sender
{
if([(UIPinchGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded)
{
lastScale = 1.0;
return;
}
CGFloat scale = 1.0 - (lastScale - [(UIPinchGestureRecognizer*)sender scale]);
CGAffineTransform currentTransform = [(UIPinchGestureRecognizer*)sender view].transform;
CGAffineTransform newTransform = CGAffineTransformScale(currentTransform, scale, scale);
[[(UIPinchGestureRecognizer*)sender view] setTransform:newTransform];
lastScale = [(UIPinchGestureRecognizer*)sender scale];
}
-(void)move:(id)sender
{
[[[(UITapGestureRecognizer*)sender view] layer] removeAllAnimations];
CGAffineTransform currentTransform = [(UIPinchGestureRecognizer*)sender view].transform;
CGPoint translatedPoint = [(UIPanGestureRecognizer*)sender translationInView:self];
if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateBegan)
{
firstX = [[sender view] center].x;
firstY = [[sender view] center].y;
}
translatedPoint = CGPointMake(firstX+translatedPoint.x, firstY+translatedPoint.y);
[[sender view] setCenter:translatedPoint];
if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded)
{
CGFloat finalX = translatedPoint.x ;//+ (.15*[(UIPanGestureRecognizer*)sender velocityInView:self].x);
CGFloat finalY = translatedPoint.y ;//+ (.15*[(UIPanGestureRecognizer*)sender velocityInView:self].y);
if(finalX < 0)
{
finalX = 0;
}
else if(finalX > 460)
{
finalX = 440;
}
if(finalY < 40)
{
finalY = 40;
}
else if(finalY > 300)
{
finalY = 300;
}
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.35];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[[sender view] setCenter:CGPointMake(finalX, finalY)];
[UIView commitAnimations];
}
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return ![gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]];
}
-(void)dealloc
{
[super dealloc];
}
#end
touchesBegan:withEvent: is a wrong place to set up your gestures as it will add a new gestures every time the user. As for the translation function, it's hard to put a finger on what's wrong. Some of the process here seems overdone. While I haven't implemented the animation part (to bring it in, right?), take a look at this sample project. It could help you get started in the right direction.