将 CIImage 转换为 CGImage 太慢
Converting CIImage to CGImage too slow
我需要将 CIImage
转换为 CGImage
。这是我目前使用的代码:
CGImageRef img = [myContext createCGImage:ciImage fromRect:[ciImage extent]];
但是他的代码行对于常规尺寸的图像来说非常慢。我可以正确使用它的速度要慢得多。是否有另一种更快的方法将这些 CIImages
转换为 CGImages
?
最后我用Core Graphics
把CGImages
画成了CGContext
。如果有一种方法可以直接将 CIImages
绘制到 CGContext
,我认为这也应该更快。这可能吗?
谢谢
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.
这意味着您可能已经应用(或者更好请求应用)到您的 CIImage
的任何过滤实际上不会发生,直到您渲染图像,这在您的情况下,发生在您创建 CGImageRef
时。这可能是您遇到减速的原因。
也就是说,在 CIImage
上过滤通常是一个非常快的过程,因此根据您的图像大小,您应该给我们您对慢的定义。
最后,为了确保瓶颈确实存在于您认为的位置,您应该 profile your application 使用 Instruments。
编辑
我刚刚尝试构建一个示例项目,通过应用 CIColorMap
滤色器来过滤来自 iPad3 上设备相机 (960x540) 的图像流,我已经完成了60 帧/秒(~16 毫秒)。
根据您的应用程序,您将通过重用 CIContext
、ColorMapFilter
、inputGradientImage
(如果它不随时间变化)和仅更新来获得更好的性能每次迭代 inputImage
。
例如,您将调用 prepareFrameFiltering
一次,然后在您要处理的每一帧上重复调用 applyFilterToFrame:
。
@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);
}
渲染CI图像的最快方法是渲染到 EAGLContext。
将 CI 图像渲染到 CGContext 中的性能不佳,因为 CI 在 GPU 上工作,但 CG 是 CPU 渲染器。 CI 必须将其结果从 GPU 读回 CPU,以便 CG 可以渲染它。
注意:当图像小于 4K 时调用 createCGImage: 时会发生此回读。如果图像较大,则在调用 CGContextDrawImage 时会发生这种情况。
我需要将 CIImage
转换为 CGImage
。这是我目前使用的代码:
CGImageRef img = [myContext createCGImage:ciImage fromRect:[ciImage extent]];
但是他的代码行对于常规尺寸的图像来说非常慢。我可以正确使用它的速度要慢得多。是否有另一种更快的方法将这些 CIImages
转换为 CGImages
?
最后我用Core Graphics
把CGImages
画成了CGContext
。如果有一种方法可以直接将 CIImages
绘制到 CGContext
,我认为这也应该更快。这可能吗?
谢谢
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.
这意味着您可能已经应用(或者更好请求应用)到您的 CIImage
的任何过滤实际上不会发生,直到您渲染图像,这在您的情况下,发生在您创建 CGImageRef
时。这可能是您遇到减速的原因。
也就是说,在 CIImage
上过滤通常是一个非常快的过程,因此根据您的图像大小,您应该给我们您对慢的定义。
最后,为了确保瓶颈确实存在于您认为的位置,您应该 profile your application 使用 Instruments。
编辑
我刚刚尝试构建一个示例项目,通过应用 CIColorMap
滤色器来过滤来自 iPad3 上设备相机 (960x540) 的图像流,我已经完成了60 帧/秒(~16 毫秒)。
根据您的应用程序,您将通过重用 CIContext
、ColorMapFilter
、inputGradientImage
(如果它不随时间变化)和仅更新来获得更好的性能每次迭代 inputImage
。
例如,您将调用 prepareFrameFiltering
一次,然后在您要处理的每一帧上重复调用 applyFilterToFrame:
。
@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);
}
渲染CI图像的最快方法是渲染到 EAGLContext。
将 CI 图像渲染到 CGContext 中的性能不佳,因为 CI 在 GPU 上工作,但 CG 是 CPU 渲染器。 CI 必须将其结果从 GPU 读回 CPU,以便 CG 可以渲染它。
注意:当图像小于 4K 时调用 createCGImage: 时会发生此回读。如果图像较大,则在调用 CGContextDrawImage 时会发生这种情况。