Swift:如何为PNG图片修改色调同时保留透明背景?
解决PNG图片添加色调同时保留透明背景的问题
当然有办法解决这个问题!你的代码里透明背景变黑的核心原因,是开头强制绘制了黑色背景——这一步直接覆盖了原本的透明区域。我们可以调整绘制逻辑和混合模式,在保留透明背景的同时,完美保留阴影这类半透明细节,还能实现色调添加的效果。
下面是修改后的完整代码:
extension UIImage { public func tintImage(with fillColor: UIColor) -> UIImage { return modifiedImage { context, rect in // 先绘制原始图片,完整保留alpha通道信息 context.setBlendMode(.normal) context.draw(self.cgImage!, in: rect) // 用multiply混合模式叠加色调,既保留原始亮度和半透明细节,又不破坏透明背景 context.setBlendMode(.multiply) fillColor.setFill() context.fill(rect) // 最后用原始图片的alpha通道做遮罩,确保完全透明的区域不受色调影响 context.setBlendMode(.destinationIn) context.draw(self.cgImage!, in: rect) } } fileprivate func modifiedImage(_ draw: (CGContext, CGRect) -> ()) -> UIImage { UIGraphicsBeginImageContextWithOptions(size, false, scale) guard let context = UIGraphicsGetCurrentContext() else { return self } // 正确处理Retina图片的旋转问题 context.translateBy(x: 0, y: size.height) context.scaleBy(x: 1.0, y: -1.0) let rect = CGRect(origin: .zero, size: size) draw(context, rect) let image = UIGraphicsGetImageFromCurrentImageContext() ?? self UIGraphicsEndImageContext() return image } }
关键改动说明:
- 移除黑色背景绘制:这是解决透明区域变黑的核心操作,不再强制填充黑色背景,让原始透明区域得以保留。
- 调整混合模式:使用
.multiply混合模式叠加色调,既能保留原始图片的亮度层次和半透明阴影细节,又不会对完全透明的区域产生影响。 - 添加alpha遮罩步骤:最后用
.destinationIn混合模式重绘原始图片,确保只有原始图片存在像素的区域才会被色调覆盖,完全透明的区域保持纯净透明。
如果你想要更贴近原代码中“保留原始亮度”的效果(类似.color混合模式的表现),只需要把混合模式换成.color即可,其他逻辑不变:
// 替换色调叠加的代码块 context.setBlendMode(.color) fillColor.setFill() context.fill(rect) context.setBlendMode(.destinationIn) context.draw(self.cgImage!, in: rect)
这样既保留了原始图片的亮度信息,又能完美保留透明背景和半透明细节。
内容的提问来源于stack exchange,提问作者Soufian Hossam
相关产品推荐
相关产品推荐

