【问题标题】:Why is drawInContext so slow here?为什么drawInContext在这里这么慢?
【发布时间】:2012-06-26 02:41:36
【问题描述】:

我在一个演示项目中使用 QuartzImage 类,我想要实现的是一个简单的帧显示单元,它基本上每 1/10 秒绘制一个图像 (320x480)。所以我的“帧速率”应该是每秒 10 帧。

在 QuartzImage 演示类中,有一个 drawInContext 方法,在这个方法中,它基本上是使用 CGContextDrawImage() 绘制一个 CGImageRef,我测量了完成完成所需的时间,平均大约需要 200 毫秒。

2011-03-24 11:12:33.350 QuartzDemo[3159:207] drawInContext took 0.19105 secs

-(void)drawInContext:(CGContextRef)context
{
    CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
    CGRect imageRect;
    imageRect.origin = CGPointMake(0.0, 0.0);
    imageRect.size = CGSizeMake(320.0f, 480.0f);
    CGContextDrawImage(context, imageRect, image);
    CFAbsoluteTime end = CFAbsoluteTimeGetCurrent();
    NSLog(@"drawInContext took %2.5f secs", end - start);
}

谁能解释为什么要花这么长时间以及是否有其他方法可以提高性能? 200 毫秒似乎比应该花费的时间长得多。

更新 我尝试了@Brad-Larson 的建议,但没有看到很多性能改进。

所以更新的版本是我有自己的课

@interface FDisplay : UIView {
    CALayer *imgFrame;
    NSInteger frameNum;
}
end

所以在我的类实现中

- (id)initWithFrame:(CGRect)frame {
    ............

    frameNum = 0;
    NSString *file = [NSString stringWithFormat:@"frame%d",frameNum];
    UIImage *img = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:file ofType:@"jpg"]];
    imgFrame = [CALayer layer];
    CGFloat     nativeWidth = CGImageGetWidth(img.CGImage);
    CGFloat     nativeHeight = CGImageGetHeight(img.CGImage);
    CGRect      startFrame = CGRectMake(0.0, 0.0, nativeWidth, nativeHeight);
    imgFrame.contents = (id)img.CGImage;
    imgFrame.frame = startFrame;
    CALayer *l = [self layer];
    [l addSublayer:imgFrame];
}

我有一个 NSTimer 在 0.1f 调用我的刷新方法

NSString *file = [NSString stringWithFormat:@"frame%d",frameNum];
UIImage *img = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:file ofType:@"jpg"]];
frameNum++;
if (frameNum>100) 
    frameNum = 0;

[CATransaction begin]; 
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; 
[imgFrame setContents:(id)img.CGImage];
[CATransaction commit];
end = CFAbsoluteTimeGetCurrent();
NSLog(@"(%d)refresh took %2.5f secs", [[self subviews] count],end - start);

我认为我做的一切都是正确的,但帧速率仍然很低,

refresh took 0.15960 secs

【问题讨论】:

    标签: iphone objective-c ios4 core-animation quartz-graphics


    【解决方案1】:

    由于内容呈现在屏幕上的方式,使用 Quartz 绘制图像是最慢的方法。

    作为一个步骤,您可以使用 UIImageView 并为每个帧换出其托管图像。更快的方法可能是使用 CALayer 并将其 contents 属性设置为代表每个图像帧的 CGImageRef。您可能需要使用 CATransaction 禁用隐式动画,以使其尽可能快。如果我记得的话,我能够使用后一种方法在原始 iPhone 上以超过 15 FPS 的速度绘制 320x480 图像。

    最后,为了获得最佳性能,您可以使用填充屏幕的矩形设置 OpenGL ES 显示,并将图像作为要在该矩形上渲染的纹理提供。这将需要更多的代码,但速度会非常快。

    【讨论】:

    • @Brad-Larson 在 iPhone4 和新一代设备上是 15 FPS 吗?我运行的测试使用的是旧的 3G iPhone。
    • @Objective-Dude - 正如我所说,15+ FPS 是在原始型号 iPhone 上(在 iPhone 3G 之前)。 iPhone 3G S 之后的新设备当然要快得多。
    • @Brad-Larson 谢谢,由于某种原因我错过了。并禁用隐式动画,你的意思是在这个答案中这样做 [link]stackoverflow.com/questions/2244147/…
    • @Objective-Dude - 是的,这是一种方式。另一种方法是使用[CATransaction begin]; [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];[CATransaction commit]; 包装对contents 的任何更改。您链接到的方式可能更适合此应用程序。
    • @Objective-Dude - 从磁盘加载这些图像中的每一个都将是一个缓慢的操作,将 UIImage 转换为 CGImageRef 也是如此。其中任何一个都可能会减慢速度,而不是您的实际绘图。尝试从磁盘上的 JPEG 加载直接 CGImage,如下所述:stackoverflow.com/questions/3550201/…。此外,使用 Time Profiler 工具在此代码中找到您的确切热点。
    【解决方案2】:

    我一直在将我的游戏从 Android 移植到 iPhone,我对 Quartz 的性能感到震惊。 Android 上的相同代码比 iPhone 快 10 倍。我有一些 DrawImages,还有一堆线条画和贝塞尔曲线。 它在 iOS 上太慢了,尤其是 iPhone 4,处理器难以跟上视网膜显示分辨率。 我的游戏在几乎任何安卓设备上都能以 60fps 的速度完美运行。

    我尝试了几种渲染方法(总是避免使用 OpenGL)。我开始在每一帧画出所有的东西。然后我开始在游戏循环之前尽可能多地使用 UIImage 进行渲染。现在我正在尝试使用 CALayers。虽然我在 iPhone 3GS 和 4S 上可以看到稳定的 60FPS 游戏,但我在 iPhone 4 上最多可以达到 45 FPS。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-03
      • 1970-01-01
      • 1970-01-01
      • 2011-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多