Search code examples
swiftswiftuicifilter

CIFilters seems to be broken on on iOS 14, Swift 5.x


iOS 14.5, Swift version 5.4.2 (swiftlang-1205.0.28.2 clang-1205.0.19.57)

Been trying to figure out why this code doesn't work? Are filters simply broken on the simulators on Xcode for this iOS/Swift version

private func generateMono(from image: UIImage) ->
UIImage {
  let mono = CIFilter(name: "CIColorMonochrome")
  mono!.setDefaults()
  mono!.setValue(image.cgImage, forKey: "inputImage")
  if let image = mono!.outputImage {
    if let image = context.createCGImage(image, from: image.extent) {
      return UIImage(cgImage: image)
    }
  }
  return UIImage(systemName: "circle") ?? UIImage()
}

I run this and get this error message, along with a system dump.

2021-07-13 09:17:45.910734+0200 GameV[32820:1828401] The filter  'CIPortraitEffectSpillCorrection' is not implemented in the bundle  at   /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/CoreImage/PortraitFilters.cifilter.
2021-07-13 09:17:45.911776+0200 GameV[32820:1828401] Metal GPU Frame Capture Enabled
2021-07-13 09:17:45.912087+0200 GameV[32820:1828401] Metal API Validation Enabled
2021-07-13 09:17:46.363938+0200 GameV[32820:1828401] -[__NSCFType imageByUnpremultiplyingAlpha]: unrecognized selector sent to instance 0x7f941bd15700
2021-07-13 09:17:46.377114+0200 GameV[32820:1828401] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFType imageByUnpremultiplyingAlpha]: unrecognized selector sent to instance 0x7f941bd15700'

Did I miss read/do something obviously wrong here? Calling it with this code?

import Foundation
import SpriteKit
import CoreImage.CIFilterBuiltins

class GameScene: SKScene {


  var img:UIImage!
  let context = CIContext(options: nil)

  static var shared = GameScene()

  override func didMove(to view: SKView) {

  backgroundColor = .white
  let mono = generateMono(from: uiImage!) as? UIImage

  let tex = SKTexture(image: mono!)
  let box = SKSpriteNode(texture: tex, size: CGSize(width: 64, height: 64))
  box.position = CGPoint(x: 128, y: 128)
  addChild(box)
  }
}

Thanks


Solution

  • I am using this UIImage extension on the SwiftUI project and its working fine:

    import CoreImage
    import CoreImage.CIFilterBuiltins
    
    extension UIImage {
        
        func applyFilter() -> UIImage {
            let beginImage = CIImage(image: self )
            let context = CIContext()
            
            let customFilter = CIFilter.colorMonochrome()
            customFilter.inputImage = beginImage
            customFilter.intensity = 1
            
            guard  let outputImage = customFilter.outputImage else { return UIImage() }
            
            // attempt to get a CGImage from our CIImage
            if let cgimg = context.createCGImage(outputImage, from: outputImage.extent) {
                let filteredImage = UIImage(cgImage: cgimg)
                return filteredImage
            }
            return UIImage()
        }
    }
    

    Usage:

    struct ContentView: View {
        var body: some View {
            Image(uiImage: (UIImage(named: "img3")?.applyFilter())!)
        }
    }