I have a CIImage that is 258x258. I apply a filter CIAreaAverage
to it, in order to get the green value of the average color of that image.
I am using this function to get that...
// channel 0,1,2 = red, green, blue
func averageColorOfImage (_ inputImage: CIImage, _ channel: Int) -> Double {
let extentVector = CIVector(x: inputImage.extent.origin.x, y: inputImage.extent.origin.y, z: inputImage.extent.size.width, w: inputImage.extent.size.height)
guard let filter = CIFilter(name: "CIAreaAverage", parameters: [kCIInputImageKey: inputImage, kCIInputExtentKey: extentVector]) else { return 0 }
guard let outputImage = Static.filter!.outputImage else { return 0 }
var bitmap = [UInt8](repeating: 0, count: 4)
let context = CIContext(options: [.workingColorSpace: kCFNull])
context.render(outputImage, toBitmap: &bitmap, rowBytes: 4, bounds: CGRect(x: 0, y: 0, width: 1, height: 1), format: .RGBA8, colorSpace: nil)
return Double(bitmap[channel]) / Double(255)
}
This runs relatively fast but I am trying to see if there is a way to get that color fast.
I remember that Core Image has this custom "core filter" stuff.
Is there a way to do get the green value of the average color of an image using custom core filter?
Here's what I'd do. (And actually do in one app to create a constant color CIImage of a specific size.
(1) Use CIAreaAverage
to get you signal pixel value just like you are doing. But instead of using the output of the green channel to create a bitmap (which I believe is the real issue you are facing)....
(2) Use if as input for CIConstantColorGenerator
, which will create an infinite sized color. Then....
(3) Use that output as input to CICrop
and crop it to the dimensions you want.
Essentially you end up with a "sized" CIImage of a constant color of whatever you wish. In the code below, replace my input for inputColor
with the green channel output of CIAreaAverage
and you'll get a 640x640 CIImage of it.
func createNewPalette() {
let filter = CIFilter(name: "CIConstantColorGenerator")
filter?.setValue(CIColor(red: 0.7, green: 0.4, blue: 0.4), forKey: "inputColor")
ciPalette = filter?.outputImage
let crop = CIFilter(name: "CICrop")
crop?.setValue(ciPalette, forKey: "inputImage")
crop?.setValue(CIVector(x: 0, y: 0, z: 640, w: 640), forKey: "inputRectangle")
ciPaletteOriginal = crop?.outputImage
}