Get scale value and rotate value in CGAffineTransform xcode - ios

I'm developing an application on which user can pinch and rotate the the image. After pinching and rotating the image. the image must be print. I want to get the scaling factor and rotating factor of my image so that I can draw a new image and then print that new image. But my problem is I cant get the scaling and rotating factor of my image. Can anybody teach me on how to get the scaling factor and rotate factor using CGAffineTransform. Or can anybody teach me on how to save the image after scaling and rotating. thank you so much guys. here is my code.
- (void)rotationImage:(UIRotationGestureRecognizer*)gesture {
[self.view bringSubviewToFront:gesture.view];
if ([gesture state] == UIGestureRecognizerStateEnded) {
lastRotation = 0;
return;
}
CGAffineTransform currentTransform = img_tempImage.transform;
CGFloat rotation = 0.0 - (lastRotation - gesture.rotation);
CGAffineTransform newTransform = CGAffineTransformRotate(currentTransform, rotation);
img_tempImage.transform = newTransform;
myTransform = img_tempImage.transform;
lastRotation = gesture.rotation;
isTransform = YES;
}
- (void)pinchImage:(UIPinchGestureRecognizer*)pinchGestureRecognizer {
[self.view bringSubviewToFront:pinchGestureRecognizer.view];
pinchGestureRecognizer.view.transform = CGAffineTransformScale(pinchGestureRecognizer.view.transform, pinchGestureRecognizer.scale, pinchGestureRecognizer.scale);
pinchGestureRecognizer.scale = 1;
myTransform = img_tempImage.transform;
isTransform = YES;
}
- (void)panpan:(UIPanGestureRecognizer *)sender {
[self.view bringSubviewToFront:img_tempImage];
CGPoint translation = [sender translationInView:self.view];
CGPoint imageViewPosition = img_tempImage.center;
imageViewPosition.x += translation.x;
imageViewPosition.y += translation.y;
myPoint = imageViewPosition;
img_tempImage.center = imageViewPosition;
[sender setTranslation:CGPointZero inView:self.view];
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}

I found the answer on my question on how to get the scale and rotate value.
CGFloat angle = [(NSNumber *)[img_tempImage valueForKeyPath:#"layer.transform.rotation.z"] floatValue];
NSLog(#"by angle: %.2f",angle);
CGFloat xScale = img_tempImage.transform.a;
CGFloat yScale = img_tempImage.transform.d;
NSLog(#"xScale :%.2f",xScale);
NSLog(#"yScale :%.2f",yScale);

Related

Zoom a specific area of a Scrollview

I'm stuck on a case where I want to zooming a part(rect) of a scrollview programatically not by touch or gestures.
CGRect cropRect = CGRectMake(xPos * [UIScreen mainScreen].nativeScale, yPos * [UIScreen mainScreen].nativeScale, width1 * [UIScreen mainScreen].nativeScale, height1 * [UIScreen mainScreen].nativeScale);
[self.scrlVPhoto zoomToRect:cropRect animated:YES];
I've set delegate and also implemented delegate method.
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)aScrollView {
return self.containerView;
}
self.containerView is a view that I want to zoom.
I've tried everything and I'm still confused how to get out of this.
Please some one can help me. Any help is appreciated.
Thanks in advance.
I am going to answer my own question.
I've searched lots of articles and hours of debugging I've found that when scrollview is zoomed then actually its contentSize is increased its zoomScale remain unchanged.
So I just used transform property of the scrollview's subview (i.e. self.containerView) and set scrollview's contentOffset I got what I was looking for.
self.containerView.transform = CGAffineTransformMakeScale(1.8, 1.8); // containerView is subview of scrollview and 1.8 is zoom scale just for eg.
[self.scrlVPhoto setContentOffset:CGPointMake(self.scrlVPhoto.contentOffset.x, (self.scrlVPhoto.contentOffset.y + cropRect.origin.y)) animated:true];
You should add the view which you want to zoom inside the scrollview. Inside the delegate method return the view which you want to zoom.
I have Create the UIImageView, set the Zoom option in imageView when double tap or single tap to UIImageView and the code is given below,
viewDidLoad Method:
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleDoubleTap:)];
[doubleTap setNumberOfTapsRequired:2];
DoubleTab Method:
- (void)handleDoubleTap:(UIGestureRecognizer *)gestureRecognizer {
// zoom in
float newScale = [myscrollview zoomScale] * 2;
if (newScale > self.myscrollview.maximumZoomScale){
newScale = self.myscrollview.minimumZoomScale;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]];
[myscrollview zoomToRect:zoomRect animated:YES];
}
else{
newScale = self.myscrollview.maximumZoomScale;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]];
[myscrollview zoomToRect:zoomRect animated:YES];
}
}
- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center {
CGRect zoomRect;
// the zoom rect is in the content view's coordinates.
// At a zoom scale of 1.0, it would be the size of the imageScrollView's bounds.
// As the zoom scale decreases, so more content is visible, the size of the rect grows.
zoomRect.size.height = [myscrollview frame].size.height / scale;
zoomRect.size.width = [myscrollview frame].size.width / scale;
// choose an origin so as to get the right center.
zoomRect.origin.x = center.x - (zoomRect.size.width / 2.0);
zoomRect.origin.y = center.y - (zoomRect.size.height / 2.0);
return zoomRect;
}
And you need the delegate methods are shown below,
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
if (vmov==nil)
{
float newwidth;
float newheight;
UIImage *image=detaimageview.image;
if (image.size.height>=image.size.width){
newheight=detaimageview.frame.size.height;
newwidth=(image.size.width/image.size.height)*newheight;
if(newwidth>detaimageview.frame.size.width){
float diff=detaimageview.frame.size.width-newwidth;
newheight=newheight+diff/newheight*newheight;
newwidth=detaimageview.frame.size.width;
}
}
else{
newwidth=detaimageview.frame.size.width;
newheight=(image.size.height/image.size.width)*newwidth;
if(newheight>detaimageview.frame.size.height){
float diff=detaimageview.frame.size.height-newheight;
newwidth=newwidth+diff/newwidth*newwidth;
newheight=detaimageview.frame.size.height;
myscrollview.clipsToBounds = NO;
}
}
CGRect frame;
CGFloat screenWidth;
CGFloat screenHeight;
CGRect screenRect = [[UIScreen mainScreen] bounds];
screenWidth = screenRect.size.width;
screenHeight = screenRect.size.height-64;
frame.size.width = newwidth;
frame.size.height = newheight;
self.myscrollview.contentSize = frame.size;
float x,y;
x=0;
y=0;
if (newheight<screenHeight)
{
x =screenHeight/2-newheight/2;
}
if (newwidth<screenWidth)
{
y =screenWidth/2-newwidth/2;
}
self.detaimageview.frame = CGRectMake(y,x,newwidth,newheight);
return self.detaimageview;
}
return nil;
}
this above codes are zoom the imageView and its working for my Projects,
hope its helpful
Please check this one. Its may be helpful to you
-(void)handlePinchWithGestureRecognizer:(UIPinchGestureRecognizer *)pinchGestureRecognizer{
//[self.superImage_View setAlpha:0.5];
if([pinchGestureRecognizer state] == UIGestureRecognizerStateBegan) {
// Reset the last scale, necessary if there are multiple objects with different scales
lastScale = [pinchGestureRecognizer scale];
}
if ([pinchGestureRecognizer state] == UIGestureRecognizerStateBegan ||
[pinchGestureRecognizer state] == UIGestureRecognizerStateChanged){
CGFloat currentScale = [[[pinchGestureRecognizer 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-[pinchGestureRecognizer scale]) ; // new scale is in the range (0-1)
newScale = MIN(newScale, kMaxScale / currentScale);
newScale = MAX(newScale, kMinScale / currentScale);
CGAffineTransform transform = CGAffineTransformScale([[pinchGestureRecognizer view] transform], newScale, newScale);
[pinchGestureRecognizer view].transform = transform;
lastScale = [pinchGestureRecognizer scale]; // Store the previous scale factor for the next pinch gesture call
}
if ([pinchGestureRecognizer state] == UIGestureRecognizerStateEnded) {
[undoList addObject:cropImage];
}
}

UIPanGestureRecognizer to implement scale and rotate an UIView

There is a UIView A. I put a icon on view A and try to use pan gesture to scale and rotate this view A. The scale function works fine but I can't make rotation work. The code is as following. Any help will be appreciated. thanks
- (void)scaleAndRotateWatermark:(UIPanGestureRecognizer *)gesture
{
if (gesture.state == UIGestureRecognizerStateChanged
|| gesture.state == UIGestureRecognizerStateEnded)
{
UIView *child = gesture.view;
UIView *view = child.superview;
CGPoint translatedPoint = [gesture translationInView:view];
CGPoint originCenter = child.center;
CGPoint newCenter = CGPointMake(child.centerX+translatedPoint.x, child.centerY+translatedPoint.y);
float origX = originCenter.x;
float origY = originCenter.y;
float newX = newCenter.x;
float newY = newCenter.y;
float originDis = (origX*origX) + (origY*origY);
float newDis = (newX*newX) + (newY*newY);
float scale = newDis/originDis;
view.transform = CGAffineTransformScale(view.transform, scale, scale);
// rotation calulate here
// need your help
// end of rotation
[guesture setTranslation:CGPointZero inView:_videoPreviewLayer];
}
}

How do I accurately zoom in on a specific point on pinch gesture (with multiple pinches)?

I am trying to zoom a quad in my iOS application. It needs to zoom not based on the center of the quad, but based on the centroid of the pinch.
I am able to do this correctly - however only for the first pinch gesture. On subsequent pinch gestures, it works, but it drifts a little bit and doesn't quite seem accurate. I am unable to figure out what to do.
There are a few SO questions around this, and I've been through most, if not all of them. None of them accurately address my problem.
Also note that I'm scaling and translating a quad (which is rendered into a GLKView), and not the view itself. Most solutions I've seen deal with transforming the views directly.
Here's the code for the pinch gesture and handling:
First in viewDidLoad:
UIPinchGestureRecognizer *pinchRecognizer = [[UIPinchGestureRecognizer alloc]
initWithTarget:self action:#selector(respondToPinchGesture:)];
pinchRecognizer.cancelsTouchesInView = YES;
pinchRecognizer.delaysTouchesEnded = NO;
[glView addGestureRecognizer:pinchRecognizer];
Where glView is a GLKView object.
And the handler:
- (IBAction)respondToPinchGesture:(UIPinchGestureRecognizer *)recognizer{
if (recognizer.state == UIGestureRecognizerStateEnded || [recognizer numberOfTouches] < 2) return;
if (recognizer.state == UIGestureRecognizerStateBegan) {
point = [recognizer locationInView:glView];
point.x *= glView.contentScaleFactor;
point.y *= glView.contentScaleFactor;
point.y = height - point.y;
anchor = GLKVector3Make(point.x, point.y, 0);
lastScale = 1.0;
}
if (fabs(recognizer.scale - lastScale) > 0.01){
GLfloat scale = 1.0 - (lastScale - recognizer.scale);
lastScale = recognizer.scale;
new_anchor_point = anchor;
new_anchor_point = GLKVector3MultiplyScalar(new_anchor_point, scale);
GLKVector3 translate = GLKVector3Subtract(anchor, new_anchor_point);
path.transform = GLKMatrix4TranslateWithVector3(path.transform, translate);
path.transform = GLKMatrix4Scale(path.transform, scale, scale, 0);
cumulative_translate = GLKVector3Add(cumulative_translate, translate);
}
}
Any pointers appreciated. I am 2 days into this and even a vague suggestion might be helpful.
You have to
remember the previous transformation matrix upon RecognizerStateBegan,
construct your new transformation matrix for pinch zoom assuming the view or object have not been transformed before.
Then, concatenate two matrices together. This will be your final matrix for transforming your object or view.
I managed to solve this using:
-(GLKVector3)get_touch_point_on_view:(UIGestureRecognizer *)recognizer{
CGRect bounds = [glView bounds];
CGPoint point = [recognizer locationInView:glView];
point.y = bounds.size.height - point.y;
return GLKVector3Make((point.x * glView.contentScaleFactor - total_translation.x)/total_scale,
(point.y * glView.contentScaleFactor - total_translation.y)/total_scale, 0);
}
- (void)respondToPinchGesture:(UIPinchGestureRecognizer *)recognizer{
if (recognizer.state == UIGestureRecognizerStateBegan) {
lastScale = 1.0;
}
[self get_touch_point_on_view:recognizer];
if (fabs(recognizer.scale - lastScale) > 0.01){
GLfloat scale = 1.0 - (lastScale - recognizer.scale);
lastScale = recognizer.scale;
total_scale *= scale;
path.transform = GLKMatrix4TranslateWithVector3(path.transform, centroid);
path.transform = GLKMatrix4Scale(path.transform, scale, scale, 0);
path.transform = GLKMatrix4TranslateWithVector3(path.transform, GLKVector3Negate(centroid));
total_translation = [self get_total_translation];
}
}

Image is stretching while Pinch

I'm getting images from remote server and displaying in UIImageView then doing pinch gesture to this imageview. But when i pinching image, i'm getting image stretching. It's loosing original resolution and quality.
mmageView=[[UIImageView alloc]initWithFrame:CGRectMake(50,50,150,150)];
[self.view addSubview:mmageView];
UIPinchGestureRecognizer *dbpinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(dbhandlePinch:)];
[mmageView addGestureRecognizer:dbpinchGesture];
UIPinchGesture:
-(void)dbhandlePinch:(UIPinchGestureRecognizer*)recognizer {
if([recognizer state] == UIGestureRecognizerStateBegan) {
// Reset the last scale, necessary if there are multiple objects with different scales
LastScale = [recognizer scale];
}
if ([recognizer state] == UIGestureRecognizerStateBegan ||
[recognizer state] == UIGestureRecognizerStateChanged) {
CGFloat currentScale = [[[recognizer view].layer valueForKeyPath:#"transform.scale"] floatValue];
// Constants to adjust the max/min values of zoom
// const CGFloat kMaxScale = 2.0;
const CGFloat kMinScale = 0.8;
CGFloat newScale = 1 - (LastScale - [recognizer scale]);
// newScale = MIN(newScale, kMaxScale / currentScale);
newScale = MAX(newScale, kMinScale / currentScale);
CGAffineTransform transform = CGAffineTransformScale([[recognizer view] transform], newScale, newScale);
[recognizer view].transform = transform;
LastScale = [recognizer scale]; // Store the previous scale factor for the next pinch gesture call
}
}
For pinch zoom add your imageView in a scrollView and Import UIScrollViewDelegate
- (void)viewDidLoad
{
[super viewDidLoad];
//for pinch gesture
_scrollView.minimumZoomScale = 0.5;
_scrollView.maximumZoomScale = 6.0;
_scrollView.contentSize = CGSizeMake(_imageView.frame.size.width, _imageView.frame.size.height);
_scrollView.delegate = self;
}
-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return _imageView;
}
UIScrollView makes supporting the pinch gestures for zooming easy. Better solution in Apple Documentation.

UIView flipping by UIPanGestureRecognizer

I'm trying to use UIPanGestureRecognizer to flip an UIView. I'm using below code to handle flipping the view,
- (void)handlePan:(UIPanGestureRecognizer*)gesture{
CGPoint translation = [gesture translationInView:self.view];
NSLog(#"PAN X VALUE %f", translation.x );
double percentageOfWidth = translation.x / (gesture.view.frame.size.width / 2);
float angle = (percentageOfWidth * 100) * M_PI_2 / 180.0f;
CALayer *layer = testView.layer;
CATransform3D flipTransform = CATransform3DIdentity;
flipTransform.m34 = -0.002f;
flipTransform = CATransform3DRotate(flipTransform, angle, 0.0f, 1.0f, 0.0f);
layer.transform = flipTransform;
}
My problem is when i pan, sometimes there are some quick jumpings happen, I believe thats because translation.x(PAN X VALUE) value jumps from few points ahead, In my case i need it to be very smooth.
Any help greatly appreciated.
Thanks in advance.
You can use the gestureRecognizerShouldBegin method, which u can limit the UIPanGestureRecognizer sensitivity.
Example:
- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)panGestureRecognizer {
CGPoint translation = [panGestureRecognizer translationInView:self.view];
return fabs(translation.y) < fabs(translation.x);
}
Here's how I solved this for a cube rotation - just take the amount dragged and divide:
- (void)panHandle:(UIPanGestureRecognizer*)recognizer;
{
if ([recognizer state] == UIGestureRecognizerStateBegan)
{
CGPoint translation = [recognizer translationInView:[self superview]];
_startingX = translation.x;
}
else if ([recognizer state] == UIGestureRecognizerStateChanged)
{
CGPoint translation = [recognizer translationInView:[self superview]];
CGFloat angle = -(_startingX - translation.x) / 4;
//Now do translation with angle
_transitionContainer.layer.sublayerTransform = [self->_currentMetrics asTransformWithAngle:angle];
}
else if ([recognizer state] == UIGestureRecognizerStateEnded)
{
[self transitionOrReturnToOrigin];
}
}

Resources