onevcat / Kingfisher

A lightweight, pure-Swift library for downloading and caching images from the web.
MIT License
23.4k stars 2.66k forks source link

Gradient CImageProcessor #585

Closed pballada closed 7 years ago

pballada commented 7 years ago

Hi, I'm trying to create a gradient generator, using CIImage Filters. I'm using the CIImageProcessor processor wrapper, but I didn't find how can I pass some parameters like the gradient colors and positions.

The code for achieving gradients is like this.

`struct GradientFilter: CIImageProcessor {

let identifier = "com.domain.CILinearGradient"

let filter = Filter { input in

    guard let colorFilter = CIFilter(name: "CILinearGradient") else { return nil }

    let startColor = CIColor(cgColor: UIColor.redColor.cgColor)
    var endColor = CIColor(cgColor: UIColor.clear.cgColor)
    var startVector = CIVector(x: 0, y: 0)
    var endVector = CIVector(x: input.extent.size.width, y: 100)

    colorFilter.setValue(startVector, forKey: "inputPoint0")
    colorFilter.setValue(endVector, forKey: "inputPoint1")
    colorFilter.setValue(startColor, forKey: "inputColor0")
    colorFilter.setValue(endColor, forKey: "inputColor1")

    let colorImage = colorFilter.outputImage
    let filter = CIFilter(name: "CISourceOverCompositing")!
    filter.setValue(colorImage, forKey: kCIInputImageKey)
    filter.setValue(input, forKey: kCIInputBackgroundImageKey)
    return filter.outputImage?.cropping(to: input.extent)

}

}`

I'm calling it like this. processor = GradientFilter()

But I would like adding some parameters. processor = GradientFilter(startColor: .red, endColor: .blue, startPosition: CGPoint(x:0,y:0), endPosition: CGPoint(x:0,y:1))

Thanks so much

onevcat commented 7 years ago

Maybe you mean something like this?

struct GradientFilter: CIImageProcessor {

    let startColor: UIColor
    let endColor: UIColor

    let startVector: CIVector
    let endVector: CIVector

    var identifier: String {
        return "com.domain.CILinearGradient_#{startcolor}_#{endcolor}_#{startvector}_#{endvector}"
    }

    var filter: Filter {
        return Filter {
            input in
            guard let colorFilter = CIFilter(name: "CILinearGradient") else { return nil }

            let startColor = CIColor(cgColor: self.startColor.cgColor)
            let endColor = CIColor(cgColor: self.endColor.cgColor)

            colorFilter.setValue(self.startVector, forKey: "inputPoint0")
            colorFilter.setValue(self.endVector, forKey: "inputPoint1")
            colorFilter.setValue(startColor, forKey: "inputColor0")
            colorFilter.setValue(endColor, forKey: "inputColor1")

            let colorImage = colorFilter.outputImage
            let filter = CIFilter(name: "CISourceOverCompositing")!
            filter.setValue(colorImage, forKey: kCIInputImageKey)
            filter.setValue(input, forKey: kCIInputBackgroundImageKey)
            return filter.outputImage?.cropping(to: input.extent)
        }
    }
}

Please note that the identifier property should be identical, which says, for every combination of the startColor, endColor, startVector and endVector, the identifier should be different. Or Kingfisher will be confused when retrieving the images from cache.

pballada commented 7 years ago

Wow, that was it!!

thanks so much.