简体   繁体   中英

How Can I Rotate A UIImage and Image Data By 90 Degrees

I have a UIImageView that contains an image. At the minute the user can click to save the image within the UIImageView to disk.

I would like to make it so that the the user can click to rotate the UIImageView and also rotate the UImage within the view so that when the image is saved it keeps the new rotation.

At the minute I have

- (IBAction)rotateImage:(id)sender {

float degrees = 90; //the value in degrees
self.imagePreview.transform = CGAffineTransformMakeRotation(degrees * M_PI/180);

}

Can someone point me in the right direction regarding keeping the current rotation.

Thanks

I have such code in my old app. But this code can be simplified because you have no need to rotate it on non-90 degrees angle.

Objective-C

@implementation UIImage (Rotation)

- (UIImage *)imageRotatedOnDegrees:(CGFloat)degrees
{
  // Follow ing code can only rotate images on 90, 180, 270.. degrees.
  CGFloat roundedDegrees = (CGFloat)(round(degrees / 90.0) * 90.0);
  BOOL sameOrientationType = ((NSInteger)roundedDegrees) % 180 == 0;
  CGFloat radians = M_PI * roundedDegrees / 180.0;
  CGSize newSize = sameOrientationType ? self.size : CGSizeMake(self.size.height, self.size.width);

  UIGraphicsBeginImageContext(newSize);
  CGContextRef ctx = UIGraphicsGetCurrentContext();
  CGImageRef cgImage = self.CGImage;
  if (ctx == NULL || cgImage == NULL) {
    UIGraphicsEndImageContext();
    return self;
  }

  CGContextTranslateCTM(ctx, newSize.width / 2.0, newSize.height / 2.0);
  CGContextRotateCTM(ctx, radians);
  CGContextScaleCTM(ctx, 1, -1);
  CGPoint origin = CGPointMake(-(self.size.width / 2.0), -(self.size.height / 2.0));
  CGRect rect = CGRectZero;
  rect.origin = origin;
  rect.size = self.size;
  CGContextDrawImage(ctx, rect, cgImage);
  UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();
  return image ?: self;
}

@end

Swift

extension UIImage {

  func imageRotated(on degrees: CGFloat) -> UIImage {
    // Following code can only rotate images on 90, 180, 270.. degrees.
    let degrees = round(degrees / 90) * 90
    let sameOrientationType = Int(degrees) % 180 == 0
    let radians = CGFloat.pi * degrees / CGFloat(180)
    let newSize = sameOrientationType ? size : CGSize(width: size.height, height: size.width)

    UIGraphicsBeginImageContext(newSize)
    defer {
      UIGraphicsEndImageContext()
    }

    guard let ctx = UIGraphicsGetCurrentContext(), let cgImage = cgImage else {
      return self
    }

    ctx.translateBy(x: newSize.width / 2, y: newSize.height / 2)
    ctx.rotate(by: radians)
    ctx.scaleBy(x: 1, y: -1)
    let origin = CGPoint(x: -(size.width / 2), y: -(size.height / 2))
    let rect = CGRect(origin: origin, size: size)
    ctx.draw(cgImage, in: rect)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    return image ?? self
  }

}

This will rotate an image by any given radians.

Note this works 2x and 3x retina as well

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

在Swift 4中

imageView.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi/2))

The highlighted state of a UIButton did not take the correct orientation of the normal inserted turned image. So I had to redraw the image like @RyanG showed. Here is the Swift 2.2 code for that:

extension UIImage
{
    /// Rotate an image by any given radians.
    /// Works for 2x and 3x retina as well.
    func imageRotatedByDegrees(degrees: Double) -> UIImage
    {
        let radians = CGFloat(degrees * (M_PI / 180.0))

        let rotatedViewBox = UIView(frame: CGRect(origin: CGPointZero, size: self.size))
        let t: CGAffineTransform = CGAffineTransformMakeRotation(radians)
        rotatedViewBox.transform = t
        let rotatedSize = rotatedViewBox.frame.size

        UIGraphicsBeginImageContextWithOptions(rotatedSize, false, self.scale)
        let bitmap = UIGraphicsGetCurrentContext()

        CGContextTranslateCTM(bitmap, rotatedSize.width / 2, rotatedSize.height / 2)
        CGContextRotateCTM(bitmap, radians)
        CGContextScaleCTM(bitmap, 1.0, -1.0)
        CGContextDrawImage(bitmap, CGRect(origin: CGPoint(x: -self.size.width / 2, y: -self.size.height / 2), size: self.size), self.CGImage)

        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage
    }
}

Swift version made from answer of @RyanG with some fixes:

func rotated(by degrees: CGFloat) -> UIImage {
    let radians : CGFloat = degrees * CGFloat(.pi / 180.0)
    let rotatedViewBox = UIView(frame: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height))
    let t = CGAffineTransform(rotationAngle: radians)
    rotatedViewBox.transform = t
    let rotatedSize = rotatedViewBox.frame.size
    UIGraphicsBeginImageContextWithOptions(rotatedSize, false, self.scale)
    defer { UIGraphicsEndImageContext() }
    guard let bitmap = UIGraphicsGetCurrentContext(), let cgImage = self.cgImage else {
      return self
    }
    bitmap.translateBy(x: rotatedSize.width / 2, y: rotatedSize.height / 2)
    bitmap.rotate(by: radians)
    bitmap.scaleBy(x: 1.0, y: -1.0)
    bitmap.draw(cgImage, in: CGRect(x: -self.size.width / 2, y: -self.size.height / 2, width: self.size.width, height: self.size.height))
    guard let newImage = UIGraphicsGetImageFromCurrentImageContext() else {
      return self
    }
    return newImage
  }

self.imageview.transform = CGAffineTransformMakeRotation(M_PI/2);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM