如何高效将UIImage所有像素修改为指定单一颜色?
嘿,逐像素遍历这种操作真的是效率杀手,尤其是碰到尺寸大一点的图片,卡顿感直接拉满!我给你分享几个iOS开发里常用的高效实现方式,既能快速把整个图片改成指定颜色,还能完美保留原图片的透明度:
方案1:Core Graphics 直接绘制(兼容性最好)
Core Graphics是iOS底层的图形渲染框架,硬件加速加持,性能比逐像素高几个量级。核心思路是先铺满指定颜色,再用混合模式保留原图片的透明度:
func image(withSolidColor color: UIColor, from image: UIImage) -> UIImage? { UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale) defer { UIGraphicsEndImageContext() } // 先填充指定颜色到整个画布 color.setFill() UIRectFill(CGRect(origin: .zero, size: image.size)) // 用.destinationIn混合模式绘制原图,只保留原图的透明度信息 image.draw(in: CGRect(origin: .zero, size: image.size), blendMode: .destinationIn, alpha: 1.0) return UIGraphicsGetImageFromCurrentImageContext() }
这个方法能完美适配所有iOS版本,而且处理速度极快,是最通用的方案。
方案2:Core Image 滤镜实现(适合滤镜链式处理)
如果你的场景需要和其他滤镜(比如模糊、裁剪)配合使用,Core Image的滤镜链会更灵活,同样是硬件加速:
func image(withSolidColor color: UIColor, from image: UIImage) -> UIImage? { guard let ciImage = CIImage(image: image) else { return nil } // 创建纯色生成滤镜 let colorGenerator = CIConstantColorGenerator() colorGenerator.color = CIColor(color: color) // 用混合滤镜将纯色与原图结合,保留原图透明度 let compositeFilter = CISourceInCompositing() compositeFilter.inputImage = colorGenerator.outputImage compositeFilter.backgroundImage = ciImage guard let outputCIImage = compositeFilter.outputImage else { return nil } // 转换为UIImage,注意复用CIContext以提升性能 let context = CIContext(options: [.useSoftwareRenderer: false]) guard let cgImage = context.createCGImage(outputCIImage, from: ciImage.extent) else { return nil } return UIImage(cgImage: cgImage, scale: image.scale, orientation: image.imageOrientation) }
注意:尽量全局复用同一个CIContext,避免重复创建带来的性能损耗。
方案3:UIGraphicsImageRenderer 简洁实现(iOS 10+ 推荐)
iOS 10之后推出的UIGraphicsImageRenderer封装了Core Graphics的上下文管理,代码更清爽,还自动适配屏幕缩放和 trait 环境:
func image(withSolidColor color: UIColor, from image: UIImage) -> UIImage? { let renderer = UIGraphicsImageRenderer(size: image.size, format: UIGraphicsImageRendererFormat(for: image.traitCollection)) return renderer.image { context in color.setFill() context.fill(CGRect(origin: .zero, size: image.size)) image.draw(in: CGRect(origin: .zero, size: image.size), blendMode: .destinationIn, alpha: 1.0) } }
这个方案代码最简洁,适合iOS 10及以上的新项目,维护成本极低。
这几个方法的性能都远高于逐像素遍历,尤其是处理大图的时候差距特别明显,你可以根据自己的项目版本和需求选合适的~
内容的提问来源于stack exchange,提问作者user9469498
相关产品推荐
相关产品推荐

