Rotating UIImage en Swift

Estoy usando Xcode 6.0.1 con Swift. Tengo un UIImage, y me gustaría hacer otra image usando la image anterior como fuente, con la nueva image girada de alguna forma … por ejemplo, volteada verticalmente.

Esta pregunta ya fue respondida hace unos meses . Sin embargo, esa solución no funciona para mí, a pesar de que la situación es idéntica.

Cuando tengo

var image = UIImage(CGImage: otherImage.CGImage, scale: 1.0, orientation: .DownMirronetworking) 

Xcode se queja de que hay una "escala de argumento adicional" en llamada ". Después de verificar con la documentation de Apple, esto no tiene sentido, ya que esa versión del inicializador toma esos tres arguments. Dejar los arguments de escala y orientación soluciona el problema, pero me impide hacer la rotation.

La única otra reference a esto que puedo encontrar es este chico , que tenía el mismo problema.

¿Qué piensas?

Necesito esto para ejecutarse en esta versión de Xcode, así que si hay una forma alternativa de realizar la rotation (todavía no la encontré), sería útil.

Aquí hay una extensión simple a UIImage:

 //ImageRotation.swift import UIKit extension UIImage { public func imageRotatedByDegrees(degrees: CGFloat, flip: Bool) -> UIImage { let radiansToDegrees: (CGFloat) -> CGFloat = { return $0 * (180.0 / CGFloat(M_PI)) } let degreesToRadians: (CGFloat) -> CGFloat = { return $0 / 180.0 * CGFloat(M_PI) } // calculate the size of the rotated view's containing box for our drawing space let rotatedViewBox = UIView(frame: CGRect(origin: CGPointZero, size: size)) let t = CGAffineTransformMakeRotation(degreesToRadians(degrees)); rotatedViewBox.transform = t let rotatedSize = rotatedViewBox.frame.size // Create the bitmap context UIGraphicsBeginImageContext(rotatedSize) let bitmap = UIGraphicsGetCurrentContext() // Move the origin to the middle of the image so we will rotate and scale around the center. CGContextTranslateCTM(bitmap, rotatedSize.width / 2.0, rotatedSize.height / 2.0); // // Rotate the image context CGContextRotateCTM(bitmap, degreesToRadians(degrees)); // Now, draw the rotated/scaled image into the context var yFlip: CGFloat if(flip){ yFlip = CGFloat(-1.0) } else { yFlip = CGFloat(1.0) } CGContextScaleCTM(bitmap, yFlip, -1.0) CGContextDrawImage(bitmap, CGRectMake(-size.width / 2, -size.height / 2, size.width, size.height), CGImage) let newImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return newImage } } 

( Fuente )

Úselo con:

 rotatedPhoto = rotatedPhoto?.imageRotatedByDegrees(90, flip: false) 

El primero rotará una image y la volteará si el flip se establece en verdadero.

En Swift 3 para iOS 10:

 extension UIImage { struct RotationOptions: OptionSet { let rawValue: Int static let flipOnVerticalAxis = RotationOptions(rawValue: 1) static let flipOnHorizontalAxis = RotationOptions(rawValue: 2) } func rotated(by rotationAngle: Measurement<UnitAngle>, options: RotationOptions = []) -> UIImage? { guard let cgImage = self.cgImage else { return nil } let rotationInRadians = CGFloat(rotationAngle.converted(to: .radians).value) let transform = CGAffineTransform(rotationAngle: rotationInRadians) var rect = CGRect(origin: .zero, size: self.size).applying(transform) rect.origin = .zero let renderer = UIGraphicsImageRenderer(size: rect.size) return renderer.image { renderContext in renderContext.cgContext.translateBy(x: rect.midX, y: rect.midY) renderContext.cgContext.rotate(by: rotationInRadians) let x = options.contains(.flipOnVerticalAxis) ? -1.0 : 1.0 let y = options.contains(.flipOnHorizontalAxis) ? 1.0 : -1.0 renderContext.cgContext.scaleBy(x: CGFloat(x), y: CGFloat(y)) let drawRect = CGRect(origin: CGPoint(x: -self.size.width/2, y: -self.size.height/2), size: self.size) renderContext.cgContext.draw(cgImage, in: drawRect) } } } 

Puede usarlo así:

 let rotatedImage = UIImage(named: "my_amazing_image")?.rotated(by: Measurement(value: 48.0, unit: .degrees)) 

Con la bandera girada especificada:

 let flippedImage = UIImage(named: "my_amazing_image")?.rotated(by: Measurement(value: 48.0, unit: .degrees), options: [.flipOnVerticalAxis]) 

'Argumento adicional en llamada' generalmente ocurre cuando uno de los types de input es incorrecto.

Puedes arreglar tu código con

 var image = UIImage(CGImage: otherImage.CGImage, scale: CGFloat(1.0), orientation: .DownMirronetworking) 

Swift 3:

Girando a la derecha:

 let image = UIImage(cgImage: otherImage.cgImage!, scale: CGFloat(1.0), orientation: .right) 

Probado en el patio de recreo:

 // MyPlayground.playground import UIKit import PlaygroundSupport let view = UIView(frame: CGRect(x: 0, y: 0, width: 500, height: 500)) view.backgroundColor = UIColor.white PlaygroundPage.current.liveView = view let otherImage = UIImage(named: "burger.png", in: Bundle.main, compatibleWith: nil) let imageViewLeft = UIImageView(image: UIImage(cgImage: (otherImage?.cgImage!)!, scale: CGFloat(1.0), orientation: .left)) let imageViewRight = UIImageView(image: UIImage(cgImage: (otherImage?.cgImage!)!, scale: CGFloat(1.0), orientation: .right)) view.addSubview(imageViewLeft) view.addSubview(imageViewRight) view.layoutIfNeeded() 

Prueba este código, me funcionó:

 @IBAction func btnRotateImagePressed(sender: AnyObject) { if let originalImage = self.imageView.image { let rotateSize = CGSize(width: originalImage.size.height, height: originalImage.size.width) UIGraphicsBeginImageContextWithOptions(rotateSize, true, 2.0) if let context = UIGraphicsGetCurrentContext() { CGContextRotateCTM(context, 90.0 * CGFloat(M_PI) / 180.0) CGContextTranslateCTM(context, 0, -originalImage.size.height) originalImage.drawInRect(CGRectMake(0, 0, originalImage.size.width, originalImage.size.height)) self.imageView.image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() } } } 

@confile respuesta actualizada a Swift 4

 import UIKit extension UIImage { public func imageRotatedByDegrees(degrees: CGFloat, flip: Bool) -> UIImage { let radiansToDegrees: (CGFloat) -> CGFloat = { return $0 * (180.0 / CGFloat.pi) } let degreesToRadians: (CGFloat) -> CGFloat = { return $0 / 180.0 * CGFloat.pi } // calculate the size of the rotated view's containing box for our drawing space let rotatedViewBox = UIView(frame: CGRect(origin: .zero, size: size)) let t = CGAffineTransform(rotationAngle: degreesToRadians(degrees)); rotatedViewBox.transform = t let rotatedSize = rotatedViewBox.frame.size // Create the bitmap context UIGraphicsBeginImageContext(rotatedSize) let bitmap = UIGraphicsGetCurrentContext() // Move the origin to the middle of the image so we will rotate and scale around the center. bitmap?.translateBy(x: rotatedSize.width / 2.0, y: rotatedSize.height / 2.0) // // Rotate the image context bitmap?.rotate(by: degreesToRadians(degrees)) // Now, draw the rotated/scaled image into the context var yFlip: CGFloat if(flip){ yFlip = CGFloat(-1.0) } else { yFlip = CGFloat(1.0) } bitmap?.scaleBy(x: yFlip, y: -1.0) let rect = CGRect(x: -size.width / 2, y: -size.height / 2, width: size.width, height: size.height) bitmap?.draw(cgImage!, in: rect) let newImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return newImage! } }