15

I have a UIImageView with an image in it. I have rotated the image prior to display by setting the transform property of the UIImageView to CGAffineTransformMakeRotation(angle) where angle is the angle in radians.

I want to be able to create another UIImage that corresponds to the rotated version that I can see in my view.

I am almost there, by rotating the image context I get a rotated image:

- (UIImage *) rotatedImageFromImageView: (UIImageView *) imageView{    UIImage *rotatedImage;    // Get image width, height of the bounding rectangle    CGRect boundingRect = [self getBoundingRectAfterRotation: imageView.bounds byAngle:angle];    // Create a graphics context the size of the bounding rectangle    UIGraphicsBeginImageContext(boundingRect.size);    CGContextRef context = UIGraphicsGetCurrentContext();    // Rotate and translate the context    CGAffineTransform ourTransform = CGAffineTransformIdentity;    ourTransform = CGAffineTransformConcat(ourTransform, CGAffineTransformMakeRotation(angle));    CGContextConcatCTM(context, ourTransform);    // Draw the image into the context    CGContextDrawImage(context, CGRectMake(0, 0, imageView.image.size.width, imageView.image.size.height), imageView.image.CGImage);    // Get an image from the context    rotatedImage = [UIImage imageWithCGImage: CGBitmapContextCreateImage(context)];    // Clean up    UIGraphicsEndImageContext();    return rotatedImage; }

However the image is not rotated about its centre. I have tried all kinds of transforms concatenated with my rotate to get it to rotate around the centre but to no avail. Am I missing a trick? Is this even possible since I am rotating the context not the image?

Getting desperate to make this work now, so any help would be appreciated.

Dave

EDIT: I've been asked several times for my boundingRect code, so here it is:

- (CGRect) getBoundingRectAfterRotation: (CGRect) rectangle byAngle: (CGFloat) angleOfRotation {    // Calculate the width and height of the bounding rectangle using basic trig    CGFloat newWidth = rectangle.size.width * fabs(cosf(angleOfRotation)) + rectangle.size.height * fabs(sinf(angleOfRotation));    CGFloat newHeight = rectangle.size.height * fabs(cosf(angleOfRotation)) + rectangle.size.width * fabs(sinf(angleOfRotation));    // Calculate the position of the origin    CGFloat newX = rectangle.origin.x + ((rectangle.size.width - newWidth) / 2);    CGFloat newY = rectangle.origin.y + ((rectangle.size.height - newHeight) / 2);    // Return the rectangle    return CGRectMake(newX, newY, newWidth, newHeight);}
askedMay 18, 2010 at 11:00
Magic Bullet Dave's user avatar
4
  • this should do it <br/>stackoverflow.com/questions/1315251/…CommentedMay 24, 2010 at 9:39
  • What is thisgetBoundingRectAfterRotation function?CommentedNov 12, 2011 at 4:37
  • Hi @bmdhacks the getBoundingRectAfterRotation is a method I have created, so you wont find it in any of the Cocoa-Touch classes. It takes a rect and an angle as arguments and returns a new CGRect that would encompass the original rect if it were rotated by the given angle.CommentedNov 13, 2011 at 22:30
  • Hi @bmdhacks due to popular demand have added the method in an edit to my original question.CommentedNov 22, 2011 at 12:19

1 Answer1

22

OK - at last I seem to have done it. Any comments on the correctness would be useful... needed a translate, a rotate, a scale and an offset from the drawing rect position to make it work. Code is here:

CGAffineTransform transform = CGAffineTransformIdentity;transform = CGAffineTransformTranslate(transform, boundingRect.size.width/2, boundingRect.size.height/2);transform = CGAffineTransformRotate(transform, angle);transform = CGAffineTransformScale(transform, 1.0, -1.0);CGContextConcatCTM(context, transform);// Draw the image into the contextCGContextDrawImage(context, CGRectMake(-imageView.image.size.width/2, -imageView.image.size.height/2, imageView.image.size.width, imageView.image.size.height), imageView.image.CGImage);// Get an image from the contextrotatedImage = [UIImage imageWithCGImage: CGBitmapContextCreateImage(context)];
answeredMay 24, 2010 at 14:18
Magic Bullet Dave's user avatar
Sign up to request clarification or add additional context in comments.

4 Comments

why do you needtransform = CGAffineTransformScale(transform, 1.0, -1.0); ?
The CoreGraphics uses a co-ordinate system where the origin is the bottom left. UIKit objects use an origin at the top left with the y-axis increasing as you move down the screen. This transform flips the y-axis to ensure the image is drawn the right way up.
Thanks! I was struggling on drawing image on context with translate, rotation, and scaling. I tried UIImage'sdrawInRect: and translate the context but it always rotate around top left (0,0). Your solution is the only one that works! :)
Hi, this code does not work with photos that has different orientation than UIImageOrientationUp, do you have any solution?

Your Answer

Sign up orlog in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

By clicking “Post Your Answer”, you agree to ourterms of service and acknowledge you have read ourprivacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.