在UIImage上绘制具有核心图形的渐变结果不一致

时间:2015-02-07 04:31:12

标签: ios swift uikit

目标

我试图在图像上绘制线性渐变。

设置

我有一个函数调用imageWithGradient,它使用颜色和imageView来放置带有渐变的图像。我使用storyboard将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()
}

结果

Gradient Flipped Gradient doesn't appear on the right I changed the color and add another imageView with this one

1 个答案:

答案 0 :(得分:3)

你实际上是在传递一个未初始化的内存块用于颜色组件。

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)