'How can I apply a filters to ONE image?
I'm beginner in Swift and make an app "Photo Editor". I have a problem. I need to apply a some filters to ONE image. I have four sliders(sepia, contrast, brightness, saturation ) and one image. I want to apply all this filters to my image.
I try to change my logic in code, but I have the same problem
@objc func sliderValueDidChange(sender: UISlider!)
if sender.tag == 0 {
let originalCIImage = CIImage(image: self.image!)
let value = sender.value
self.sepiaLabelValue.text = String(Int(value*100))
if let sepiaCIImage = sepiaFilter(originalCIImage!, intensity: Double(value)) {
filteredImage = sepiaCIImage
self.imageView.image = UIImage(ciImage: sepiaCIImage)
}
} else if sender.tag == 1 {
let originalCIImage = CIImage(image: self.image!)
let value = sender.value
self.brightnessValue.text = String(Int(value*100))
if let brightnessCIImage = brightnessFilter(originalCIImage!, intensity: Double(value)) {
filteredImage = brightnessCIImage
self.imageView.image = UIImage(ciImage:brightnessCIImage)
}
} else if sender.tag == 2 {
let originalCIImage = CIImage(image: self.image!)
let value = sender.value
self.contrastLabel.text = String(Int(value*100))
let contrastCIImage = contrastFilter(originalCIImage!, intensity: Double(value))
self.imageView.image = UIImage(ciImage:contrastCIImage!)
} else if sender.tag == 3 {
let originalCIImage = CIImage(image: self.image!)
let value = sender.value
self.saturationValue.text = String(Int(value*100))
let saturationCIImage = saturationFilter(originalCIImage!, intensity: Double(value))
self.imageView.image = UIImage(ciImage:saturationCIImage!)
}
}
func sepiaFilter(_ input: CIImage, intensity: Double) -> CIImage?
{
let sepiaFilter = CIFilter(name:"CISepiaTone")
sepiaFilter?.setValue(input, forKey: kCIInputImageKey)
sepiaFilter?.setValue(intensity, forKey: kCIInputIntensityKey)
return sepiaFilter?.outputImage
}
func brightnessFilter(_ input: CIImage, intensity: Double) -> CIImage? {
let brightnessFilter = CIFilter(name: "CIColorControls")
brightnessFilter?.setValue(input, forKey: kCIInputImageKey)
brightnessFilter?.setValue(intensity, forKey: kCIInputBrightnessKey)
return brightnessFilter?.outputImage
}
func contrastFilter(_ input: CIImage, intensity: Double) -> CIImage? {
let contrastFilter = CIFilter(name: "CIColorControls")
contrastFilter?.setValue(input, forKey: kCIInputImageKey)
contrastFilter?.setValue(intensity, forKey: kCIInputContrastKey)
return contrastFilter?.outputImage
}
func saturationFilter(_ input: CIImage, intensity: Double) -> CIImage? {
let saturationFilter = CIFilter(name: "CIColorControls")
saturationFilter?.setValue(input, forKey: kCIInputImageKey)
saturationFilter?.setValue(intensity, forKey: kCIInputSaturationKey)
return saturationFilter?.outputImage
}
When I apply first filter and then next filter, the value of first filter is established to begin state. How can I apply all filters to my image?
Solution 1:[1]
As Gigi said, the trick is to always apply both filters to the image when a value changed. This should do the trick:
let colorControlsFilter = CIFilter(name: "CIColorControls")!
let sepiaFilter = CIFilter(name:"CISepiaTone")!
@objc func sliderValueDidChange(sender: UISlider!) {
switch sender.tag {
case 0:
let value = sender.value
self.sepiaLabelValue.text = String(Int(value*100))
self.sepiaFilter.setValue(value, forKey: kCIInputIntensityKey)
case 1:
let value = sender.value
self.brightnessValue.text = String(Int(value*100))
self.colorControlsFilter.setValue(value, forKey: kCIInputBrightnessKey)
case 2:
let value = sender.value
self.contrastLabel.text = String(Int(value*100))
self.colorControlsFilter.setValue(value, forKey: kCIInputContrastKey)
case 3:
let value = sender.value
self.saturationValue.text = String(Int(value*100))
self.colorControlsFilter.setValue(value, forKey: kCIInputSaturationKey)
default: pass
}
self.updateImage()
}
func updateImage() {
let originalCIImage = CIImage(image: self.image!)
// first apply color controls (contrast, brightness, saturation), then sepia
self.colorControlsFilter.setValue(originalCIImage, forKey: kCIInputImageKey)
self.sepiaFilter.setValue(self.colorControlsFilter.outputImage, forKey: kCIInputImageKey)
self.imageView.image = UIImage(ciImage: self.sepiaFilter.outputImage!)
}
Solution 2:[2]
let context = CIContext(options: nil)
if let currentFilter = CIFilter(name: "CISepiaTone") {
let beginImage = CIImage(image: image!)
currentFilter.setValue(beginImage, forKey: kCIInputImageKey)
if let output = currentFilter.outputImage {
if let cgimg = context.createCGImage(output, from: output.extent) {
filteredImage = UIImage(cgImage: cgimg)
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Frank Schlegel |
Solution 2 | Balasingam Sanjeevan |