因此,我在这个过程中有一个基本的绘图应用程序,它允许我绘制线条。我绘制到一个屏幕外的位图,然后在drawRect中呈现图像。它工作,但它的方式太慢,更新大约半秒后,你用你的手指绘制它。我将代码改编自本教程http://www.youtube.com/watch?v=UfWeMIL-Nu8&feature=relmfu,正如你在评论中看到的那样,人们也说它太慢了,但这个人没有回应。
那么,我如何才能加快速度呢?还是有更好的方法呢?任何指针都将不胜感激。
下面是我的DrawView.m中的代码。
-(id)initWithCoder:(NSCoder *)aDecoder {
if ((self=[super initWithCoder:aDecoder])) {
[self setUpBuffer];
}
return self;
}
-(void)setUpBuffer {
CGContextRelease(offscreenBuffer);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
offscreenBuffer = CGBitmapContextCreate(NULL, self.bounds.size.width, self.bounds.size.height, 8, self.bounds.size.width*4, colorSpace, kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorSpace);
CGContextTranslateCTM(offscreenBuffer, 0, self.bounds.size.height);
CGContextScaleCTM(offscreenBuffer, 1.0, -1.0);
}
-(void)drawToBuffer:(CGPoint)coordA :(CGPoint)coordB :(UIColor *)penColor :(int)thickness {
CGContextBeginPath(offscreenBuffer);
CGContextMoveToPoint(offscreenBuffer, coordA.x,coordA.y);
CGContextAddLineToPoint(offscreenBuffer, coordB.x,coordB.y);
CGContextSetLineWidth(offscreenBuffer, thickness);
CGContextSetLineCap(offscreenBuffer, kCGLineCapRound);
CGContextSetStrokeColorWithColor(offscreenBuffer, [penColor CGColor]);
CGContextStrokePath(offscreenBuffer);
}
- (void)drawRect:(CGRect)rect {
CGImageRef cgImage = CGBitmapContextCreateImage(offscreenBuffer);
UIImage *image =[[UIImage alloc] initWithCGImage:cgImage];
CGImageRelease(cgImage);
[image drawInRect:self.bounds];
}在模拟器上工作得很好,但在设备上就不行了,我想这与处理器的速度有关。
我用的是ARC。
发布于 2012-07-07 21:50:57
我试图修复您的代码,但是由于您似乎只发布了一半代码,我无法使其正常工作(Copy+pasting代码会导致许多错误,更不用说开始对其进行性能调优了)。
然而,有一些技巧可以用来极大地提高性能。
第一个可能是最值得注意的,是-setNeedsDisplayInRect:而不是-setNeedsDisplay。这将意味着它只重新绘制更改过的小矩形。对于1024*768*4像素的iPad 3来说,这是一个很大的工作量。将每帧减少到大约20*20或更少将极大地提高性能。
CGRect rect;
rect.origin.x = minimum(coordA.x, coordB.x) - (thickness * 0.5);
rect.size.width = (maximum(coordA.x, coordB.x) + (thickness * 0.5)) - rect.origin.x;
rect.origin.y = minimum(coordA.y, coordB.y) - (thickness * 0.5);
rect.size.height = (maximum(coordA.y, coordB.y) + (thickness * 0.5)) - rect.origin.y;
[self setNeedsDisplayInRect:rect];你可以做的另一个很大的改进是只绘制当前触摸的CGPath (你这样做了)。但是,您随后可以在绘图矩形中绘制保存/缓存图像。因此,每一帧都会重新绘制。一种更好的方法是让绘图视图是透明的,然后在后面使用UIImageView。UIImageView是在iOS上显示图像的最佳方式。
- DrawView (1 finger)
-drawRect:
- BackgroundView (the image of the old touches)
-self.image然后,绘图视图本身将只绘制当前触摸,仅绘制每次更改的部分。当用户举起手指时,您可以将其缓存到UIImage,将其绘制在当前背景/缓存UIImageView的图像上,并将imageView.image设置为新图像。
组合图像时的最后一步涉及将2个全屏图像绘制到离屏CGContext中,因此如果在主线程上完成将导致延迟,相反,这应该在后台线程中完成,然后将结果推回到主线程。
* touch starts *
- DrawView : draw current touch
* touch ends *
- 'background thread' : combine backgroundView.image and DrawView.drawRect
* thread finished *
send resulting UIImage to main queue and set backgroundView.image to it;
Clear DrawView's current path that is now in the cache;所有这些结合在一起,可以制作一个非常流畅的60fps绘图应用程序。然而,视图的更新速度并不像我们希望的那样快,所以当图形更快地移动时,绘图看起来是参差不齐的。这可以通过使用UIBezierPath而不是CGPaths来改进。
CGPoint lastPoint = [touch previousLocationInView:self];
CGPoint mid = midPoint(currentPoint, lastPoint);
-[UIBezierPath addQuadCurveToPoint:mid controlPoint:lastPoint];发布于 2012-07-02 16:41:48
它慢的原因是因为每一帧你都在创建一个位图,并试图绘制它。
你想要更好的方法吗?你看过the apple sample code for a drawing app on iOS吗?如果您不喜欢这样,那么您可以始终使用cocos2d,它提供了一个CCRenderTexture类(和示例代码)。
目前,您正在使用一种您已经知道效率不高的方法。
发布于 2012-07-04 06:41:27
使用这种方法,我想你应该考虑使用后台线程来处理所有繁重的图像渲染工作,而只使用主线程来进行UI更新,即。
__block UIImage *__imageBuffer = nil;
- (UIImage *)drawSomeImage
{
UIGraphicsBeginImageContext(self.bounds);
// draw image with CoreGraphics
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
- (void)updateUI
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// prepare image on background thread
__imageBuffer = [self drawSomeImage];
dispatch_async(dispatch_get_main_queue(), ^{
// calling drawRect with prepared image
[self setNeedsDisplay];
});
});
}
- (void)drawRect
{
// draw image buffer on current context
[__imageBuffer drawInRect:self.bounds];
}为了使优化更清晰,我省略了一些细节。更好的做法是切换到UIImageView。这样,您就可以摆脱非常重要的- (void)drawDect方法,并在图像准备就绪时更新UIImageView的图像属性。
https://stackoverflow.com/questions/11261450
复制相似问题