简体   繁体   中英

Which CIFilter can add a color layer to image

For example:

This is original image

在此处输入图片说明

This is 50% alpha color layer

在此处输入图片说明

Combine two images can get the result

在此处输入图片说明

Which CIFilter can do this task?


update:

I found a CIColorCube example here.

https://github.com/rnsm504/CIColorCube/blob/master/CIColorCubeSample/ViewController.swift

I use this example to write my color filter

var hue : Float = 0.1
func RGBtoHSV(_ r : Float, g : Float, b : Float) -> (h : Float, s : Float, v : Float) {
    var h : CGFloat = 0
    var s : CGFloat = 0
    var v : CGFloat = 0
    let col = UIColor(red: CGFloat(r), green: CGFloat(g), blue: CGFloat(b), alpha: 1.0)
    col.getHue(&h, saturation: &s, brightness: &v, alpha: nil)
    return (Float(h), Float(s), Float(v))
}

func HSVtoRGB(_ h : Float, s : Float, v : Float) -> (r : Float, g : Float, b : Float) {
    var r : Float = 128
    var g : Float = 0
    var b : Float = 0
    let C = s * v
    let HS = h * 6.0
    let X = C * (1.0 - fabsf(fmodf(HS, 2.0) - 1.0))
    if (HS >= 0 && HS < 1) {
        r = C
        g = X
        b = 0
    } else if (HS >= 1 && HS < 2) {
        r = X
        g = C
        b = 0
    } else if (HS >= 2 && HS < 3) {
        r = 0
        g = C
        b = X
    } else if (HS >= 3 && HS < 4) {
        r = 0
        g = X
        b = C
    } else if (HS >= 4 && HS < 5) {
        r = X
        g = 0
        b = C
    } else if (HS >= 5 && HS < 6) {
        r = C
        g = 0
        b = X
    }
    let m = v - C
    r += m
    g += m
    b += m
    return (r, g, b)
}

func filter() -> CIFilter {

    let size = 64
    let defaultHue: Float = 0 //default color of blue truck
    let hueRange: Float = 60 //hue angle that we want to replace

    let centerHueAngle: Float = defaultHue/360.0
    var destCenterHueAngle: Float = hue
    let minHueAngle: Float = (defaultHue - hueRange/2.0) / 360
    let maxHueAngle: Float = (defaultHue + hueRange/2.0) / 360
    let hueAdjustment = centerHueAngle - destCenterHueAngle
    if destCenterHueAngle == 0  {
        destCenterHueAngle = 1 //force red if slider angle is 0
    }

    var cubeData = [Float](repeating: 0, count: (size * size * size * 4))
    var offset = 0
    var x : Float = 0, y : Float = 0, z : Float = 0, a :Float = 1.0

    for b in 0..<size {
        x = Float(b)/Float(size)
        for g in 0..<size {
            y = Float(g)/Float(size)
            for r in 0..<size {
                z = Float(r)/Float(size)
                var hsv = RGBtoHSV(z, g: y, b: x)

                if (hsv.h > minHueAngle && hsv.h < maxHueAngle) {
                    hsv.h = destCenterHueAngle == 1 ? 0 : hsv.h - hueAdjustment //force red if slider angle is 360
                    let newRgb = HSVtoRGB(hsv.h, s:hsv.s, v:hsv.v)

                    cubeData[offset] = newRgb.r
                    cubeData[offset+1] = newRgb.g
                    cubeData[offset+2] = newRgb.b
                } else {
                    cubeData[offset] = z
                    cubeData[offset+1] = y
                    cubeData[offset+2] = x
                }
                cubeData[offset+3] =  a
                offset += 4
            }
        }
    }

    let b = cubeData.withUnsafeBufferPointer{ Data(buffer:$0) }
    let data = b as NSData
    let colorCube = CIFilter(name: "CIColorCube", withInputParameters: ["inputCubeDimension": size, "inputCubeData" : data])
    return colorCube!
}

The difference is here, I add more red in filter

var r : Float = 128

And this is how I use the filter, but this filter remove all red color in image, which is the right variable I should change to add more red color?

@IBOutlet weak var inputImg: UIImageView!
@IBOutlet weak var outputImg: UIImageView!



@IBAction func clickButton(_ sender: Any) {
    let img = inputImg.image
    outputImg.image = img


    addColor(img: &outputImg.image!)

}


func addColor(img : inout UIImage){
    let beginImage = CIImage(image: img)
    let cifilter = filter()
    cifilter.setValue(beginImage, forKey: kCIInputImageKey)

    var ciimg = cifilter.outputImage
    let context:CIContext = CIContext.init(options: nil)
    let cgImage:CGImage = context.createCGImage(ciimg!, from: ciimg!.extent)!
    let newImage = UIImage(cgImage: cgImage)
    img = newImage
}

Update 2

Finally I found the answer

I should use CIConstantColorGenerator and CISourceOverCompositing

CIColorCube will replace the color

Here is the correct implementation of color filter

func createOverlay() -> CIImage {
    let overlayColor = UIColor.red.withAlphaComponent(0.5)
    let c = CIColor(color: overlayColor)
    let parameters = [kCIInputColorKey: c]
    guard let filter = CIFilter(name: "CIConstantColorGenerator", withInputParameters: parameters) else {
        fatalError()
    }
    guard let overlay = filter.outputImage else { fatalError() }
    return overlay
}

func compositeSourceOver(img: CIImage, overlay:CIImage) -> CIImage {

    let parameters = [
        kCIInputBackgroundImageKey: img,
        kCIInputImageKey: overlay
    ]
    guard let filter = CIFilter(name: "CISourceOverCompositing", withInputParameters: parameters) else {
        fatalError()
    }
    guard let outputImage = filter.outputImage else { fatalError() }
    let cropRect = img.extent
    return outputImage.cropped(to: cropRect)
}

Apply CIColorCube filter.

The result from docs looks similar.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM