How to apply Hald 3D Lut image filter in ios swift

98 Views Asked by At

We are working on an app that uses a LUT to apply a filter on the image. For filter, we are using CIFilter and Hald 3d Lut image.

we have tried different code available on the internet but does not work with Hald 3d lut image.

Problem

Output is not as expected.

Below is our code.

/// This function return cifilter
func colorCubeFilterFromLUT(filterName : String) -> CIFilter? {

        let x = filterName
        let filterImage = UIImage(named: x)!
        let size = 64

        let lutImage    = filterImage.cgImage
        let lutWidth    = lutImage!.width
        let lutHeight   = lutImage!.height
        let rowCount    = lutHeight / size
        let columnCount = lutWidth / size

        if ((lutWidth % size != 0) || (lutHeight % size != 0) || (rowCount * columnCount != size)) {
            NSLog("Invalid colorLUT %@", filterName);
            return nil
        }

        let bitmap  = getBytesFromImage(image: filterImage)!
        let floatSize = MemoryLayout<Float>.size

        let cubeData = UnsafeMutablePointer<Float>.allocate(capacity: size * size * size * 4 * floatSize)
        var z = 0
        var bitmapOffset = 0

        for _ in 0 ..< rowCount {
            for y in 0 ..< size {
                let tmp = z
                for _ in 0 ..< columnCount {
                    for x in 0 ..< size {

                        let alpha   = (Float(bitmap[bitmapOffset]) / 255.0)
                        let red     = (Float(bitmap[bitmapOffset+1]) / 255.0)
                        let green   = (Float(bitmap[bitmapOffset+2]) / 255.0)
                        let blue    = (Float(bitmap[bitmapOffset+3]) / 255.0)

                        let dataOffset = (z * size * size + y * size + x) * 4

                        cubeData[dataOffset + 3] = alpha
                        cubeData[dataOffset + 2] = red
                        cubeData[dataOffset + 1] = green
                        cubeData[dataOffset + 0] = blue
                        bitmapOffset += 4
                    }
                    z += 1
                }
                z = tmp
            }
            z += columnCount
        }

        
        
        let colorCubeData = NSData(bytesNoCopy: cubeData, length: size * size * size * 4 * floatSize, freeWhenDone: true)

        // create CIColorCube Filter
        let filter = CIFilter(name: "CIColorCube")
        filter?.setValue(colorCubeData, forKey: "inputCubeData")
        filter?.setValue(size, forKey: "inputCubeDimension")
        return filter
    }

/// This function return bytes from image
private func getBytesFromImage(image:UIImage?) -> [UInt8]? {
        var pixelValues: [UInt8]?
        if let imageRef = image?.cgImage {
            let width = Int(imageRef.width)
            let height = Int(imageRef.height)
            let bitsPerComponent = 8
            let bytesPerRow = width * 4
            let totalBytes = height * bytesPerRow

            let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Little.rawValue
            let colorSpace = CGColorSpaceCreateDeviceRGB()
            var intensities = [UInt8](repeating: 0, count: totalBytes)

            let contextRef = CGContext(data: &intensities, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo)
            contextRef?.draw(imageRef, in: CGRect(x: 0.0, y: 0.0, width: CGFloat(width), height: CGFloat(height)))
            pixelValues = intensities
        }
        return pixelValues!
    }

Example of hald Lut image

enter image description here

Actual Image

enter image description here

Output Image

enter image description here

0

There are 0 best solutions below