mrwalker provided a great answer that I converted to Swift.
Swift 5
let sourceImage: CIImage = ...
// This is where I get the overlayImage, and intensity is alpha, used later
guard let ciFilter = LUTBuilder.getCIFilter(from: filter.filter), let intensity = filter.intensity else { return CIImage() }
ciFilter.setValue(sourceImage.clampedToExtent(), forKey: kCIInputImageKey)
let overlayImage = ciFilter.outputImage!.cropped(to: sourceImage.extent)
let alpha = CGFloat(intensity)
let rgba = [0.0, 0.0, 0.0, alpha]
guard
let colorMatrix = CIFilter(name: "CIColorMatrix"),
let composite = CIFilter(name: "CISourceOverCompositing")
else { return CIImage() }
colorMatrix.setDefaults()
colorMatrix.setValue(overlayImage, forKey: kCIInputImageKey)
colorMatrix.setValue(CIVector(values: rgba, count: 4), forKey: "inputAVector")
composite.setDefaults()
composite.setValue(colorMatrix.outputImage, forKey: kCIInputImageKey)
composite.setValue(sourceImage, forKey: kCIInputBackgroundImageKey)
return composite.outputImage ?? CIImage()