Will Chen
Will Chen

Reputation: 46

Simple Pass Thru cikernel Distorts Color Values

I've written a rgbToHSV cikernel to convert the pixels in images; however, it is not working correctly. I've narrowed it down to the fact that the RGB values are being distorted along the way.

To simplify my code, I've changed it to a simple pass through filter.

I've passed images of 1280 x 720 images that are all one color and then sampled pixel colors at position (100, 100) vbefore and after it passes through the cikernel.

Here are the results:

Red before:pixelColor :: rgba : 1.0 : 0.0 : 0.0 : 1.0 after: pixelColor :: rgba : 1.0 : 0.07450980392156863 : 0.0 : 1.0

Green before:pixelColor :: rgba : 0.0 : 1.0 : 0.0 : 1.0 after: pixelColor :: rgba : 0.0 : 0.984313725490196 : 0.0 : 1.0

Blue before:pixelColor :: rgba : 0.0 : 0.0 : 1.0 : 1.0 after: pixelColor :: rgba : 0.0 : 0.1803921568627451 : 1.0 : 1.0

As you can see Red and Green are slightly distorted, but Blue is massively distorted.

I have saved the output files and checked the colors and the filter is definitely altering the colors.

Any insight into why a simple passthrough is altering the colors is greatly appreciated.

Simplified Pass Thru Filter:

kernel vec4 rgbToHsv( __sample rgb) {
  return rgb;
}

Here's the CIFilter that uses the cikernel:

class RgbToHsvFilter: CIFilter {
  @objc dynamic var inputImage: CIImage?

  
  private lazy var kernel: CIColorKernel? = {
    guard let path = Bundle.main.path(forResource: "RgbToHsv", ofType: "cikernel"),
      let code = try? String(contentsOfFile: path) else { fatalError("Failed to load RgbToHsv.cikernel from bundle") }
    let kernel = CIColorKernel(source: code)
    return kernel
  }()

  override public var outputImage: CIImage! {
    get {
      if let inputImage = self.inputImage {
        
        let args = [inputImage as AnyObject]
        return self.kernel?.apply(extent: inputImage.extent, arguments: args)
      } else {
        return nil
      }
    }
  }
}

Calling the Filter

    let rgbToHsvFilter = RgbToHsvFilter()
    let currentCI = CIImage(cgImage: colorImage!.cgImage!)
    rgbToHsvFilter.setValue(currentCI, forKey: kCIInputImageKey)
    
    if let hsvImage = rgbToHsvFilter.outputImage {
      if let image = cgImage(from: hsvImage) {
        let newImage = UIImage(cgImage: image as! CGImage)
        
        
        let _ = newImage.getPixelColor(pos: pixelPoint)
     
        //UIImageWriteToSavedPhotosAlbum(newImage, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
      }
    }
  }

the getPixelColor method where the CGPoint is set to (100, 100). I thought the issue might be occurring here as a possible misrepresentation in the print statement of the color coming out, but I checked the actual output images and filter is altering the image colors:

  func getPixelColor(pos: CGPoint) -> UIColor {
    
    let pixelData = self.cgImage!.dataProvider!.data
    let data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)
    
    let pixelInfo: Int = ((Int(self.size.width) * Int(pos.y)) + Int(pos.x)) * 4
    
    let r = CGFloat(data[pixelInfo]) / CGFloat(255.0)
    let g = CGFloat(data[pixelInfo+1]) / CGFloat(255.0)
    let b = CGFloat(data[pixelInfo+2]) / CGFloat(255.0)
    let a = CGFloat(data[pixelInfo+3]) / CGFloat(255.0)
    
    print("pixelColor :: rgba : \(r) : \(g) : \(b) : \(a)")
    
    return UIColor(red: r, green: g, blue: b, alpha: a)
  }

and cgImage (edited):


  func cgImage(from ciImage: CIImage) -> CGImage? {
      let context = CIContext(options: nil)
      return context.createCGImage(ciImage, from: ciImage.extent)
  }

Upvotes: 0

Views: 207

Answers (1)

Will Chen
Will Chen

Reputation: 46

So the CIContext is not properly initialized in method cgImage.

Here's the corrected method:

  func cgImage(from ciImage: CIImage) -> CGImage? {
    let context = CIContext(options: [CIContextOption.workingColorSpace: kCFNull!])
    return context.createCGImage(ciImage, from: ciImage.extent, format: .RGBA8, colorSpace: CGColorSpace.init(name: CGColorSpace.sRGB)!)
  }

Upvotes: 0

Related Questions