Reputation: 46
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
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