Corta un UIImage en un círculo

Quiero cortar un UIImage en un círculo para poder usarlo como anotación. Cada respuesta en este sitio que he encontrado describe la creación de un UIImageView , luego lo modifica y lo muestra, pero no se puede establecer la imagen de una anotación en un UIImageView , solo un UIImage . ¿Cómo debo ir sobre esto?

Asegúrese de importar QuarzCore si es necesario.

  func maskRoundedImage(image: UIImage, radius: CGFloat) -> UIImage { let imageView: UIImageView = UIImageView(image: image) let layer = imageView.layer layer.masksToBounds = true layer.cornerRadius = radius UIGraphicsBeginImageContext(imageView.bounds.size) layer.render(in: UIGraphicsGetCurrentContext()!) let roundedImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return roundedImage! } 

Xcode 8.2 • Swift 3.0.2

 extension UIImage { var isPortrait: Bool { return size.height > size.width } var isLandscape: Bool { return size.width > size.height } var breadth: CGFloat { return min(size.width, size.height) } var breadthSize: CGSize { return CGSize(width: breadth, height: breadth) } var breadthRect: CGRect { return CGRect(origin: .zero, size: breadthSize) } var circleMasked: UIImage? { UIGraphicsBeginImageContextWithOptions(breadthSize, false, scale) defer { UIGraphicsEndImageContext() } guard let cgImage = cgImage?.cropping(to: CGRect(origin: CGPoint(x: isLandscape ? floor((size.width - size.height) / 2) : 0, y: isPortrait ? floor((size.height - size.width) / 2) : 0), size: breadthSize)) else { return nil } UIBezierPath(ovalIn: breadthRect).addClip() UIImage(cgImage: cgImage, scale: 1, orientation: imageOrientation).draw(in: breadthRect) return UIGraphicsGetImageFromCurrentImageContext() } } 

Prueba de patio de recreo

 let profilePicture = UIImage(data: try! Data(contentsOf: URL(string:"http://i.stack.imgur.com/Xs4RX.jpg")!))! profilePicture.circleMasked 

UIImage extensión:

 extension UIImage { func circularImage(size size: CGSize?) -> UIImage { let newSize = size ?? self.size let minEdge = min(newSize.height, newSize.width) let size = CGSize(width: minEdge, height: minEdge) UIGraphicsBeginImageContextWithOptions(size, false, 0.0) let context = UIGraphicsGetCurrentContext() self.drawInRect(CGRect(origin: CGPoint.zero, size: size), blendMode: .Copy, alpha: 1.0) CGContextSetBlendMode(context, .Copy) CGContextSetFillColorWithColor(context, UIColor.clearColor().CGColor) let rectPath = UIBezierPath(rect: CGRect(origin: CGPoint.zero, size: size)) let circlePath = UIBezierPath(ovalInRect: CGRect(origin: CGPoint.zero, size: size)) rectPath.appendPath(circlePath) rectPath.usesEvenOddFillRule = true rectPath.fill() let result = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return result } } 

Uso:

UIImageView:

 @IBDesignable class CircularImageView: UIImageView { override var image: UIImage? { didSet { super.image = image?.circularImage(size: nil) } } } 

UIButton:

 @IBDesignable class CircularImageButton: UIButton { override func setImage(image: UIImage?, forState state: UIControlState) { let circularImage = image?.circularImage(size: nil) super.setImage(circularImage, forState: state) } } 

Xcode 8.1, Swift 3.0.1

Mi código se verá así:

 let image = yourImage.resize(CGSize(width: 20, height: 20))?.circled(forRadius: 20) 

Agrega UIImage Extension, luego:

 func resize(_ size: CGSize) -> UIImage? { let rect = CGRect(origin: .zero, size: size) return redraw(in: rect) } func redraw(in rect: CGRect) -> UIImage? { UIGraphicsBeginImageContextWithOptions(rect.size, false, UIScreen.main.scale) guard let context = UIGraphicsGetCurrentContext(), let cgImage = cgImage else { return nil } let rect = CGRect(origin: .zero, size: size) let flipVertical = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: rect.size.height) context.concatenate(flipVertical) context.draw(cgImage, in: rect) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return image } func circled(forRadius radius: CGFloat) -> UIImage? { let rediusSize = CGSize(width: radius, height: radius) let rect = CGRect(origin: .zero, size: size) UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale) guard let context = UIGraphicsGetCurrentContext(), let cgImage = cgImage else { return nil } let flipVertical = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: rect.size.height) context.concatenate(flipVertical) let bezierPath = UIBezierPath(roundedRect: rect, byRoundingCorners: [.allCorners], cornerRadii: rediusSize) context.addPath(bezierPath.cgPath) context.clip() context.drawPath(using: .fillStroke) context.draw(cgImage, in: rect) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return image } 

¡Pude responder mi propia pregunta buscando el uso de BezierPath!

 if let xyz = UIImage(contentsOfFile: readPath) { var Rect: CGRect = CGRectMake(0, 0, xyz.size.width, xyz.size.height) var x = UIBezierPath(roundedRect: Rect, cornerRadius: 200).addClip() UIGraphicsBeginImageContextWithOptions(xyz.size, false, xyz.scale) xyz.drawInRect(Rect) var ImageNew = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() annotation.image = ImageNew } 

Puedes usar este código para hacer un círculo Image

 extension UIImage { func circleImage(_ cornerRadius: CGFloat, size: CGSize) -> UIImage? { let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height) UIGraphicsBeginImageContextWithOptions(size, false, 0) if let context = UIGraphicsGetCurrentContext() { var path: UIBezierPath if size.height == size.width { if cornerRadius == size.width/2 { path = UIBezierPath(arcCenter: CGPoint(x: size.width/2, y: size.height/2), radius: cornerRadius, startAngle: 0, endAngle: 2.0*CGFloat(Double.pi), clockwise: true) }else { path = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius) } }else { path = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius) } context.addPath(path.cgPath) context.clip() self.draw(in: rect) // 从上下文上获取剪裁后的照片guard let uncompressedImage = UIGraphicsGetImageFromCurrentImageContext() else { UIGraphicsEndImageContext() return nil } // 关闭上下文UIGraphicsEndImageContext() return uncompressedImage }else { return nil } }} 

swift 3 se ajusta al patrón MVC crea un archivo externo

 @IBDesignable class RoundImage: UIImageView{ @IBInspectable var cornerRadius: CGFloat = 0 { didSet{ self.layer.cornerRadius = cornerRadius } } // set border width @IBInspectable var borderWidth: CGFloat = 0 { didSet{ self.layer.borderWidth = borderWidth } } // set border color @IBInspectable var borderColor: UIColor = UIColor.clear { didSet{ self.layer.borderColor = borderColor.cgColor } } override func awakeFromNib() { self.clipsToBounds = true } }// class 

llame a la clase en el IB en el guión gráfico

llame a la clase en el IB en el guión gráfico

pon el cornerradius como quieras (1/2 de ancho si deseas un círculo)

establecer atributo

¡Hecho!

Todas estas respuestas fueron realmente complejas para una solución directa. Acabo de replicar mi código Objective-C y ajustado para Swift.

 self.myImageView?.layer.cornerRadius = (self.myImageView?.frame.size.width)! / 2; self.myImageView?.clipsToBounds = true 

Basado en la respuesta de Nikos:

 public extension UIImage { func roundedImage() -> UIImage { let imageView: UIImageView = UIImageView(image: self) let layer = imageView.layer layer.masksToBounds = true layer.cornerRadius = imageView.frame.width / 2 UIGraphicsBeginImageContext(imageView.bounds.size) layer.render(in: UIGraphicsGetCurrentContext()!) let roundedImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return roundedImage! } } //Usage let roundedImage = image.roundedImage()