可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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
回答1:
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
}
}
回答2:
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;
}
回答3:
In Swift 4
imageView.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi/2))
回答4:
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
}
}
回答5:
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
}
回答6:
self.imageview.transform = CGAffineTransformMakeRotation(M_PI/2);