Search code examples
iosswiftimage-processinguiimagecore-image

Custom CIFilter - a CIColorCube - does not change the UIImage


I have made a custom CIColorCube filter, to turn an image in predetermined shades of gray (evenly spaced, black and white included) into a coloured image, with each shade turned into a different hue. The problem is - it either does not give any output or gives back the image completely unchanged. Here's the code of the filter:

class GreyToColoutrsFilterMaker{
static let FilterHaver = GreyToColoutrsFilterMaker()
let filter: CIFilter?
private init() {
    let size = Constants.SHADES_COUNT
    var cubeRGB = [Float]()
    for _ in 0 ..< size {
        for _ in 0 ..< size {
            for x in 0 ..< size {
                let red = CGFloat(x) / CGFloat(size-1)
                
                let hue = (1 - red) * 240 / 360
                let destColor = UIColor(hue: hue, saturation: 1, brightness: 1, alpha: 1)
                let colorParts = destColor.rgba
                cubeRGB.append(Float(colorParts.red))
                cubeRGB.append(Float(colorParts.green))
                cubeRGB.append(Float(colorParts.blue))
                cubeRGB.append(Float(colorParts.alpha))
            }
        }
    }
    let data = withUnsafeBytes(of: cubeRGB) { Data($0) }
    filter = CIFilter(name: "CIColorCube", parameters: ["inputCubeDimension": size, "inputCubeData": data])
}

And here's how I use it on the UIImage img:

if let filter = GreyToColoutrsFilterMaker.FilterHaver.filter{
            let ciImg = CIImage(image: img)
            filter.setDefaults()
            filter.setValue(ciImg, forKey: kCIInputImageKey)
            if let filteredImageData = filter.outputImage{
                let ciContext = CIContext(options: nil)
                if let filteredImageRef =   ciContext.createCGImage(filteredImageData, from: filteredImageData.extent){
                    img = UIImage(cgImage: filteredImageRef)
                }
            }
        }

If the line "filter.setDefaults()" is removed, then the code inside "if let filteredImageData = filter.outputImage" does not execute, showing that the filter did not return any data. But if the line is used, then the filter does not change the image in any way.


Solution

  • The problem was solved by changing the initing of data to:

    let data = cubeRGB.withUnsafeBufferPointer{ Data(buffer: $0) }
    

    After that, the filter started to work without setting defaults.