2

I am performing rotation on an UIImageView and then i try to crop a part of it and save it as an UIImage. The UIImageView rotates however it always crops the same part of the photo. So the cropping does not take into account the image rotation. What am i doing wrong?

//rotate image 
CGRect new = CGRectMake(0, 0, 100, 50);
CGAffineTransform rotation = CGAffineTransformMakeRotation(5);
[photo setTransform:rotation];

// crop image 
CGImageRef imageRef = CGImageCreateWithImageInRect([photo.image CGImage], new);
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef]; 
CGImageRelease(imageRef);

// display crop bounds 
UIView* faceBounds = [[UIView alloc] initWithFrame:new];
faceBounds.layer.borderWidth = 2;
faceBounds.layer.borderColor = [[UIColor redColor] CGColor];
Rory Lester
  • 2,858
  • 11
  • 49
  • 66
  • Because the transformation is applied when rendering the image-view to the screen and not on the image data itself. – Till Aug 21 '12 at 19:28
  • I see.. and how could i fix this? – Rory Lester Aug 21 '12 at 19:29
  • It also seems as if you are using the wrong unit for the rotation angle. I guess you mean to rotate by 5 degrees. For doing that, you will have to convert that angle into radians. A simple conversion would be `angleInRadians = angleInDegrees * M_PI / 180` – Till Aug 21 '12 at 19:44
  • I just gave that as an example, i realised that i need to convert degrees to radian's. Spent so much time on this, but thank you yet again for your help. – Rory Lester Aug 21 '12 at 19:48
  • My pleasure - hope things work smooth from this point on. – Till Aug 21 '12 at 19:51

2 Answers2

1

Use the following snippet for rotating image data.

The input data is inAngle (angle in radians) and inImage (UIImage instance).

What this does, it creates an image context, applies the transformation to it and draws the original image into that context. The resulting image data will now be stored in resultImage.

The first three lines handle the calculation of the bounding result image frame.

UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, inImage.size.width, inImage.size.height)];
rotatedViewBox.transform = CGAffineTransformMakeRotation(inAngle);
CGSize rotatedSize = rotatedViewBox.frame.size;

UIGraphicsBeginImageContext(rotatedSize);
CGContextRef bitmap = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(bitmap, rotatedSize.width / 2.0f, rotatedSize.height / 2.0f);
CGContextRotateCTM(bitmap, inAngle);
CGContextScaleCTM(bitmap, 1.0f, -1.0f);
CGContextDrawImage(bitmap, CGRectMake(-inImage.size.width / 2.0f,
                                      -inImage.size.height / 2.0f,
                                      inImage.size.width,
                                      inImage.size.height),
                                      inImage.CGImage);
UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Till
  • 27,559
  • 13
  • 88
  • 122
  • Hey, thank you for the snippet of code. I want to ask, where does the image pivot from? (0,0?) and if so how can i make it pivot from the image center?. Also, if the image is e.g. jpeg format, will i have to modify the 'bitmap' part? (code works as it is for jpeg but just wondering). – Rory Lester Aug 21 '12 at 19:46
  • It rotates around the center of the image. The source format does not matter as long as UIImage properly *understands* it. – Till Aug 21 '12 at 19:48
  • That `bitmap` is a bit misleading. What this is is a graphics context for drawing in memory (as opposed to on screen). – Till Aug 21 '12 at 19:50
  • @Till I am trying your code, but it's not working. I don't understand how CGRectMake locates the x and y? – Dejell Feb 03 '13 at 12:38
  • @Odelya this code works fine, rest assured. What exactly is your problem? I do not get you on "I dont understand how CGRectMake locates the x and y". – Till Feb 03 '13 at 20:01
  • @Till The code rotates the image for me, but doesn't crop it! – Dejell Feb 03 '13 at 20:14
  • @Odelya That is by design, it is not supposed to crop anything. You should read the original question for getting the exact point. – Till Feb 03 '13 at 20:15
  • @Till so where should the cropping be done? before or after the rotation? – Dejell Feb 03 '13 at 20:19
  • @Odelya that entirely depends on your needs. I would like to suggest you post a new question that describes exactly what you are trying to achieve. It often helps to include a mocked image showing how your results are supposed to look like. – Till Feb 04 '13 at 00:03
  • @Till - i keep hearing that the frame property should not be used after applying a transformation. Still, your code seems to work properly and i dont understand half of what a transformation is. would you mind explaining why it is ok for you to access `rotatedBox.frame.size` after setting `rotatedBox.transform`? TIA, katzenhut – katzenhut Jun 19 '13 at 09:46
  • How to CROP if image is rotated , Anyone here with answer ? – Prashant Tukadiya Aug 24 '17 at 06:38
-1

This is too late for now but For now someone can try this

vivek bhoraniya
  • 1,526
  • 2
  • 17
  • 36
  • This "answer" is more like a comment. We highly discourage such link only answers. – Till Aug 29 '17 at 15:37
  • I think it should be considered as comment. I have developed that library and also explained code in that link so I think no need to repeat the step here. @Till – vivek bhoraniya Aug 30 '17 at 05:00