I am working on a Photo Filter App. I want to change Brightness and Contrast with a single slider. I can change them but when I jump to Contrast I loose Brightness changes. Wow can I keep the Brightness applied image and then continue with Contrast change.
if sender.tag == 0 {
self.coreImage = CIImage(image: (originalImage.image!))!
let filter2 = CIFilter(name: "CIColorControls" )
filter2!.setValue(coreImage, forKey: kCIInputImageKey)
filter2?.setValue(sender.value, forKey: kCIInputBrightnessKey)
brightnessValue = sender.value
filter2!.setValue(coreImage, forKey: kCIInputImageKey)
let filteredImageData2 = filter2!.value(forKey: kCIOutputImageKey) as! CIImage
let filteredImageRef = ciContext.createCGImage(filteredImageData2, from: filteredImageData2.extent)
let imageForButton = UIImage(cgImage: filteredImageRef!)
originalImage.isHidden = true
imageToFilter.image = imageForButton
}
else if sender.tag == 1 {
self.coreImage = CIImage(image: (originalImage.image!)) ?? CIImage()
let filter2 = CIFilter(name: "CIColorControls" )
filter2!.setValue(coreImage, forKey: kCIInputImageKey)
filter2?.setValue(sender.value, forKey: kCIInputContrastKey)
filter2!.setValue(coreImage, forKey: kCIInputImageKey)
let filteredImageData2 = filter2!.value(forKey: kCIOutputImageKey) as! CIImage
let filteredImageRef = ciContext.createCGImage(filteredImageData2, from: filteredImageData2.extent)
let imageForButton = UIImage(cgImage: filteredImageRef!)
originalImage.isHidden = true
imageToFilter.image = imageForButton
}
and the following code controls the button and what to change
if (Lb == "Brightness") {
sliderColor.tag = 0
sliderColor.minimumValue = -1.0
sliderColor.maximumValue = 1.0
sliderColor.value = 0.0
} else if (Lb == "Contrast") {
sliderColor.tag = 1
sliderColor.minimumValue = 0.0
sliderColor.maximumValue = 4.0
sliderColor.value = 1.0
}
I am aware of it is caused by the fact that I use originalImage everytime I change Brightness or Contrast. But if I change it to imageToFilter things get sloppy.
Any ideas?
As you have to keep reference and track for both filter key-value and apply both key filters at the same time while slider value changes.
Here is the demo code.
Note: As this is just a demo I used force unwrapping. You need to handle nil value.
class ViewController: UIViewController {
@IBOutlet weak var imageToFilter: UIImageView!
public var brightness : Float = 0.0
public var contrast : Float = 1.0
var filter: CIFilter? = CIFilter(name: "CIColorControls")
var originalImage = UIImage(named: "image_name")
override func viewDidLoad() {
super.viewDidLoad()
}
func applyImageFilter(for image: UIImage) -> UIImage? {
guard let sourceImage = CIImage(image: image),
let filter = self.filter else { return nil }
filter.setValue(sourceImage, forKey: kCIInputImageKey)
filter.setValue(self.contrast, forKey: kCIInputContrastKey)
filter.setValue(self.brightness, forKey: kCIInputBrightnessKey)
guard let output = filter.outputImage else { return nil }
guard let outputCGImage = CIContext().createCGImage(output, from: output.extent) else { return nil }
let filteredImage = UIImage(cgImage: outputCGImage, scale: image.scale, orientation: image.imageOrientation)
return filteredImage
}
@IBAction func sliderValueChangeAction(_ sender: UISlider) {
if sender.tag == 0 {
self.brightness = sender.value
} else if sender.tag == 1 {
self.contrast = sender.value
}
imageToFilter.image = self.applyImageFilter(for: originalImage!)
}
}