ios 舍入 UIImage 并添加边框

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34984966/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 08:38:19  来源:igfitidea点击:

Rounding UIImage and adding a border

iosswiftuiimageuigraphicscontext

提问by Olexiy Burov

so I want to show some pictures as annotations on the map. In order to do that I need to add the image property of the MKAnnotationView. I'm using the regular images but I want them to be rounded and with a border. So I found a way to round UIImage and I found the way to add a border to UIImage, but border doesn't seem to add (I'm not actually having the image on the screen, maybe that is the problem?).

所以我想在地图上显示一些图片作为注释。为此,我需要添加 MKAnnotationView 的图像属性。我正在使用常规图像,但我希望它们是圆形的并带有边框。所以我找到了一种绕过 UIImage 的方法,我找到了向 UIImage 添加边框的方法,但边框似乎没有添加(我实际上没有在屏幕上显示图像,也许这就是问题所在?)。

I used this answer https://stackoverflow.com/a/29047372/4665643with a slight modification for border. Namely:

我使用了这个答案https://stackoverflow.com/a/29047372/4665643对边框稍作修改。即:

imageView.layer.borderWidth = 1.5
imageView.layer.borderColor = UIColor.whiteColor().CGColor
imageView.clipsToBounds = true

But my image on the map doesn't have any border. Any suggestions ?

但是我在地图上的图像没有任何边框。有什么建议 ?

回答by keval

imageView.layer.masksToBounds = true
imageView.layer.borderWidth = 1.5
imageView.layer.borderColor = UIColor.white.cgColor
imageView.layer.cornerRadius = imageView.bounds.width / 2

Try this.

尝试这个。

回答by Leo Dabus

If you would like to add a border to your image you need to make sure you add some extra room to it otherwise your border will be placed in top of your image. The solution is to add twice the width of your stroke to your image's width and height.

如果您想为图像添加边框,您需要确保为其添加一些额外的空间,否则您的边框将放置在图像的顶部。解决方案是将笔画宽度的两倍添加到图像的宽度和高度。

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) }
    func rounded(with color: UIColor, width: CGFloat) -> UIImage? {
        let bleed = breadthRect.insetBy(dx: -width, dy: -width)
        UIGraphicsBeginImageContextWithOptions(bleed.size, false, scale)
        defer { UIGraphicsEndImageContext() }
        guard let cgImage = cgImage?.cropping(to: CGRect(origin: CGPoint(
            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 }
        UIBezierPath(ovalIn: .init(origin: .zero, size: bleed.size)).addClip()
        var strokeRect =  breadthRect.insetBy(dx: -width/2, dy: -width/2)
        strokeRect.origin = .init(x: width/2, y: width/2)
        UIImage(cgImage: cgImage, scale: 1, orientation: imageOrientation)
            .draw(in: strokeRect.insetBy(dx: width/2, dy: width/2))
        color.set()
        let line: UIBezierPath = .init(ovalIn: strokeRect)
        line.lineWidth = width
        line.stroke()
        return UIGraphicsGetImageFromCurrentImageContext()
    }
}


For iOS10+ We can use UIGraphicsImageRenderer.

对于 iOS10+ 我们可以使用 UIGraphicsImageRenderer。

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) }
    func rounded(with color: UIColor, width: CGFloat) -> UIImage? {

        guard let cgImage = cgImage?.cropping(to: .init(origin: .init(x: isLandscape ? ((size.width-size.height)/2).rounded(.down) : .zero, y: isPortrait ? ((size.height-size.width)/2).rounded(.down) : .zero), size: breadthSize)) else { return nil }

        let bleed = breadthRect.insetBy(dx: -width, dy: -width)
        let format = imageRendererFormat
        format.opaque = false

        return UIGraphicsImageRenderer(size: bleed.size, format: format).image { context in
            UIBezierPath(ovalIn: .init(origin: .zero, size: bleed.size)).addClip()
            var strokeRect =  breadthRect.insetBy(dx: -width/2, dy: -width/2)
            strokeRect.origin = .init(x: width/2, y: width/2)
            UIImage(cgImage: cgImage, scale: 1, orientation: imageOrientation)
            .draw(in: strokeRect.insetBy(dx: width/2, dy: width/2))
            context.cgContext.setStrokeColor(color.cgColor)
            let line: UIBezierPath = .init(ovalIn: strokeRect)
            line.lineWidth = width
            line.stroke()
        }
    }
}

Playground Testing:

游乐场测试:

let profilePicture = UIImage(data: try! Data(contentsOf: URL(string:"http://i.stack.imgur.com/Xs4RX.jpg")!))!
let pp = profilePicture.rounded(with: .red, width: 10)

回答by Arun Ammannaya

Use this extension to UIImageView :

将此扩展用于 UIImageView :

func cropAsCircleWithBorder(borderColor : UIColor, strokeWidth: CGFloat)
{
    var radius = min(self.bounds.width, self.bounds.height)
    var drawingRect : CGRect = self.bounds
    drawingRect.size.width = radius
    drawingRect.origin.x = (self.bounds.size.width - radius) / 2
    drawingRect.size.height = radius
    drawingRect.origin.y = (self.bounds.size.height - radius) / 2

    radius /= 2

    var path = UIBezierPath(roundedRect: CGRectInset(drawingRect, strokeWidth/2, strokeWidth/2), cornerRadius: radius)
    let border = CAShapeLayer()
    border.fillColor = UIColor.clearColor().CGColor
    border.path = path.CGPath
    border.strokeColor = borderColor.CGColor
    border.lineWidth = strokeWidth
    self.layer.addSublayer(border)

    path = UIBezierPath(roundedRect: drawingRect, cornerRadius: radius)
    let mask = CAShapeLayer()
    mask.path = path.CGPath
    self.layer.mask = mask
}

Usage :

用法 :

        self.circleView.cropAsCircleWithBorder(UIColor.redColor(), strokeWidth: 20)

Result :

结果 :

Result

结果

回答by Rajat

For making an image rounded with border, you can do that from User Defined Runtime Attributes also, no need to write code for that.

要制作带有边框的圆形图像,您也可以从用户定义的运行时属性中执行此操作,无需为此编写代码。

Please check the below image for setting that

请检查下图进行设置

enter image description here

在此处输入图片说明

Also in your code, change

同样在您的代码中,更改

imageView.layer.clipsToBounds = true

to this,

对此,

imageView.layer.masksToBounds = true

回答by coldembrace

Leo Dabus's solution in Swift 3:

Leo Dabus在 Swift 3 中的解决方案:

extension UIImage {
    func roundedImageWithBorder(width: CGFloat, color: UIColor) -> UIImage? {
        let square = CGSize(width: min(size.width, size.height) + width * 2, height: min(size.width, size.height) + width * 2)
        let imageView = UIImageView(frame: CGRect(origin: CGPoint(x: 0, y: 0), size: square))
        imageView.contentMode = .center
        imageView.image = self
        imageView.layer.cornerRadius = square.width/2
        imageView.layer.masksToBounds = true
        imageView.layer.borderWidth = width
        imageView.layer.borderColor = color.cgColor
        UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, false, scale)
        guard let context = UIGraphicsGetCurrentContext() else { return nil }
        imageView.layer.render(in: context)
        let result = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return result
    }
}

回答by Anand

simple one line code its works for me

简单的一行代码对我有用

self.profileImage.layer.cornerRadius = self.profileImage.frame.size.width / 2

回答by u5835239

Supportive image added

添加了支持图片

I set masksToBounds, and It work.

我设置了masksToBounds,它起作用了。

layer.masksToBounds = true

回答by Olexiy Burov

Just fixed it. Apparently everything was working perfectly but I wasn't seeing the border. The original image is about 300x300 pixels and with 1.5 pixel border I was cropping it to fit 40x40 frame so the border was barely noticeable. Changing border width to a bigger number made it visible.

刚修好。显然一切正常,但我没有看到边界。原始图像约为 300x300 像素,边框为 1.5 像素,我将其裁剪为适合 40x40 帧,因此边框几乎不明显。将边框宽度更改为更大的数字使其可见。