web-dev-qa-db-fra.com

Couper un UIImage en cercle

Je veux couper une UIImage dans un cercle afin de pouvoir ensuite l'utiliser comme une annotation. Chaque réponse trouvée sur ce site décrit la création d'une UIImageView, sa modification et son affichage, mais vous ne pouvez pas définir l'image d'une annotation comme une UIImageView, uniquement une UIImage. Comment dois-je procéder?

29
Learnin

Assurez-vous d'importer QuarzCore si nécessaire.

 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!
    }
32
Nikos M.

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

Test de terrain de jeu

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

75
Leo Dabus

Extension UIImage:

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
    }

}

Utilisation:

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

}
9
Dmitry Coolerov

Basé sur la réponse 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()
2
Bas

Toutes ces réponses étaient vraiment complexes pour une solution simple. Je viens de reproduire mon code Objective-C et de l'ajuster à Swift.

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

Xcode 8.1, Swift 3.0.1

Mon code ressemblera à ceci:

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

Ajoutez une extension UIImage, puis:

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
}
1
Arco

J'ai réussi à répondre à ma propre question en trouvant une utilisation 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
}
1
Learnin

Vous pouvez utiliser ce code pour entourer l'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
    }
}}
0
Youssef

Swift 3 conforme au modèle MVC Créer un fichier externe

@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

classe d'appel à l'IB sur le scénarimage

 call class in the IB on storyboard

réglez cornerradius à votre guise (1/2 de la largeur si vous désirez cercle)

 set attribute

Terminé!

0
alpha911