Почему drawInContext здесь так медленно? - PullRequest
1 голос
/ 24 марта 2011

Я использую класс QuartzImage в одном из демонстрационных проектов, и я пытался добиться простого рамочного дисплея, который в основном рисует изображение (320x480) каждые 1/10 секунды.Так что моя «частота кадров» должна быть 10 кадров в секунду.

В демонстрационном классе QuartzImage есть метод drawInContext, и в этом методе он в основном рисует CGImageRef с использованием CGContextDrawImage (), я измерил время, которое потребовалось для завершения, и занимает в среднем около ~ 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 мс кажется гораздо длиннее, чем следовало бы.

ОБНОВЛЕНИЯ Я попробовал предложение Брэда-Ларсона, но не увидел значительного улучшения производительности.

Итак, в обновленной версии у меня есть свой собственный класс

@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, вызывая мое обновлениеmethod

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 ]

2 голосов
/ 24 марта 2011

Использование Quartz для рисования изображений - это самый медленный способ сделать это из-за способа представления контента на экране.

В качестве шага вверх вы можете использовать UIImageView и поменяться местами.его хостинг изображения для каждого кадра.Еще более быстрый подход может заключаться в использовании CALayer и установке его свойства contents в CGImageRef, представляющем каждый кадр изображения.Возможно, вам придется отключить неявные анимации с помощью CATransaction, чтобы это было как можно быстрее.Если я не забуду, мне удалось получить изображения 320x480, которые можно рисовать со скоростью более 15 кадров в секунду на оригинальном iPhone, используя последний метод.

Наконец, для оптимальной производительности вы можете настроить дисплей OpenGL ES с прямоугольником, которыйзаполнить экран и предоставить изображения в виде текстур, которые будут отображаться в этом прямоугольнике.Для этого потребуется значительно больше кода, но это будет очень быстро.

0 голосов
/ 25 июня 2012

Я портировал свою игру с Android на iPhone, и я был шокирован производительностью Quartz. Тот же код на Android в 10 раз быстрее, чем на iPhone. У меня есть несколько DrawImages, и несколько линий рисования и Безье. Это так медленно на iOS, особенно на iPhone 4, где процессор пытается справиться с разрешением экрана сетчатки. Моя игра отлично работала на скорости 60 кадров в секунду почти на ЛЮБОМ устройстве Android.

Я пробовал несколько подходов для рендеринга (всегда избегая OpenGL). Я начал рисовать все на каждом кадре. Затем я начал рендерить как можно больше перед игровым циклом, используя UIImage. Теперь я пытаюсь пойти с CALayers. Хотя на iPhone 3GS и 4S я могу видеть стабильную скорость 60FPS на iPhone, максимум, что я могу получить на iPhone 4 - 45 FPS.

...