Swift - 直接改内存实现图片圆角

参考自文章://www.greatytc.com/p/bbb50b2cb7e6
以下是关键方法的Swift写法。

func dealImage(_ img: UIImage, cornerRadius c: CGFloat) -> UIImage? {
    
    guard
        let sourceData = img.cgImage?.dataProvider?.data,
        let mutableSourceData = CFDataCreateMutableCopy(kCFAllocatorDefault, CFDataGetLength(sourceData), sourceData),
        let mutablePointer = CFDataGetMutableBytePtr(mutableSourceData)
    else { return nil }
    
    let width = Int(img.size.width * img.scale)
    let height = Int(img.size.height * img.scale)

    cornerImage(at: mutablePointer, w: width, h: height, cornerRadius: c)
    
    guard let pv = CGDataProvider(dataInfo: nil,
                                  data: UnsafeRawPointer(mutablePointer),
                                  size: width * height * 4,
                                  releaseData: { (info, data, size) in
                                    free(UnsafeMutableRawPointer(mutating: data))
    }) else { return nil }
    
    let alphaPremultipliedLast = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)
    
    guard let content = CGImage(
        width: width,
        height: height,
        bitsPerComponent: 8,
        bitsPerPixel: 32,
        bytesPerRow: 4 * width,
        space: CGColorSpaceCreateDeviceRGB(),
        bitmapInfo: [.byteOrder32Big, alphaPremultipliedLast],
        provider: pv,
        decode: nil,
        shouldInterpolate: true,
        intent: .defaultIntent) else { return nil }
    let result = UIImage(cgImage: content)
    return result
}

func cornerImage(at pointer: UnsafeMutablePointer<UInt8>, w: Int, h: Int, cornerRadius: CGFloat) {
    let min = CGFloat(w > h ? h : w)
    let c: Int = {
        var c = cornerRadius
        if c < 0 { c = 0 }
        if c > min * 0.5 { c = 0.5 }
        return Int(c)
    }()
    
    let pixelPointer = unsafeBitCast(pointer, to: UnsafeMutablePointer<UInt32>.self)
    
    // 左上 y:[0, c), x:[0, c-y)
    for y in 0 ..< c {
        for x in 0 ..< c - y {
            if outsideCircle(cx: c, cy: c, r: c, px: x, py: y) {
                pixelPointer[y * w + x] = 0
            }
        }
    }
    
    // 右上
    for y in 0 ..< c {
        for x in w - c - y ..< w {
            if outsideCircle(cx: w - c, cy: c, r: c, px: x, py: y) {
                pixelPointer[y * w + x] = 0
            }
        }
    }
    
    // 左下
    for y in h - c ..< h {
        for x in 0 ..< y - (h - c) {
            if outsideCircle(cx: c, cy: h - c, r: c, px: x, py: y) {
                pixelPointer[y * w + x] = 0
            }
        }
    }
    
    // 右下
    for y in h - c ..< h {
        for x in w - c + (h - y) ..< w {
            if outsideCircle(cx: w - c, cy: h - c, r: c, px: x, py: y) {
                pixelPointer[y * w + x] = 0
            }
        }
    }
}

func outsideCircle(cx: Int, cy: Int, r: Int, px: Int, py: Int) -> Bool {
    return (cx - px) * (cx - px) + (cy - py) * (cy - py) > r * r
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 173,596评论 25 708
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,259评论 4 61
  • 只是跟他呆在一起的时候很开心,很自在,也不会计较什么。 只是我有男朋友,他有喜欢的人。 他觉得我很傻,我也认为他二...
    王晓晓DE小屋阅读 186评论 0 0
  • 10点起床,打开邮箱发现铲子骑士打折了,立即购买。玩了一小时继续看python的函数式编程。 1点和脏好人去吃午饭...
    AJI米阅读 175评论 0 0
  • 一,.为自己开设的店铺里的某款具体产品,按照花卷app产品推介6模块进行描述(建议下载app或登录职教云app查看...
    68b183b38b2b阅读 374评论 0 0