From the CIImage documentation:
Although a CIImage object has image data associated with it, it is not
an image. You can think of a CIImage object as an image “recipe.” A
CIImage object has all the information necessary to produce an image,
but Core Image doesn’t actually render an image until it is told to do
so. This “lazy evaluation” method allows Core Image to operate as
efficiently as possible.
This means that any filtering you may have applied (or better requested to apply) to your CIImage
won't actually occur until you render the image, which in your case happens when you create the CGImageRef
. That's probably the reason you're experiencing the slow down.
That said, filtering on CIImage
is generally a really fast process so based on your image size you should give us your definition of slow.
Finally to make sure the bottleneck is really where you think it is you should profile your application by using Instruments.
Edit
I've just tried building a sample project that filters an image stream coming from the device camera (960x540) on an iPad3 by applying the CIColorMap
color filter and I'm getting over 60fps (~16ms).
Depending on your application you'll get better performances by reusing the CIContext
, the ColorMapFilter
, the inputGradientImage
(if it doesn't change over time) and updating only the inputImage
on every iteration.
For example you would call prepareFrameFiltering
once and then repeatably call applyFilterToFrame:
on every frame you want to process.
@property (nonatomic, strong) CIContext *context;
@property (nonatomic, strong) CIFilter *colorMapFilter;
- (void)prepareFrameFiltering {
self.context = [CIContext contextWithOptions:nil];
CIImage *colorMap = [CIImage imageWithCGImage:[UIImage imageNamed:@"gradient.jpg"].CGImage];
self.colorMapFilter = [CIFilter filterWithName:@"CIColorMap"];
[self.colorMapFilter setValue:colorMap forKey:@"inputGradientImage"];
}
- (void)applyFilterToFrame:(CIImage *)ciFrame {
// filter
[self.colorMapFilter setValue:ciFrame forKey:@"inputImage"];
CIImage *ciImageResult = [self.colorMapFilter valueForKey: @"outputImage"];
CGImageRef ref = [self.context createCGImage:ciImageResult fromRect:ciFrame.extent];
// do whatever you need
CGImageRelease(ref);
}