如何正确添加图片遮罩?Swift添加图片光效时遮罩仅显白色如何解决
问题原因
遮罩区域显示为白色主要由两点导致:
CGImage初始化遮罩对输入的遮罩图片有严格格式要求,必须为无alpha通道的灰度图,普通彩色、带alpha通道的图片直接传入会导致遮罩计算异常,出现全白显示- 直接对原图做遮罩时,遮罩后透明的区域会显示底层视图的白色背景,不符合添加光效的需求逻辑
解决步骤
1. 预处理遮罩图片为符合要求的灰度图
添加灰度转换方法,将输入的遮罩图转换为符合CGImage要求的格式:
func convertToGrayscaleMask(image: UIImage) -> UIImage? { let size = image.size let graySpace = CGColorSpaceCreateDeviceGray() guard let context = CGContext(data: nil, width: Int(size.width), height: Int(size.height), bitsPerComponent: 8, bytesPerRow: 0, space: graySpace, bitmapInfo: CGImageAlphaInfo.none.rawValue) else { return nil } context.draw(image.cgImage!, in: CGRect(origin: .zero, size: size)) guard let grayCGImage = context.makeImage() else { return nil } return UIImage(cgImage: grayCGImage, scale: image.scale, orientation: image.imageOrientation) }
灰度遮罩的生效规则为:黑色区域对应上层素材完全保留,白色区域对应上层素材完全透明,中间灰度值对应半透明效果。
2. 修正原遮罩方法
原方法未处理UIImage的scale和方向属性,易出现遮罩错位、变形问题,修正后代码:
func maskImage(image: UIImage, mask: UIImage) -> UIImage? { guard let grayMask = convertToGrayscaleMask(image: mask), let maskCGImage = grayMask.cgImage, let sourceCGImage = image.cgImage else { return nil } guard let imageMask = CGImage(maskWidth: maskCGImage.width, height: maskCGImage.height, bitsPerComponent: maskCGImage.bitsPerComponent, bitsPerPixel: maskCGImage.bitsPerPixel, bytesPerRow: maskCGImage.bytesPerRow, provider: maskCGImage.dataProvider!, decode: nil, shouldInterpolate: true) else { return nil } guard let maskedCGImage = sourceCGImage.masking(imageMask) else { return nil } return UIImage(cgImage: maskedCGImage, scale: image.scale, orientation: image.imageOrientation) }
3. 调整光效实现逻辑
如果你的需求是在指定区域添加光效,不要直接对原图做遮罩,按以下步骤实现:
- 准备好光效素材图(光晕、亮光类素材)
- 用你需要显示光效的区域作为遮罩,对光效素材图执行遮罩处理
- 将处理后的光效图叠加在原图上方,根据需要调整透明度和图层混合模式,即可得到自然的光效效果
内容的提问来源于stack exchange,提问作者Kamlesh Shingarakhiya
相关产品推荐
相关产品推荐

