简体   繁体   中英

How to change Brightness and Contrast with one UISlider with Swift

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?

You are creating a new CIFilter every time the value changes. The new filter doesn't know the previous setting. So the easiest way to solve this is to only create one CIFilter instance outside of the method (for instance as an instance variable) and only change the filter's brightness or contrast value in your slider callback. It should remember previous values this way.

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!)
    }
}

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