create ios swift uiimage

ios - create - uiimageview set image swift



Rotar UIImage en Swift (11)

Estoy usando Xcode 6.0.1 con Swift. Tengo un UIImage, y me gustaría hacer otra imagen usando la imagen anterior como fuente, con la nueva imagen rotada de alguna manera ... digamos 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: .DownMirrored)

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

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

¿Qué piensas?

Necesito que esto se ejecute en esta versión de Xcode, por lo que si hay una forma alternativa de realizar la rotación (todavía no he encontrado una), sería útil.


Solución Swift 5

Aquí está la solución más simple.

extension UIImage { func rotate(radians: Float) -> UIImage? { var newSize = CGRect(origin: CGPoint.zero, size: self.size).applying(CGAffineTransform(rotationAngle: CGFloat(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) UIGraphicsBeginImageContextWithOptions(newSize, false, self.scale) let context = UIGraphicsGetCurrentContext()! // Move origin to middle context.translateBy(x: newSize.width/2, y: newSize.height/2) // Rotate around middle context.rotate(by: CGFloat(radians)) // Draw the image at its center self.draw(in: CGRect(x: -self.size.width/2, y: -self.size.height/2, width: self.size.width, height: self.size.height)) let newImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return newImage } }

y para usar esta solución puedes hacer lo siguiente

let image = UIImage(named: "image.png")! let newImage = image.rotate(radians: .pi/2) // Rotate 90 degrees


Aquí hay una extensión simple para 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 } }

( Source )

Úselo con:

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

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


El ''argumento adicional en la llamada'' generalmente ocurre cuando uno de los tipos de entrada es incorrecto.

Puedes arreglar tu código con

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


Esto funciona para iOS 8+ y mantiene la calidad de la imagen. Son dos extensiones para UIImage.

extension UIImage { func withSize(_ width: CGFloat, _ height: CGFloat) -> UIImage { let target = CGSize(width, height) var scaledImageRect = CGRect.zero let aspectWidth:CGFloat = target.width / self.size.width let aspectHeight:CGFloat = target.height / self.size.height let aspectRatio:CGFloat = min(aspectWidth, aspectHeight) scaledImageRect.size.width = self.size.width * aspectRatio scaledImageRect.size.height = self.size.height * aspectRatio scaledImageRect.origin.x = (target.width - scaledImageRect.size.width) / 2.0 scaledImageRect.origin.y = (target.height - scaledImageRect.size.height) / 2.0 UIGraphicsBeginImageContextWithOptions(target, false, 0) self.draw(in: scaledImageRect) let scaledImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return scaledImage! } func rotated(degrees: Double) -> UIImage { let radians = CGFloat(Double.pi * degrees / 180) var rotatedViewBox: UIView? = UIView(frame: CGRect(x: 0, y: 0, width: size.width * scale, height: size.height * scale)) let t = CGAffineTransform(rotationAngle: radians) rotatedViewBox!.transform = t let rotatedSize = rotatedViewBox!.frame.size rotatedViewBox = nil // 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, y: rotatedSize.height/2) // // Rotate the image context bitmap.rotate(by: radians) // Now, draw the rotated/scaled image into the context bitmap.scaleBy(x: 1.0, y: -1.0) bitmap.draw(cgImage!, in: CGRect(x:-size.width * scale / 2, y: -size.height * scale / 2, width: size.width * scale, height: size.height * scale)) let newImage = UIGraphicsGetImageFromCurrentImageContext()! UIGraphicsEndImageContext() return newImage.withSize(newImage.size.width/scale, newImage.size.height/scale) } }


Mira esto:

func rotatedImage(with angle: CGFloat) -> UIImage { let updatedSize = CGRect(origin: .zero, size: size) .applying(CGAffineTransform(rotationAngle: angle)) .size return UIGraphicsImageRenderer(size: updatedSize) .image { _ in let context = UIGraphicsGetCurrentContext() context?.translateBy(x: updatedSize.width / 2.0, y: updatedSize.height / 2.0) context?.rotate(by: angle) draw(in: CGRect(x: -size.width / 2.0, y: -size.height / 2.0, width: size.width, height: size.height)) } .withRenderingMode(renderingMode) }


No use UIGraphicsBeginImageContext porque destruirá la calidad de su vector, use UIGraphicsBeginImageContextWithOptions . Esta es mi implementación en Swift 3/4:

extension UIImage { func rotated(degrees: CGFloat) -> UIImage? { let degreesToRadians: (CGFloat) -> CGFloat = { (degrees: CGFloat) in return degrees / 180.0 * CGFloat.pi } // Calculate the size of the rotated view''s containing box for our drawing space let rotatedViewBox: UIView = UIView(frame: CGRect(origin: .zero, size: size)) rotatedViewBox.transform = CGAffineTransform(rotationAngle: degreesToRadians(degrees)) let rotatedSize: CGSize = rotatedViewBox.frame.size // Create the bitmap context UIGraphicsBeginImageContextWithOptions(rotatedSize, false, 0.0) guard let bitmap: CGContext = UIGraphicsGetCurrentContext(), let unwrappedCgImage: CGImage = cgImage else { return nil } // 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)) bitmap.scaleBy(x: CGFloat(1.0), y: -1.0) let rect: CGRect = CGRect( x: -size.width/2, y: -size.height/2, width: size.width, height: size.height) bitmap.draw(unwrappedCgImage, in: rect) guard let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext() else { return nil } UIGraphicsEndImageContext() return newImage }


Prueba este código, funcionó para mí:

@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() } } }


Para Swift 4.2

extension UIImage { func rotate(_ radians: CGFloat) -> UIImage { let cgImage = self.cgImage! let LARGEST_SIZE = CGFloat(max(self.size.width, self.size.height)) let context = CGContext.init(data: nil, width:Int(LARGEST_SIZE), height:Int(LARGEST_SIZE), bitsPerComponent: cgImage.bitsPerComponent, bytesPerRow: 0, space: cgImage.colorSpace!, bitmapInfo: cgImage.bitmapInfo.rawValue)! var drawRect = CGRect.zero drawRect.size = self.size let drawOrigin = CGPoint(x: (LARGEST_SIZE - self.size.width) * 0.5,y: (LARGEST_SIZE - self.size.height) * 0.5) drawRect.origin = drawOrigin var tf = CGAffineTransform.identity tf = tf.translatedBy(x: LARGEST_SIZE * 0.5, y: LARGEST_SIZE * 0.5) tf = tf.rotated(by: CGFloat(radians)) tf = tf.translatedBy(x: LARGEST_SIZE * -0.5, y: LARGEST_SIZE * -0.5) context.concatenate(tf) context.draw(cgImage, in: drawRect) var rotatedImage = context.makeImage()! drawRect = drawRect.applying(tf) rotatedImage = rotatedImage.cropping(to: drawRect)! let resultImage = UIImage(cgImage: rotatedImage) return resultImage } }


Respuesta de @confile 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! } }


Swift 3:

Rotación hacia 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()


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) } } }

Puedes usarlo así:

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

Con la bandera invertida especificada:

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