7

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.

Community
  • 1
  • 1
Christoph
  • 702
  • 6
  • 16

3 Answers3

6

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
pkamb
  • 33,281
  • 23
  • 160
  • 191
reza23
  • 3,079
  • 2
  • 27
  • 42
3

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
    }
}
tim
  • 57
  • 7
Ozgur Sahin
  • 1,305
  • 16
  • 24
2

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 Sizecorresponds 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.

Community
  • 1
  • 1
Christoph
  • 702
  • 6
  • 16