xcode 将 CIImage 转换为 CGImage 太慢

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28210847/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 06:33:43  来源:igfitidea点击:

Converting CIImage to CGImage too slow

iosxcodecore-graphicscgimageciimage

提问by Laurens

I need to convert a CIImageto a CGImage. This is the code I am currently using:

我需要将 a 转换CIImage为 a CGImage。这是我目前使用的代码:

CGImageRef img = [myContext createCGImage:ciImage fromRect:[ciImage extent]];

But his line of code is very slow for images with a regular size. Much to slow that I can use it properly. Is there another faster method to convert these CIImagesto CGImages?

但是对于常规尺寸的图像,他的代码行非常慢。很慢,我可以正确使用它。是否有另一种更快的方法将这些转换CIImagesCGImages

In the end I use Core Graphicsto draw the CGImagesto a CGContext. If there is a way to directly draw CIImagesto a CGContexti think that should also be faster. Is this possible?

最后,我使用Core Graphics将 绘制CGImagesCGContext. 如果有一种方法可以直接绘制CIImages到 aCGContext我认为也应该更快。这可能吗?

thanks

谢谢

回答by Tomas Camin

From the CIImage documentation:

CIImage 文档

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 对象具有与之关联的图像数据,但它不是图像。您可以将 CIImage 对象视为图像“配方”。CIImage 对象具有生成图像所需的所有信息,但 Core Image 在被告知之前不会实际渲染图像。这种“懒惰的评估”方法可以让 Core Image 尽可能高效地运行。

This means that any filtering you may have applied (or better requested to apply) to your CIImagewon'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.

这意味着您可能已应用(或更好地要求应用)的任何过滤CIImage在您渲染图像之前实际上不会发生,在您的情况下,当您创建CGImageRef. 这可能就是您遇到减速的原因。

That said, filtering on CIImageis generally a really fast process so based on your image size you should give us your definition of slow.

也就是说,过滤CIImage通常是一个非常快的过程,因此根据您的图像大小,您应该给我们您对慢的定义。

Finally to make sure the bottleneck is really where you think it is you should profile your applicationby using Instruments.

最后,为了确保瓶颈确实在您认为的位置,您应该使用 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 CIColorMapcolor filter and I'm getting over 60fps (~16ms).

我刚刚尝试构建一个示例项目,该项目通过应用CIColorMap滤色器来过滤来自 iPad3 上的设备摄像头 (960x540) 的图像流,并且速度超过 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 inputImageon every iteration.

根据您的应用程序,您可以通过重用CIContextColorMapFilterinputGradientImage(如果它不随时间变化)并inputImage在每次迭代时仅更新,从而获得更好的性能。

For example you would call prepareFrameFilteringonce and then repeatably call applyFilterToFrame:on every frame you want to process.

例如,您将调用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);
}

回答by David Hayward

The fastest way to render a CIImage is to render into a EAGLContext.

渲染 CIImage 的最快方法是渲染到 EAGLContext 中。

Rendering a CIImage into a CGContext is not as performant because CI works on the GPU but CG is a CPU renderer. CI must read its results back from the GPU to the CPU so that CG can render it.

将 CIImage 渲染到 CGContext 的性能不高,因为 CI 在 GPU 上工作,而 CG 是 CPU 渲染器。CI 必须将其结果从 GPU 读回 CPU,以便 CG 可以渲染它。

Note: This read-back will happen when createCGImage: is called if the image is smaller than 4K. It will happen when CGContextDrawImage is called if the image is larger.

注意:如果图像小于 4K,调用 createCGImage: 时会发生这种回读。如果图像较大,则在调用 CGContextDrawImage 时会发生这种情况。