UIGraphicsImageRenderer
was newly introduced in iOS 10. I was wondering if there is any possibility to rotate an UIImage
with it (any custom angle). I know there is the classic way with CGContextRotateCTM
.
Rotate image with UIGraphicsImageRenderer?
Asked Answered
You can setup UIGraphicsImageRenderer to create an image and with that call the UIGraphicsGetCurrentContext() and rotate the context
let renderer = UIGraphicsImageRenderer(size:sizeOfImage)
let image = renderer.image(actions: { _ in
let context = UIGraphicsGetCurrentContext()
context?.translateBy(x: orgin.x, y: orgin.y)
context?.rotate(by: angle)
context?.draw(image.cgImage!, in: CGRect(origin: CGPoint(x: -orgin.x,y: -orgin.y), size: size))
}
return image
Instead of grabbing the current context, I think you'd want to use the renderer's context.cgContext property since it's automatically managed. –
Belinda
As of 2021.10.23 this code does not work anymore. –
Fernandez
Built on @reza23's answer. You don't need to call UIGraphicsGetCurrentContext, you can use renderer's context.
extension UIImage {
public func rotate(_ angle: Angle) -> UIImage {
var newSize = CGRect(origin: CGPoint.zero, size: self.size).applying(CGAffineTransform(rotationAngle: angle.radians)).size
// Trim off the extremely small float value to prevent core graphics from rounding it up
newSize.width = floor(newSize.width)
newSize.height = floor(newSize.height)
let image = UIGraphicsImageRenderer(size:newSize).image { renderer in
let context = renderer.cgContext
//rotate from center
context.translateBy(x: newSize.width/2, y: newSize.height/2)
context.rotate(by: angle.radians)
draw(in: CGRect(origin: CGPoint(x: -self.size.width/2, y: -self.size.height/2), size: size))
}
return image
}
}
Going through the documentation and also due to the lack of replies on this question, I assume that it is not possible with the new UIGraphicsImageRenderer
. Here is how I solved it at the end of the day:
func changeImageRotation(forImage image:UIImage, rotation alpha:CGFloat) -> UIImage{
var newSize:CGSize{
let a = image.size.width
let b = image.size.height
let width = abs(cos(alpha)) * a + abs(sin(alpha)) * b
let height = abs(cos(alpha)) * b + abs(sin(alpha)) * a
return CGSize(width: width, height: height)
}
let size = newSize
let orgin = CGPoint(x: size.width/2, y: size.height/2)
UIGraphicsBeginImageContext(size)
let context = UIGraphicsGetCurrentContext()
context?.translateBy(x: orgin.x, y: orgin.y)
context?.rotate(by: alpha)
context?.draw(image.cgImage!, in: CGRect(origin: CGPoint(x: -orgin.x,y: -orgin.y), size: size))
let newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage!
}
New Size
corresponds to the rectangular area that is required to draw the rotated image without changing its overall size. The image is than rotated and drawn in the center. For more information on that, refer to this post.
Cool but expensive (performance). Hope there's a better way –
Armenian
© 2022 - 2024 — McMap. All rights reserved.