参考自文章:http://www.jianshu.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
}