Применить LUT (справочную таблицу) к изображению (Swift + Xcode) - PullRequest
1 голос
/ 06 марта 2019

Я хочу отредактировать изображение с фильтром LUT в качестве фильтра CIF для редактирования цвета изображения.К сожалению, я сталкиваюсь с преобразованием в Swift.Когда я выполняю код, processedImage приводит к nil в конце.

Вот мой код из моего ViewController:

Пример изображения: LUT.png

let nameLUT = "LUT.png"
let inputImage = CIImage(image: image)
let context = CIContext(options: nil)

if let currentFilter = CIFilter(name: nameLUT) {

    let beginImage = inputImage
    currentFilter.setValue(beginImage, forKey: kCIInputImageKey)
    currentFilter.setValue(0.5, forKey: kCIInputIntensityKey)

    if let output = currentFilter.outputImage {
        if let cgimg = context.createCGImage(output, from: output.extent) {
            let processedImage = UIImage(cgImage: cgimg)
        }
    }
}

Вот реализация функций CIFilter из моего расширения .swift:

extension CIFilter {
func colorCubeFilterFromLUT(name : String) -> CIFilter? {
    print("Filter: func colorCubeFilterFromLUT")

    let size = 64

    let name1 = "LUT2.png"
    let lutImage    = UIImage(named: name1)!.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)) {
        print("iInvalid colorLUT %@\(name1)")
        return nil
    }

    let bitmap  = CIFilter.getBytesFromImage(from: lutImage)
    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
}

class func getBytesFromImage(from image:CGImage?) -> [UInt8]?{
    print("Filter: func getBytesFromImage")
    var pixelValues: [UInt8]?
    if let imageRef = image {
        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!
}
...