为什么drawInContext这么慢?

时间:2011-03-24 15:40:53

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

我在其中一个演示项目中使用了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

2 个答案:

答案 0 :(得分:2)

使用Quartz绘制图像是您执行此操作的最慢方式,因为内容呈现在屏幕上的方式。

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

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

答案 1 :(得分:0)

我一直在将我的游戏从Android移植到iPhone,我对Quartz的性能感到震惊。 Android上的相同代码比iPhone上快10倍。我有一些DrawImages,以及一堆画线和beziers。 iOS上的速度非常慢,特别是iPhone 4,处理器很难跟上视网膜的显示分辨率。 我的游戏几乎在任何Android设备上以60fps的速度完美运行。

我尝试了几种渲染方法(总是避免使用OpenGL)。我开始在每一帧画出一切。然后我通过使用UIImage来开始在游戏循环之前尽可能多地渲染。现在我想和CALayers一起去。虽然我可以在iPhone 3GS和4S上看到稳定的60FPS游戏,但我在iPhone 4上获得的最多只有45 FPS。