在 UIImage 上使用 Core Graphic 绘制渐变结果不一致
Posted
技术标签:
【中文标题】在 UIImage 上使用 Core Graphic 绘制渐变结果不一致【英文标题】:Drawing Gradient with Core Graphic on UIImage result not consistent 【发布时间】:2015-02-07 04:31:11 【问题描述】:目标
我正在尝试在图像上绘制线性渐变。
设置
我有一个函数调用 imageWithGradient
,它使用颜色和 imageView 来放入带有渐变绘制的图像。我使用故事板将 imageView 添加到视图中。
问题
当我在模拟器上尝试代码时,有时不会出现渐变,有时不会出现 alpha(纯色),有时会翻转渐变。由于我使用相同颜色运行相同的代码,因此它应该对所有图像应用相同的渐变,但很少这样做。
override func viewDidLoad()
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var c1 = UIColor(red: 1.0, green: 0, blue: 0, alpha: 0.9).CGColor
var c2 = UIColor(red: 0, green: 0, blue: 0, alpha: 0).CGColor
imageWithGradient(self.imageView1, startColor: c1, endColor: c2)
imageWithGradient(self.imageView2, startColor: c1, endColor: c2)
func imageWithGradient(imgView:UIImageView, startColor: CGColor, endColor: CGColor)
var img = UIImage(named:"sample.jpg")!
UIGraphicsBeginImageContext(img.size)
var context = UIGraphicsGetCurrentContext()
img.drawAtPoint(CGPointMake(0, 0))
var colorSpace = CGColorSpaceCreateDeviceRGB()
var startColorComp = CGColorGetComponents(startColor)
var endColorComp = CGColorGetComponents(endColor)
var colorComps = [startColorComp[0], endColorComp[0]]
var locations:[CGFloat] = [0.0, 1.0]
var gradient = CGGradientCreateWithColorComponents(colorSpace, &colorComps, &locations, 2)
var startPoint = CGPointMake(img.size.width/2, img.size.height/2)
var endPoint = CGPointMake(img.size.width/2, img.size.height)
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0)
imgView.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
结果
【问题讨论】:
【参考方案1】:您实际上是在为颜色组件传递一个未初始化的内存块。
var colorComps = [startColorComp[0], endColorComp[0]]
创建一个由每种颜色的第一个组件组成的数组,因此 2 个组件(甚至不是您想要的组件)
进一步,您将 2 个元素的数组传递给:
let gradient = CGGradientCreateWithColorComponents(colorSpace, colorComps, locations, 2)
其中 colorComps 期望接收 8 个浮点数的数组,因此其他 6 个浮点数基本上是随机内存内容,因此结果差异很大。
您可以使用此函数将颜色分量提取到实际颜色分量的数组中。这会构建一个由 4 个颜色分量组成的快速数组(或者无论有多少,但应该是 4 个)
func CGColorComponents(color:CGColorRef) -> [CGFloat]
let count = CGColorGetNumberOfComponents(color)
var comps = CGColorGetComponents(color)
var array = [CGFloat]()
for i in 0 ..< count
array.append(comps.memory)
comps = comps.successor()
return array
您可以使用以下方法构建适当的组件数组:
let startColorComp = CGColorComponents(startColor)
let endColorComp = CGColorComponents(endColor)
let colorComps = startColorComp + endColorComp
把它们放在一起,你就可以创建一个函数来覆盖你的图像上的渐变:
func imageWithGradient(startColor: CGColor, endColor: CGColor) -> UIImage
var img = UIImage(named:"img_0002.png")!
UIGraphicsBeginImageContext(img.size)
var context = UIGraphicsGetCurrentContext()
img.drawAtPoint(CGPointMake(0, 0))
let colorSpace = CGColorSpaceCreateDeviceRGB()
let componentCount = CGColorSpaceGetNumberOfComponents(colorSpace)
let startColorComp = CGColorComponents(startColor)
let endColorComp = CGColorComponents(endColor)
let colorComps = startColorComp + endColorComp
let locations:[CGFloat] = [0.0, 1.0]
let gradient = CGGradientCreateWithColorComponents(colorSpace, colorComps, locations, 2)
let startPoint = CGPointMake(img.size.width/2, img.size.height/2)
let endPoint = CGPointMake(img.size.width/2, img.size.height)
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
不完全是你使用它的方式,但如果你真的想保持你的语义,你应该能够挖掘出功能。
更好的是,只需使用 CGGradientCreateWithColors
代替:
let gradient = CGGradientCreateWithColors(colorSpace, [startColor, endColor], locations)
【讨论】:
你的回答很清楚。非常感谢。我正在尝试在图像上覆盖一些文本,并将使用渐变为文本提供某种对比度,例如 Flipboard link。你认为这是一种有效的方法吗?因为我必须将此应用于从服务器获取的大量照片。以上是关于在 UIImage 上使用 Core Graphic 绘制渐变结果不一致的主要内容,如果未能解决你的问题,请参考以下文章
如何从 UIImage (Cocoa Touch) 或 CGImage (Core Graphics) 获取像素数据?
Core Data 不会从内存中释放 UIImage 数据 (ImageIO_PNG_Data)
如何在 Documents 文件夹中保存 UIImagePicker 中的 UIImage 并获取路径字符串以保存在 Swift 中的 Core Data 中