Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using CIColorMatrix filter in Swift

The following Swift func is supposed to tint a greyscale image 'greyImage' using specified 'tintColor':

import UIKit

func colorizeImage(greyImage : UIImage, tintColor : UIColor) -> UIImage? {

    let colorMatrixFilter = CIFilter(name: "CIColorMatrix")

    var r:CGFloat = 0
    var g:CGFloat = 0
    var b:CGFloat = 0
    var a:CGFloat = 0
    tintColor.getRed(&r, green:&g, blue:&b, alpha:&a)

    colorMatrixFilter.setDefaults()
    colorMatrixFilter.setValue(greyImage, forKey:"inputImage") //kCIInputImageKey)
    colorMatrixFilter.setValue(CIVector(x:r, y:0, z:0, w:0), forKey:"inputRVector")
    colorMatrixFilter.setValue(CIVector(x:0, y:g, z:0, w:0), forKey:"inputGVector")
    colorMatrixFilter.setValue(CIVector(x:0, y:0, z:b, w:0), forKey:"inputBVector")
    colorMatrixFilter.setValue(CIVector(x:0, y:0, z:0, w:a), forKey:"inputAVector")

    if let ciImage =  colorMatrixFilter.outputImage {
        return UIImage(CIImage: ciImage);
    }

    return nil;
}

The colour is UIColor.orangeColor() (r=1,g=0.5,b=0,a=1), the greyscale image is OK since it is displayed all right when fed to ImageView.

It looks like all the necessary keys are supplied and the key assignments go smoothly (BTW does the filter check the validity of keys, or takes everything?), however reading 'outputImage' property produces SIGABRT and the following console message:

2015-05-02 13:04:07.319 MyApp[436:8241] -[UIImage _internalRepresentation]: unrecognized selector sent to instance 0x7fd5b3ca82b0
2015-05-02 13:04:07.629 MyApp[436:8241] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIImage _internalRepresentation]: unrecognized selector sent to instance 0x7fd5b3ca82b0'
*** First throw call stack:
(
    0   CoreFoundation                      0x00000001087abf35 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x000000010a56cbb7 objc_exception_throw + 45
    2   CoreFoundation                      0x00000001087b304d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
    3   CoreFoundation                      0x000000010870b27c ___forwarding___ + 988
    4   CoreFoundation                      0x000000010870ae18 _CF_forwarding_prep_0 + 120
    5   CoreImage                           0x0000000108bd30fe -[CIColorMatrix outputImage] + 885
    6   MyApp                            0x00000001085c182d _TF8MyApp13colorizeImageFTCSo7UIImageCSo7UIColor_GSqS0__ + 4733
    7   MyApp                            0x00000001085c2b59 
like image 625
cyanide Avatar asked Dec 25 '22 19:12

cyanide


1 Answers

The problem there is that CIColorMatrix is expecting the parameter inputImage which should be CIImage object and not a UIImage (greyImage).

update: Swift 3 or later

extension UIColor {
    var rgba: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat)? {
        var (r,g,b,a): (CGFloat,CGFloat,CGFloat,CGFloat) = (0,0,0,0)
        return getRed(&r, green: &g, blue: &b, alpha: &a) ? (r,g,b,a) : nil
    }
}

extension CIImage {
    var image: UIImage { .init(ciImage: self) }
    func colorized(with color: UIColor) -> CIImage? {
        guard
            let (r,g,b,a) = color.rgba,
            let colorMatrix = CIFilter(name: "CIColorMatrix",
                parameters: ["inputImage":  self,
                             "inputRVector": CIVector(x: r, y: 0, z: 0, w: 0),
                             "inputGVector": CIVector(x: 0, y: g, z: 0, w: 0),
                             "inputBVector": CIVector(x: 0, y: 0, z: b, w: 0),
                             "inputAVector": CIVector(x: 0, y: 0, z: 0, w: a)])
        else { return nil }
        return colorMatrix.outputImage
    }
}

extension UIImage {
    var coreImage: CIImage? { CIImage(image: self) }
    func colorized(with color: UIColor) -> UIImage? {
        coreImage?.colorized(with: color)?.image
    }
}

Playground testing:

let profilePicture = UIImage(data: try! Data(contentsOf: URL(string: "http://i.stack.imgur.com/Xs4RX.jpg")!))!
profilePicture.colorized(with: .orange)

enter image description here

like image 194
Leo Dabus Avatar answered Jan 14 '23 15:01

Leo Dabus