func getDetailedNonTransparentPath(from image: UIImage, tolerance: UInt8 = 0) -> UIBezierPath? {
guard let cgImage = image.cgImage else { return nil }
let width = cgImage.width
let height = cgImage.height
let colorSpace = CGColorSpaceCreateDeviceRGB()
let bytesPerPixel = 4
let bytesPerRow = bytesPerPixel * width
let bitsPerComponent = 8
let pixelData = UnsafeMutablePointer<UInt8>.allocate(capacity: bytesPerRow * height)
defer {
pixelData.deallocate()
}
guard let context = CGContext(
data: pixelData,
width: width,
height: height,
bitsPerComponent: bitsPerComponent,
bytesPerRow: bytesPerRow,
space: colorSpace,
bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue
) else { return nil }
context.draw(cgImage, in: CGRect(x: 0, y: 0, width: width, height: height))
let path = UIBezierPath()
// 查找所有非透明像素并构建路径
for y in 0..<height {
var insideOpaqueRegion = false
var startX = 0
for x in 0..<width {
let offset = 4 * (y * width + x)
let alpha = pixelData[offset + 3]
let isOpaque = alpha > tolerance
if isOpaque && !insideOpaqueRegion {
// 进入非透明区域
insideOpaqueRegion = true
startX = x
} else if !isOpaque && insideOpaqueRegion {
// 离开非透明区域,添加这一段线
path.move(to: CGPoint(x: startX, y: y))
path.addLine(to: CGPoint(x: x, y: y))
insideOpaqueRegion = false
}
}
// 如果一行结束时仍在非透明区域内
if insideOpaqueRegion {
path.move(to: CGPoint(x: startX, y: y))
path.addLine(to: CGPoint(x: width, y: y))
}
}
return path
}
///识别图片非透明内容,并修改它的颜色
extension UIImage {
func tintedImage(with color: UIColor) -> UIImage? {
guard let ciImage = CIImage(image: self) else { return nil }
// 创建颜色滤镜
let colorFilter = CIFilter(name: "CIConstantColorGenerator", parameters: [
kCIInputColorKey: CIColor(color: color)
])
// 创建混合滤镜
let blendFilter = CIFilter(name: "CIBlendWithAlphaMask")!
blendFilter.setValue(colorFilter?.outputImage, forKey: kCIInputImageKey)
blendFilter.setValue(ciImage, forKey: kCIInputBackgroundImageKey)
blendFilter.setValue(ciImage, forKey: "inputMaskImage")
guard let outputImage = blendFilter.outputImage,
let cgImage = CIContext().createCGImage(outputImage, from: outputImage.extent) else {
return nil
}
return UIImage(cgImage: cgImage)
}
}