관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] 위젯 iOS 17 saturation 버그 (dimmed효과, 딤드효과, 채도, saturation, CIColorControls, kCIInputSaturationKey, CIFilter) 본문

iOS 응용 (swift)

[iOS - swift] 위젯 iOS 17 saturation 버그 (dimmed효과, 딤드효과, 채도, saturation, CIColorControls, kCIInputSaturationKey, CIFilter)

jake-kim 2024. 5. 17. 01:36

Saturation (채도)

  • 가끔 dimmed 효과를 주기 위해서 일반 이미지에 CIFilter를 사용하여 채도를 낮추는 코드
    • (하지만 iOS 17에서 위젯 관련 버그가 존재)

ex) CIFilter를 활용한 채도를 변화시키는 메소드

// 출처: https://stackoverflow.com/questions/62040870/how-can-we-decrease-saturation-of-uiview-in-swift

extension UIImage {

    func withSaturationAdjustment(byVal: CGFloat) -> UIImage {
        guard let cgImage = self.cgImage else { return self }
        guard let filter = CIFilter(name: "CIColorControls") else { return self }
        filter.setValue(CIImage(cgImage: cgImage), forKey: kCIInputImageKey)
        filter.setValue(byVal, forKey: kCIInputSaturationKey)
        guard let result = filter.value(forKey: kCIOutputImageKey) as? CIImage else { return self }
        guard let newCgImage = CIContext(options: nil).createCGImage(result, from: result.extent) else { return self }
        return UIImage(cgImage: newCgImage, scale: UIScreen.main.scale, orientation: imageOrientation)
    }
}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        let image = UIImage(named: "b")
        view.addSubview(UIImageView(image: image))

        let imageView2 = UIImageView(image: image?.withSaturationAdjustment(byVal: 0.3))
        imageView2.frame.origin.y = 300
        view.addSubview(imageView2)

    }


}
  • iOS 17에서 위 메소드를 사용하면 앱에서는 잘 보이지만 위젯에서 안보이는 이슈가 존재

(아래처럼 앱에서는 잘 표출)

saturation 값 1 saturation 값 0.1

 

(위젯에서는 특정 이미지에 대해서 CIFilter로 채도를 낮추면 위젯에서 투명색으로 보이는 이슈가 존재)

  • 위젯에 채도를 낮추는 이미지를 표출할 때는 이미지 자체를 filter해서 관리하지 말고, SwiftUI에서 제공하는 saturation(_:)을 사용할 것

https://developer.apple.com/documentation/swiftui/view/saturation(_:)

Image(uiImage: image)
    .imageScale(.large)
    .foregroundStyle(.tint)
    .saturation(0.01) // <-
  • 이렇게 사용하면 좋은점에 위 버그를 막기위한 것도 있지만, CIFilter를 사용하면 모든 픽셀에 하나하나 접근하여 픽셀값을 변경해주는 내부 GPU 자원이 들기 때문제 그것보다 가벼운 SwiftUI의 saturation(_:)을 사용하는 것이 성능면에서도 유리

* 위젯 사용 방법은 위젯 사용 방법 포스팅 글 참고

* 참고

- https://developer.apple.com/documentation/swiftui/view/saturation(_:)

- https://stackoverflow.com/questions/62040870/how-can-we-decrease-saturation-of-uiview-in-swift

Comments