Help, Im new to ios programming, I want to rotate may UIImage but I dont want the edges to be cut or loose some part of the image.
this is my code:
double angle = M_PI * 10/ 180; CGSize s = {image.size.width, image.size.height}; UIGraphicsBeginImageContext(s); CGContextRef ctx = UIGraphicsGetCurrentContext();
CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformTranslate(transform, image.size.width/2, image.size.height/2);
transform = CGAffineTransformRotate(transform, angle);
transform = CGAffineTransformScale(transform, 1.0, -1.0);
CGContextConcatCTM(ctx, transform);
CGContextDrawImage(ctx,CGRectMake(-[image size].width/2,-[image size].height/2,image.size.width, image.size.height),image.CGImage);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(newImage, nil, nil, nil);
The image is rotating but the size of the frame does not change because of that some of the image has been cut.
OUTPUT:https://fbcdn-sphotos-e-a.akamaihd.net/hphotos-ak-xpf1/t1.0-9/1555286_761679470521535_1800180000235265553_n.jpg
EXPECTED OUTPUT: https://fbcdn-photos-g-a.akamaihd.net/hphotos-ak-xfa1/t1.0-0/10314770_761675840521898_6536715783383115855_a.jpg
Please help me thank you.
This might be what you are searching for.
Just copy the following code at the end of the .m file (after the #end) in which you want to rotate an image.
#interface UIImage (RotationMethods)
- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees;
#end
#implementation UIImage (RotationMethods)
static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;};
- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees
{
// calculate the size of the rotated view's containing box for our drawing space
UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0,self.size.width, self.size.height)];
CGAffineTransform t = CGAffineTransformMakeRotation(DegreesToRadians(degrees));
rotatedViewBox.transform = t;
CGSize rotatedSize = rotatedViewBox.frame.size;
// Create the bitmap context
UIGraphicsBeginImageContext(rotatedSize);
CGContextRef bitmap = UIGraphicsGetCurrentContext();
// Move the origin to the middle of the image so we will rotate and scale around the center.
CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2);
// // Rotate the image context
CGContextRotateCTM(bitmap, DegreesToRadians(degrees));
// Now, draw the rotated/scaled image into the context
CGContextScaleCTM(bitmap, 1.0, -1.0);
CGContextDrawImage(bitmap, CGRectMake(-self.size.width / 2, -self.size.height / 2, self.size.width, self.size.height), [self CGImage]);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Then rotate your image like in the example below:
CGFloat degrees = 90;
yourImage = [yourImage imageRotatedByDegrees:degrees];
Related
I want to create a button that rotates an image in a UIImageView several times. After that I have to send it to an external API. I need not loose the proportions (like in the images)
Image after rotatation
Image before rotation
I have try two options
Option 1: I loose the proportions
(UIImage *)imageRotatedByDegrees:(UIImage*)oldImage deg:(CGFloat)degrees
{
// calculate the size of the rotated view's containing box for our drawing space
UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0,oldImage.size.width, oldImage.size.height)];
CGAffineTransform t = CGAffineTransformMakeRotation(degrees * M_PI / 180);
rotatedViewBox.transform = t;
CGSize rotatedSize = rotatedViewBox.frame.size;
// Create the bitmap context
UIGraphicsBeginImageContext(rotatedSize);
CGContextRef bitmap = UIGraphicsGetCurrentContext();
// Move the origin to the middle of the image so we will rotate and scale around the center.
CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2);
// // Rotate the image context
CGContextRotateCTM(bitmap, (degrees * M_PI / 180));
// Now, draw the rotated/scaled image into the context
CGContextScaleCTM(bitmap, 1.0, -1.0);
CGContextDrawImage(bitmap, CGRectMake(-oldImage.size.width / 2, -oldImage.size.height / 2, oldImage.size.width, oldImage.size.height), [oldImage CGImage]);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Option 2:
(UIImage*)upsideDownBunny:(CGFloat)radians withImage:(UIImage*)testImage {
__block CGImageRef cgImg;
__block CGSize imgSize;
__block UIImageOrientation orientation;
dispatch_block_t createStartImgBlock = ^(void) {
// UIImages should only be accessed from the main thread
UIImage *img =testImage;
imgSize = [img size]; // this size will be pre rotated
orientation = [img imageOrientation];
cgImg = CGImageRetain([img CGImage]); // this data is not rotated
};
if([NSThread isMainThread]) {
createStartImgBlock();
} else {
dispatch_sync(dispatch_get_main_queue(), createStartImgBlock);
}
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
// in iOS4+ you can let the context allocate memory by passing NULL
CGContextRef context = CGBitmapContextCreate( NULL,
imgSize.width,
imgSize.height,
8,
imgSize.width * 4,
colorspace,
kCGImageAlphaPremultipliedLast);
// rotate so the image respects the original UIImage's orientation
switch (orientation) {
case UIImageOrientationDown:
CGContextTranslateCTM(context, imgSize.width, imgSize.height);
CGContextRotateCTM(context, -radians);
break;
case UIImageOrientationLeft:
CGContextTranslateCTM(context, 0.0, imgSize.height);
CGContextRotateCTM(context, 3.0 * -radians / 2.0);
break;
case UIImageOrientationRight:
CGContextTranslateCTM(context,imgSize.width, 0.0);
CGContextRotateCTM(context, -radians / 2.0);
break;
default:
// there are mirrored modes possible
// but they aren't generated by the iPhone's camera
break;
}
// rotate the image upside down
CGContextTranslateCTM(context, +(imgSize.width * 0.5f), +(imgSize.height * 0.5f));
CGContextRotateCTM(context, -radians);
//CGContextDrawImage( context, CGRectMake(0.0, 0.0, imgSize.width, imgSize.height), cgImg );
CGContextDrawImage(context, (CGRect){.origin.x = -imgSize.width* 0.9f , .origin.y = -imgSize.width* 0.5f , .size.width = imgSize.width, .size.height = imgSize.width}, cgImg);
// grab the new rotated image
CGContextFlush(context);
CGImageRef newCgImg = CGBitmapContextCreateImage(context);
__block UIImage *newImage;
dispatch_block_t createRotatedImgBlock = ^(void) {
// UIImages should only be accessed from the main thread
newImage = [UIImage imageWithCGImage:newCgImg];
};
if([NSThread isMainThread]) {
createRotatedImgBlock();
} else {
dispatch_sync(dispatch_get_main_queue(), createRotatedImgBlock);
}
CGColorSpaceRelease(colorspace);
CGImageRelease(newCgImg);
CGContextRelease(context);
return newImage;
}
It works well with the rotation of the image but with every rotation the image and the view is reduced.
Can someone can help me?
If you want to animate the rotation you can use Core Animation. This will not change the image itself, just rotate it on the screen.
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
rotationAnimation.toValue = [NSNumber numberWithFloat:M_PI * 2.0];
rotationAnimation.duration = duration;
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = numRotations;
[self.imgviewRotate.layer addAnimation:animation forKey:#"animation"];
I have a problem to rotate UIImage without quality loss. Now I am using ready method provided by BFKit imageRotatedByDegrees:, but my image become diffused (blurred).
Sample code:
UIImage *image = [[UIImage imageNamed:#"car"] imageRotatedByDegrees:(((float)arc4random() / ARC4RANDOM_MAX) * (360))];
Code of imageRotatedByDegrees: :
- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees
{
// calculate the size of the rotated view's containing box for our drawing space
UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0,self.size.width, self.size.height)];
CGAffineTransform t = CGAffineTransformMakeRotation(DegreesToRadians(degrees));
rotatedViewBox.transform = t;
CGSize rotatedSize = rotatedViewBox.frame.size;
// Create the bitmap context
UIGraphicsBeginImageContext(rotatedSize);
CGContextRef bitmap = UIGraphicsGetCurrentContext();
// Move the origin to the middle of the image so we will rotate and scale around the center.
CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2);
// // Rotate the image context
CGContextRotateCTM(bitmap, DegreesToRadians(degrees));
// Now, draw the rotated/scaled image into the context
CGContextScaleCTM(bitmap, 1.0, -1.0);
CGContextDrawImage(bitmap, CGRectMake(-self.size.width / 2, -self.size.height / 2, self.size.width, self.size.height), [self CGImage]);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Is there another way to rotate UIImage without quality loss?
I'm the author of BFKit, and when I read about your question I investigated about that issue.
In the latest version (1.6.4) I've fixed that!
Now the image will no more be diffused (blurred).
My aim was to rotate an image that was in my MKAnnotationView. So I solved the problem by rotating not image, but whole MKAnnotationView.
An answer which helped me is this.
My code in MKMapViewDelegate method mapView:viewForAnnotation::
annotationView.transform = CGAffineTransformMakeRotation((((float)arc4random() / ARC4RANDOM_MAX) * (360)));
Hi in my iOS application I want to rotate the UIImage data in 90 Degrees.
I used the below code for 180 degree rotation - and it works fine.
- (UIImage*)upsideDownBunny:(UIImage *)img {
CGSize imgSize = [img size];
UIGraphicsBeginImageContext(imgSize);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextRotateCTM(context, M_PI);
CGContextTranslateCTM(context, -imgSize.width, -imgSize.height);
[img drawInRect:CGRectMake(0, 0, imgSize.width, imgSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
But when I try to rotate in 90 degree it is not working - please correct me
- (UIImage *)upsideDownBunny:(UIImage *)img {
CGSize imgSize = [img size];
UIGraphicsBeginImageContext(imgSize);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextRotateCTM(context, M_PI_2);
CGContextTranslateCTM(context, -imgSize.width, -imgSize.height);
[img drawInRect:CGRectMake(0, 0, imgSize.width, imgSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Try this...
UIImage * LandscapeImage = [UIImage imageNamed: imgname];
UIImage * PortraitImage = [[UIImage alloc] initWithCGImage: LandscapeImage.CGImage
scale: 1.0
orientation: UIImageOrientationLeft];
hope this helps you!
Try this
- (UIImage *)upsideDownBunny:(UIImage *)image {
// Rotate in degrees
CGFloat degrees = M_PI_2;
// Calculate the size of the rotated view's containing box for our drawing space
UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0, 0, image.size.width, image.size.height)];
CGAffineTransform transform = CGAffineTransformMakeRotation(degrees);
rotatedViewBox.transform = transform;
CGSize rotatedSize = rotatedViewBox.frame.size;
// Create image context
UIGraphicsBeginImageContext(rotatedSize);
CGContextRef context = UIGraphicsGetCurrentContext();
// Move the origin to the middle of the image.
CGContextTranslateCTM(context, rotatedSize.width * 0.5f, rotatedSize.height * 0.5f);
// Rotate the image context
CGContextRotateCTM(context, degrees);
// Now, draw the rotated/scaled image into the context
CGContextScaleCTM(context, 1.0, -1.0);
CGContextDrawImage(context, CGRectMake(-image.size.width * 0.5f, -image.size.height * 0.5f, image.size.width, image.size.height), [image CGImage]);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
The problem is your context is being rotated around (0,0) which is the top left corner and after 90 degrees rotate it will go out of bounds. So you need to move the origin of the context to middle.
I have read numerous answers related to this, but I still can't get it to work.
I have a view where a user can sign their name. Here's how it looks: http://d.pr/i/McuE
I can successfully retrieve this image and save it to the file system, but I need to rotate it 90 degrees before saving so the signature reads from left-to-right.
// Grab the image
UIGraphicsBeginImageContext(self.signArea.bounds.size);
[self.signArea drawRect: self.signArea.bounds];
UIImage *signatureImage = UIGraphicsGetImageFromCurrentImageContext();
//-- ? -- Rotate the image (this doesn't work) -- ? --
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextRotateCTM(context, M_PI_2);
UIGraphicsEndImageContext();
//Save the image as a PNG in Documents folder
[UIImagePNGRepresentation(signatureImage) writeToFile:[[PPHelpers documentsPath] stringByAppendingPathComponent:#"signature-temp.png"] atomically:YES];
How can I rotate the image prior to saving?
Thanks in advance for your help. I'm on Xcode 5 using the iOS 7 SDK.
I finally got this to work using one of the answers on this post: How to Rotate a UIImage 90 degrees?
I used this method:
- (UIImage *)imageRotatedByDegrees:(UIImage*)oldImage deg:(CGFloat)degrees{
//Calculate the size of the rotated view's containing box for our drawing space
UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0,oldImage.size.width, oldImage.size.height)];
CGAffineTransform t = CGAffineTransformMakeRotation(degrees * M_PI / 180);
rotatedViewBox.transform = t;
CGSize rotatedSize = rotatedViewBox.frame.size;
//Create the bitmap context
UIGraphicsBeginImageContext(rotatedSize);
CGContextRef bitmap = UIGraphicsGetCurrentContext();
//Move the origin to the middle of the image so we will rotate and scale around the center.
CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2);
//Rotate the image context
CGContextRotateCTM(bitmap, (degrees * M_PI / 180));
//Now, draw the rotated/scaled image into the context
CGContextScaleCTM(bitmap, 1.0, -1.0);
CGContextDrawImage(bitmap, CGRectMake(-oldImage.size.width / 2, -oldImage.size.height / 2, oldImage.size.width, oldImage.size.height), [oldImage CGImage]);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
And then called it like this:
//Rotate it
UIImage *rotatedImage = [self imageRotatedByDegrees:signatureImage deg:90];
Thanks, everyone.
I want to rotate a UIImageView with the press of a button. I am using this code:
#import "UIImage-Extensions.h"
UIImage *rotatedImage = [SplashItGroupPicker.image imageRotatedByDegrees:360/arrayCount];
SplashItGroupPicker.image = rotatedImage;
and in "UIImage-Extensions.h" i have:
#interface UIImage (CS_Extensions)
- (UIImage *)imageRotatedByRadians:(CGFloat)radians;
- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees;
and in the .m:
- (UIImage *)imageRotatedByRadians:(CGFloat)radians
{
return [self imageRotatedByDegrees:RadiansToDegrees(radians)];
}
- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees
{
// calculate the size of the rotated view's containing box for our drawing space
UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0,self.size.width, self.size.height)];
CGAffineTransform t = CGAffineTransformMakeRotation(DegreesToRadians(degrees));
rotatedViewBox.transform = t;
CGSize rotatedSize = rotatedViewBox.frame.size;
// Create the bitmap context
UIGraphicsBeginImageContext(rotatedSize);
CGContextRef bitmap = UIGraphicsGetCurrentContext();
// Move the origin to the middle of the image so we will rotate and scale around the center.
CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2);
// // Rotate the image context
CGContextRotateCTM(bitmap, DegreesToRadians(degrees));
// Now, draw the rotated/scaled image into the context
CGContextScaleCTM(bitmap, 1.0, -1.0);
CGContextDrawImage(bitmap, CGRectMake(-self.size.width / 2, -self.size.height / 2, self.size.width, self.size.height), [self CGImage]);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
...the rotation works fine, but when the image is rotated, the image also gets smaller and I can't understand why. Any ideas?
Here's a guess, is this only happening on Retina screens? Whenever saving a UIImage from a graphics context, you need to make sure the scale is correct. This is how I have done it:
CGFloat scale = [[UIScreen mainScreen] scale];
CGSize size = CGSizeMake(rotatedViewBox.frame.size.width * scale, rotatedViewBox.frame.size.height * scale);
UIGraphicsBeginImageContext( size );
/* Do your image manipulations here */
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// overwrite the image with one that has the correct scale set
newImage = [UIImage imageWithCGImage:newImage.CGImage scale:scale orientation:newImage.imageOrientation];
Using Kekoa's snippet (thanks a ton), I was able to get a working rotateImage function that works on retina devices based on Apples rotateImage code:
- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees {
CGFloat radians = DegreesToRadians(degrees);
UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0, self.size.width, self.size.height)];
CGAffineTransform t = CGAffineTransformMakeRotation(radians);
rotatedViewBox.transform = t;
CGSize rotatedSize = rotatedViewBox.frame.size;
UIGraphicsBeginImageContextWithOptions(rotatedSize, NO, [[UIScreen mainScreen] scale]);
CGContextRef bitmap = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(bitmap, rotatedSize.width / 2, rotatedSize.height / 2);
CGContextRotateCTM(bitmap, radians);
CGContextScaleCTM(bitmap, 1.0, -1.0);
CGContextDrawImage(bitmap, CGRectMake(-self.size.width / 2, -self.size.height / 2 , self.size.width, self.size.height), self.CGImage );
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
There is no need to UIGraphicsGetImageFromCurrentImageContext. its a way to get screenshot of desired portion of mainscreen. so the result image quality affected. the only way to get Rotated Image is...
first rotate your image view by(if you want to show rotated view)
[mainImgV setTransform:CGAffineTransformRotate(mainImgV.transform, M_PI)];
it will rotate your imageview.
now you will take this rotated image by these lines.(you can call these lines without rotate imgaeview also.)
CGImageRef cgRef = mainImgV.image.CGImage;
newImage = [[UIImage alloc] initWithCGImage:cgRef scale:1.0 orientation:UIImageOrientationDown];
there is no need to save or take screenshot or compromise bad quality image. just enjoy coding.