Reputation: 726
I am trying to create a CIFilter which converts the following QR Code:
To:
Here is the code that I'm using:
let invert = CIFilter(name: "CIColorInvert")
invert!.setDefaults()
invert!.setValue(ciImage, forKey: "inputImage")
let filter = CIFilter(name: "CIColorMatrix")
filter?.setDefaults()
filter?.setValue(invert?.outputImage, forKey: kCIInputImageKey)
let r = CGFloat(70.0/255.0)
let g = CGFloat(224.0/255.0)
let b = CGFloat(182.0/255.0)
filter?.setValue(CIVector(x: r, y: 0, z: 0, w: 0), forKey: "inputRVector")
filter?.setValue(CIVector(x: 0, y: g, z: 0, w: 0), forKey: "inputGVector")
filter?.setValue(CIVector(x: 0, y: 0, z: b, w: 0), forKey: "inputBVector")
filter?.setValue(CIVector(x: 0, y: 0, z: 0, w: 1), forKey: "inputAVector")
What the code does is first invert the normal QR code so that it's black on white, then it takes that image and applies a filter on it. The result of the code is this:
Which is not the color that I wanted. I would appreciate any help!
Thanks!
Upvotes: 2
Views: 1292
Reputation: 10682
I had to create a context without a colorspace, to get the color correct:
...
let ciContext = CIContext(options: [CIContextOption.outputColorSpace: NSNull(), CIContextOption.workingColorSpace: NSNull()])
let cgimg = ciContext.createCGImage(outputs!,from: output!.extent)
let processedImage = UIImage(cgImage: cgimg!)
(Swift 4)
Upvotes: 0
Reputation: 8986
You can use one of the following methods to achieve QR filter effect
using coreImage
.
Output:
Method 1: Using Custom Filter
Step1:
Create seperate class
to your custom kernel
as follow.
class CustomFilter: CIFilter {
var inputImage: CIImage?
override public var outputImage: CIImage! {
get {
if let inputImage = self.inputImage {
let args = [inputImage as AnyObject]
return createCustomKernel().apply(withExtent: inputImage.extent, arguments: args)
} else {
return nil
}
}
}
}
func createCustomKernel() -> CIColorKernel {
let kernelString =
"kernel vec4 chromaKey( __sample s) { \n" +
" vec4 newPixel = s.rgba;" +
" newPixel[0] = 0.0;" +
" newPixel[2] = newPixel[2] / 2.0;" +
" return newPixel;\n" +
"}"
return CIColorKernel(string: kernelString)!
}
In your ViewController
you can declare your custom filter as below.
var context = CIContext(options: nil)
func customQRFilter() {
let myInvertFilter = CIFilter(name: "CIColorInvert")
myInvertFilter!.setValue(CIImage(image: imageView.image!), forKey: kCIInputImageKey)
let output = myInvertFilter!.outputImage
let filter = CustomFilter()
filter.setValue(output, forKey: kCIInputImageKey)
// Get the filtered output image and return it
let outputImage = filter.outputImage!
let cgimg = context.createCGImage(outputImage,from: output!.extent)
let processedImage = UIImage(cgImage: cgimg!)
imageView.image = processedImage
}
Method 2: Using CIColorMatrix
filter.
func colorMatrixFilter() {
let myInvertFilter = CIFilter(name: "CIColorInvert")
myInvertFilter!.setValue(CIImage(image: imageView.image!), forKey: kCIInputImageKey)
let output = myInvertFilter!.outputImage
let filter = CIFilter(name: "CIColorMatrix")
filter?.setDefaults()
filter?.setValue(output, forKey: kCIInputImageKey)
let r = CGFloat(0.0)
let g = CGFloat(0.9)
let b = CGFloat(0.416)
filter?.setValue(CIVector(x: r, y: 0, z: 0, w: 0), forKey: "inputRVector")
filter?.setValue(CIVector(x: 0, y: g, z: 0, w: 0), forKey: "inputGVector")
filter?.setValue(CIVector(x: 0, y: 0, z: b, w: 0), forKey: "inputBVector")
filter?.setValue(CIVector(x: 0, y: 0, z: 0, w: 1), forKey: "inputAVector")
let outputs = filter?.outputImage
let cgimg = context.createCGImage(outputs!,from: output!.extent)
let processedImage = UIImage(cgImage: cgimg!)
imageView2.image = processedImage
}
Note: I advice you to use a colour Picker tool
to pick RGB value of any colour
you want.
Upvotes: 2