Reputation: 377
I want to access the average colour value of a specific area of CVPixelBuffer
that I get from ARFrame
in real-time. I managed to crop the image, use filter to calculate average colour and after converting to CGImage
I get the value from the pixel but unfortunately, it affects the performance of my app (FPS drops below 30fps). I think that the reason for that is using CGContext. Is there a way to access colour without converting CIImage
to CGImage
?
This is code that I'm using at the moment:
func fun() {
let croppVector = CIVector(cgRect: inputImageRect)
guard let filter = CIFilter(
name: "CIAreaAverage",
parameters: [kCIInputImageKey: image, kCIInputExtentKey: croppVector]
),
let outputImage = filter.outputImage,
let cgImage = context.createCGImage(
outputImage,
from: CGRect(x: 0, y: 0, width: 1, height: 1)
),
let dataProvider = cgImage.dataProvider,
let data = CFDataGetBytePtr(dataProvider.data) else { return nil }
let color = UIColor(
red: CGFloat(data[0]) / 255,
green: CGFloat(data[1]) / 255,
blue: CGFloat(data[2]) / 255,
alpha: CGFloat(data[3]) / 255
)
}
Upvotes: 4
Views: 2871
Reputation: 10418
I think there is not too much you can do here – reduction operations like this are expensive.
A few things you can try:
CIContext
to not perform any color management by setting the .workingColorSpace
and .outputColorSpace
options to NSNull()
.CGImage
. The context has the method render(_ image: CIImage, toBitmap data: UnsafeMutableRawPointer, rowBytes: Int, bounds: CGRect, format: CIFormat, colorSpace: CGColorSpace?)
you can use for that. Also pass nil
as color space here. You should be able to just pass a "pointer" to a simd_uchar4
var as data
here. rowBytes
would be 4 and format would be .BGRA8
in this case, I think.Upvotes: 2