According to Apple docs,
filters property of CALayer
is not supported in iOS
. As i used one of the apps which are applying CIFilter
to UIView
i.e. Splice, Video Editor Videoshow FX for Funimate and artisto. That's means we can apply CIFilter
to UIView
.
I have used SCRecorder
library and try to get this task done by SCPlayer
and SCFilterImageView
. But i am facing black screen issue when video is playing after apply CIFilter
. So kindly help me to complete this task so that i can apply CIFilter
to UIView
and also can change the filter by clicking on a UIButton.
The technically accurate answer is that a CIFilter
requires a CIImage
. You can turn a UIView
into a UIImage
and then convert that into a CIImage
, but all CoreImage filters that use an image for input (there are some that generate a new image) use a `CIImage for input and output.
- Please note that the origin for a
CIImage
is bottom left, not top left. Basically the Y axis is flipped.
- If you use CoreImage filters dynamically, learn to use a
GLKView
to render in - it uses the GPU where a UIImageView
uses the CPU.
- If you want to test out a filter, it's best to use an actual device. The simulator will give you very poor performance. I've seen a simple blur take nearly a minute where on a device it will be a fraction of a second!
Let's say you have a UIView
that you wish to apply a CIPhotoEffectMono to. The steps to do this would be:
- Convert the
UIView
into a CIImage
.
- Apply the filter, getting a
CIImage
as output.
- Use a
CIContext
to create a CGImage
and then convert that to a UIImage
.
Here's a UIView
extension that will convert the view and all it's subviews into a UIImage
:
extension UIView {
public func createImage() -> UIImage {
UIGraphicsBeginImageContextWithOptions(
CGSize(width: self.frame.width, height: self.frame.height), true, 1)
self.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
}
Converting a UIImage
into a CIImage
is one line of code:
let ciInput = CIImage(image: myView.createImage)
Here's a function that will apply the filter and return a UIImage
:
func convertImageToBW(image:UIImage) -> UIImage {
let filter = CIFilter(name: "CIPhotoEffectMono")
// convert UIImage to CIImage and set as input
let ciInput = CIImage(image: image)
filter?.setValue(ciInput, forKey: "inputImage")
// get output CIImage, render as CGImage first to retain proper UIImage scale
let ciOutput = filter?.outputImage
let ciContext = CIContext()
let cgImage = ciContext.createCGImage(ciOutput!, from: (ciOutput?.extent)!)
return UIImage(cgImage: cgImage!)
}