Ios 将图像剪成圆形

Ios 将图像剪成圆形,ios,swift,uiimage,Ios,Swift,Uiimage,我想把一个UIImage切成一个圆,这样我就可以把它用作注释了。我在这个网站上找到的每一个答案都描述了创建一个UIImageView,然后修改并显示它,但是你不能将注释的图像设置为UIImageView,只有UIImage。 我应该怎么做?如果需要,请确保导入QuarzCore func maskRoundedImage(image: UIImage, radius: CGFloat) -> UIImage { let imageView: UIImageView = U

我想把一个
UIImage
切成一个圆,这样我就可以把它用作注释了。我在这个网站上找到的每一个答案都描述了创建一个
UIImageView
,然后修改并显示它,但是你不能将注释的图像设置为
UIImageView
,只有
UIImage

我应该怎么做?

如果需要,请确保导入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!
    }

我设法通过使用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
}

Xcode 11•Swift 5.1或更高版本

编辑/更新:对于iOS10+,我们可以使用UIGraphicsImageRenderer。对于较旧的Swift语法,请检查编辑历史记录

extension UIImage {
    var isPortrait:  Bool    { size.height > size.width }
    var isLandscape: Bool    { size.width > size.height }
    var breadth:     CGFloat { min(size.width, size.height) }
    var breadthSize: CGSize  { .init(width: breadth, height: breadth) }
    var breadthRect: CGRect  { .init(origin: .zero, size: breadthSize) }
    var circleMasked: UIImage? {
        guard let cgImage = cgImage?
            .cropping(to: .init(origin: .init(x: isLandscape ? ((size.width-size.height)/2).rounded(.down) : 0,
                                              y: isPortrait  ? ((size.height-size.width)/2).rounded(.down) : 0),
                                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: .init(origin: .zero, size: breadthSize))
        }
    }
}
操场测试

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

扩展UIImage{ func circularImage(大小:CGSize?->UIImage{ 让newSize=size×self.size 让minEdge=min(newSize.height,newSize.width) let size=CGSize(宽度:minEdge,高度:minEdge) UIGraphicsBeginImageContextWithOptions(大小,false,0.0) let context=UIGraphicsGetCurrentContext() self.drawInRect(CGRect(原点:CGPoint.zero,大小:size),blendMode:.Copy,alpha:1.0) CGContextSetBlendMode(上下文,.Copy) CGContextSetFillColorWithColor(上下文,UIColor.clearColor().CGColor) 设rectPath=UIBezierPath(rect:CGRect(原点:CGPoint.zero,大小:size)) 设circlePath=UIBezierPath(ovalInRect:CGRect(原点:CGPoint.zero,大小:size)) rectPath.appendPath(circlePath) rectPath.usesevenodfillrule=true rectPath.fill() 让结果=UIGraphicsGetImageFromCurrentImageContext() UIGraphicsSendImageContext() 返回结果 } } 用法:

UIImageView:

@IBDesignable类CircularImageView:UIImageView{
覆盖变量映像:UIImage{
迪塞特{
super.image=图像?.circularImage(大小:零)
}
}
}
UI按钮:

@IBDesignable class CircularImageButton:UIButton{
覆盖func setImage(图像:UIImage?,用于状态:uicontrol状态){
设circularImage=图像?.circularImage(大小:零)
super.setImage(circularImage,forState:state)
}
}

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
}

您可以使用此代码来圈出图像

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符合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中调用类

根据需要设置拐角半径(如果需要圆形,则为宽度的1/2)


完成了

对于一个直接的解决方案来说,所有这些答案都非常复杂。我只是复制了我的Objective-C代码,并根据Swift进行了调整

self.myImageView?.layer.cornerRadius = (self.myImageView?.frame.size.width)! / 2;
self.myImageView?.clipsToBounds = true
根据尼科斯的回答:

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

我使用的是RoundedImageView类,面临的问题是,当从gallery浏览图像时,图像不会以圆形或圆形显示。。我只需更改UIImageView/RoundedImageView->view->Content Mode->Aspect Fill的属性即可

Swift 5.3、Xcode 12.2处理所有图像方向 根据答案

谢谢,很好用!但仅适用于具有imageOrientation.up或.down的图像。对于具有.right或.left方向的图像,结果中存在失真。最初我们通过iPhone/iPad相机拍摄原始照片,获得了正确的方位

下面的代码考虑了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))
        }
    }
}


好吧,我想会的,我只是检查了一下,我已经导入了QuartzCore和所有东西,但没有环绕图像。你能检查一下它是否适用于你吗?是的,我在一个操场上检查过。如果你看到别名图像,请使用
UIGraphicsBeginImageContextWithOptions(imageView.bounds.size,false,UIScreen.mainScreen().scale)
。非常感谢!简单实用的答案!我认为这个代码太复杂了。您可以使用剪切路径直接渲染到图像上下文中,而不是创建未使用的图像视图。太棒了!我已经在这上面呆了一段时间了,谢谢!谢谢圈。你是上帝。@b卡特尔他的方法会扭曲不真实的形象squared@LeoDabus我忘了送赏金了,赏金马上就到。顺便说一句,你的经典答案在这里非常有用:@Fattie Yes Geddy Lee本人:我在寻找将图像裁剪成圆形的代码,我发现这个答案是最好的!,但是有一个问题,图像是反转的,如何修复?你能帮忙吗?嗨@Salah,很抱歉,我以前的方法有一些问题。我已经在我的代码中修复了这个问题,你可以试试!但是,虽然我必须编写
圈(:)
方法,但我很少使用它。大多数情况下,
resize
+`fill(with:)`方法将帮助我控制我的资产图像,我向您推荐
Kingfisher
,他必须提供`roundcorneimageprocessor`此类来执行图像裁剪功能。你可以在这里看到(.@Salah我写了一篇英语来展示我所有的图像助手。我非常欢迎你学习iOS开发。你可以在gist.github.com/YueJun1991/867f667f5a14eb65deaacf9db2120481中看到这一点。非常感谢你!我很感激这真的很有帮助,我使用了你的新图片,并用圆圈圈出,但图片仍然颠倒了。它看起来像这样:为什么会发生这种情况g?我无法修复它。我需要使用
contentMode=.scaleAspectFit
为UIImageView设置圆形图像。这个答案非常有效。如果有很多这样的项目,使用层角半径可能会导致掉帧/性能问题。这就是为什么会有更复杂的替代解决方案