Rotate UIImage custom degree

15,292

Solution 1

This method return you image on your angle of rotate

#pragma mark -
#pragma mark Rotate Image 

- (UIImage *)scaleAndRotateImage:(UIImage *)image  { 

    CGImageRef imgRef = image.CGImage;

    CGFloat width = CGImageGetWidth(imgRef);
    CGFloat height = CGImageGetHeight(imgRef);

    CGAffineTransform transform = CGAffineTransformIdentity;
    CGRect bounds = CGRectMake(0, 0, width, height);

    CGFloat boundHeight;

    boundHeight = bounds.size.height;  
    bounds.size.height = bounds.size.width; 
    bounds.size.width = boundHeight;
    transform = CGAffineTransformMakeScale(-1.0, 1.0);
    transform = CGAffineTransformRotate(transform, M_PI / 2.0); //use angle/360 *MPI

    UIGraphicsBeginImageContext(bounds.size);   
    CGContextRef context = UIGraphicsGetCurrentContext();   
    CGContextConcatCTM(context, transform); 
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imgRef);
    UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return imageCopy;   

}

Solution 2

- (UIImage *)rotate:(UIImage *)image radians:(float)rads
{
    float newSide = MAX([image size].width, [image size].height);
    CGSize size =  CGSizeMake(newSide, newSide);
    UIGraphicsBeginImageContext(size);
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(ctx, newSide/2, newSide/2);
    CGContextRotateCTM(ctx, rads);
    CGContextDrawImage(UIGraphicsGetCurrentContext(),CGRectMake(-[image size].width/2,-[image size].height/2,size.width, size.height),image.CGImage);
    //CGContextTranslateCTM(ctx, [image size].width/2, [image size].height/2);

    UIImage *i = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return i;
}

this function rotates any image on its center, but the image becomes a square so I would suggest referencing the image center when drawing it after this function.

Solution 3

You need to address two things to make this work.

  1. You are rotating about the bottom corner of the image instead of the centre
  2. The bounding rectangle of the resulting image needs to be larger now the image is rotated for it to fit in.

To solve the rotation about the centre, first perform a translate to the centre, then rotate, then translate back.

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 context
CGContextDrawImage(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 context
rotatedImage = [UIImage imageWithCGImage: CGBitmapContextCreateImage(context)];

To calculate the size of the bounding rectangle you'd need to fit the new rotated image into use this:

- (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);
}

You can find these techniques in my previous posts and answers here:

Creating a UIImage from a rotated UIImageView

and here:

Saving 2 UIImages

Hope this helps,

Dave

Share:
15,292
Admin
Author by

Admin

Updated on June 04, 2022

Comments

  • Admin
    Admin almost 2 years

    I want to rotate an UIImage (not UIImageView) in custom degree I followed this post but it didn't work for me.

    Anyone can help? Thanks.

    UPDATE: The code below does some of the job, but I lose some of the image after rotating it:

    enter image description here

    What should I change to get it right? (btw the yellow color in the screenshots is my UIImageView bg)

    - (UIImage *) rotate: (UIImage *) image
    {
        double angle = 20;
        CGSize s = {image.size.width, image.size.height};
        UIGraphicsBeginImageContext(s);
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        CGContextTranslateCTM(ctx, 0,image.size.height);
        CGContextScaleCTM(ctx, 1.0, -1.0);
    
        CGContextRotateCTM(ctx, 2*M_PI*angle/360);
        CGContextDrawImage(ctx,CGRectMake(0,0,image.size.width, image.size.height),image.CGImage);
        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return newImage;
    
    }
    
  • Nyx0uf
    Nyx0uf about 13 years
    Except that he want to rotate the image itself, not the view that contains it.
  • Admin
    Admin about 13 years
    this code rotate it in 90degrees right? what if I need to rotate it to left or right in 5 degrees only ?
  • Martin
    Martin almost 12 years
    Great! is imageCopy in autorelease mode ?
  • Guy
    Guy over 11 years
    Image is rotated but is upside down.
  • Pion
    Pion about 11 years
    Hi, this code does not work with photos that has different orientation than UIImageOrientationUp, do you have any solution?
  • Dev2rights
    Dev2rights almost 11 years
    Image rotates but is flipped too