将UIImage切成圆形

时间:2015-03-14 07:29:17

标签: ios swift uiimage

我想将UIImage剪切成一个圆圈,以便我可以将其用作注释。我在本网站上发现的每个答案都描述了创建UIImageView,然后修改并显示它,但是您无法将注释的图像设置为UIImageView,只能{{1} }}。 我应该怎么做呢?

11 个答案:

答案 0 :(得分:76)

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

游乐场测试

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

答案 1 :(得分:34)

如果需要,请务必导入QuarzCore。

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

答案 2 :(得分:9)

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
    }

}

<强>用法:

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

}

答案 3 :(得分:2)

所有这些答案对于一个简单的解决方案来说确实很复杂。我刚刚复制了我的Objective-C代码并针对Swift进行了调整。

{{1}}

答案 4 :(得分:2)

基于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()

答案 5 :(得分:1)

我设法通过找到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
}

答案 6 :(得分:1)

Xcode 8.1,Swift 3.0.1

我的代码如下所示:

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

添加UIImage扩展,然后:

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
}

答案 7 :(得分:0)

您可以使用此代码圈出图片

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

答案 8 :(得分:0)

swift 3符合MVC模式 创建外部文件

@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

在故事板上的IB中调用类

call class in the IB on storyboard

随意设置cornerradius(宽度的1/2,如果需要圆圈)

set attribute

完成!

答案 9 :(得分:0)

我正在使用RoundedImageView类,面临的问题是,从图库浏览图像时,图像不能以圆形或圆形显示。我只需更改UIImageView / RoundedImageView->视图->内容模式->宽高比填充{ {3}}

答案 10 :(得分:0)

Swift 5.3,Xcode 12.2,处理所有imageOrientations

基于答案Leo Dabus

谢谢,效果很好!但仅适用于具有imageOrientation .up .down 的图像。对于具有 .right .left 方向的图像,结果会失真。从iPhone / iPad相机拍摄的原始照片开始,我们会得到 .right 方向。

下面的代码考虑了imageOrientation属性:

extension UIImage {

    func cropToCircle() -> UIImage? {
    
        let isLandscape = size.width > size.height
        let isUpOrDownImageOrientation = [0,1,4,5].contains(imageOrientation.rawValue)
    
        let breadth: CGFloat = min(size.width, size.height)
        let breadthSize = CGSize(width: breadth, height: breadth)
        let breadthRect = CGRect(origin: .zero, size: breadthSize)
    
        let xOriginPoint = CGFloat(isLandscape ?
                                (isUpOrDownImageOrientation ? ((size.width-size.height)/2).rounded(.down) : 0) :
                                (isUpOrDownImageOrientation ? 0 : ((size.height-size.width)/2).rounded(.down)))
        let yOriginPoint = CGFloat(isLandscape ?
                                (isUpOrDownImageOrientation ? 0 : ((size.width-size.height)/2).rounded(.down)) :
                                (isUpOrDownImageOrientation ? ((size.height-size.width)/2).rounded(.down) : 0))
    
        guard let cgImage = cgImage?.cropping(to: CGRect(origin: CGPoint(x: xOriginPoint, y: yOriginPoint),
                                                     size: breadthSize)) else { return nil }
        let format = imageRendererFormat
        format.opaque = false
    
        return UIGraphicsImageRenderer(size: breadthSize, format: format).image {_ in
            UIBezierPath(ovalIn: breadthRect).addClip()
            UIImage(cgImage: cgImage, scale: format.scale, orientation: imageOrientation).draw(in: CGRect(origin: .zero, size: breadthSize))
        }
    }
}